0

[解決済み] 同様の C コードが行うことを行うために、独自のアセンブリ コードを実行しようとしています。

main()
{
scanf("%d",&integer_var); // here must be the address of the integer_var
printf("Your Value is:%d",integer_var);
}

これは C で書かれているので、extern 関数を使用して Linux で NASM を使用しています。scanf と printf を実行し、最初に nasm でコンパイルし、次に gcc でコンパイルします。これが私のコードです(正しくありません:D)

SECTION .text

argstr: db "%d",10,0
str: db "Your value is:%d",10,0

extern printf
extern scanf

SECTION .data

global main

main:
        push ebp
    mov esp,ebp
    sub esp, 0x10 ;ok integer right?
    mov [ebp-0x4],0x0 ;just put 0 number on our integer variable
    mov eax,(ebp-0x4) ;here i don't know how to push the address of ebp-0x4
    push ecx ;first push is last argument so here's our address to scanf
    push argstr ;just the string format
    call scanf ;call that to input something
    ;I have no idea how to do this
    ;but if i don't do this i get an error
    ;because the scanf won't clear the arguments on stack
    ;and what scanf can't return
    pop edx ;maybe help here? but it works fine
    pop edx
    push [-0x4(ebp)] ;i want the value of our var :D
    push str
    call printf
    pop edx ;clear the stack to avoid "segment fault" or something similar
    pop edx
    mov esp,ebp
    pop ebp
    ret ;the end :(

コンパイラ エラー:

a.asm:18: error: invalid operand type
a.asm:28: error: parser: expecting ]

別のこと: ところで、この場合、スタックを揃える必要がありますか?

みんなありがとう !:)

EDITはプログラム全体を解決しました! 少なくとも、printf を使用して変数を出力できます。scanf は後で行い、最後の結果をここで共有します。

SECTION .text
str: db "Value is:%d",10,0
extern printf
SECTION .data
global main
main:
        push ebp                ;the main function starts here.
        mov ebp,esp
        ;
        sub esp,4               ;we need 4bytes of space for the integer
        and esp,0xfffffff0      ;align the stack 
        mov [esp-4], dword 0xff ;move the value 0xff to our var
        mov eax,[esp-4]         ;move our variable value to the eax
        push eax                ;second argument of printf
        push str                ;first argument of printf
        call printf             ;printf
        ;
        add esp,16              ;this add to the stack pointer what we pushed basicly
        mov ebp,esp             ;if we don't do add 16 to esp it shows us
        pop ebp                 ;a segment fault cuz ret doesnt pop saved ebp
        ret                     ;of who whatever called this program :)
4

1 に答える 1

1

EBP-4アドレスをにロードするにEAXは、 を使用しますlea eax, [ebp-4]。(これは、アドレスをプッシュすることと同じではありません。)

メモリ位置EBP-4に値をプッシュするには、動作push dword [ebp-4]するはずです。

次に、いずれかの のオペランド サイズも指定する必要がありmovますmov [ebp-4], dword 0x0

これらは現在のアセンブラ エラーを修正し、プログラムをコンパイルしますが、実行を妨げる可能性のあるエラーが他にもいくつかあります。

あなたに近い実用的な試みは次のとおりです。

;note the sections, the string literals are better in .rodata
;all code goes in .text

SECTION .rodata 
;no newline after scanf string
argstr: db "%d",0 
str: db "Your value is: %d",10,0

SECTION .text 
extern printf 
extern scanf 
global main

main:
    push ebp
    mov ebp,esp ;move esp to ebp, NOT other way round!
    sub esp, 4  ;4 bytes are enough for the local variable
                ;there are NO alignment requirements for this program

    lea eax,[ebp-4]
    push eax
    push dword argstr

    call scanf

    add esp, 8  ;since we don't actually need the popped values
                ;we can increment esp instead of two pop edx

    push dword [ebp-4]
    push dword str

    call printf

    add esp, 8

    mov esp,ebp
    pop ebp
    ret
于 2013-10-07T22:36:40.533 に答える