Вызов _printf в цикле сборки, вывод только один раз - PullRequest
0 голосов
/ 25 марта 2012

Я изучаю ассемблер и у меня есть очень простой цикл здесь

segment .data
    msg: db '%d',10,0

segment .text

    global  _asm_main
    extern _printf

_asm_main:

    push DWORD 5 ; Should loop 5 times
    call dump_stack
    add esp,4

    ret

dump_stack:
    push ebp
    mov ebp, esp

    mov ecx, 0

loop_start:
    cmp ecx,[ebp+8] ;compare to the first param of dump_stack, (5)
    jnle loop_end

    push ecx ;push the value of my loop onto the stack
    push DWORD msg ;push the msg (%d) should just print the value of my loop
    call _printf
    add esp, 8 ;clear the stack

    inc ecx ;increment ecx
    jmp loop_start ; go back to my loop start

loop_end:

    mov esp, ebp
    pop ebp
    ret

Мой вывод выглядит примерно так

program.exe
0

Просто 0, затем перевод строки.Я попытался проверить, выполняется ли цикл, переместив мой printf в часть loop_end, и он получил ecx как 6, что правильно.Таким образом, цикл выполняется, но printf не ... Что я делаю не так?

(Кроме того, функция называется dump stack, потому что изначально она должна была выводить данные стека, но это нездесь работает по той же причине)

И я компилирую с помощью nasm -f win32 program.asm -o program.o Затем у меня есть файл cpp, который включает в себя windows.h, и я скомпилировал его с помощью gcc-c include и, наконец, я связал их с gcc -o program program.o include.o и запускаю program.exe

1 Ответ

0 голосов
/ 25 марта 2012

Я предполагаю, что printf() изменяет ecx, становится> = [ebp+8], и ваше тело цикла выполняется только один раз. В этом случае вам необходимо ознакомиться с соглашениями о вызовах, используемыми в вашем компиляторе, и вручную сохранить и восстановить так называемые энергозависимые регистры (которые вызываемая функция может свободно изменять без восстановления). Обратите внимание, что может быть несколько различных соглашений о вызовах. Используйте отладчик!

...