我对装配很新(昨天开始学习)并且遇到循环问题:
下面的代码应该打印0-49的值,而是打印0-49然后打印~20行垃圾(我假设这是其他程序的堆栈的一部分/该程序的其他位正在使用)。我预计问题是第二个循环.loop
,因为它打印的行数错误,打印由.loop
处理。
我正在使用FASM(Flat Assembler)程序来编译它。
代码:
format PE console
include "win32ax.inc"
start:
mov ecx, 50 ;number of loops
.mainloop: ;for testing purposes, just pushes 49-0 onto the stack
push ecx ;push onto stack
dec ecx ;decrement counter
jnz .mainloop ;jump if counter not zero
mov ecx, 50 ;reset ecx (counter)
.loop: ;prints the stack, should print 0-49 but also prints garbage at the end
pop eax ;pop from stack to eax
cinvoke printf,formatstring,eax ;print eax
dec ecx ;decrement counter
jnz .loop ;loop if counter not zero
int 15;wait 5 seconds ish
invoke ExitProcess ;exit
formatstring db "%d",13,10,0 ;to print digits instead of ASCII chars
section '.idata' import data readable ;stuff I copied but seems to work
library msvcrt,'msvcrt.dll',\ ;don't understand it
kernel32,'kernel32.dll' ;^
import msvcrt,printf,'printf';^^
import kernel32,ExitProcess,"ExitProcess";^^^
提前致谢。
P.S。如何使用语法高亮显示格式化代码?
答案 0 :(得分:2)
问题是cinvoke printf,formatstring,eax
更改了ECX
寄存器,正如zx485所指出的那样。事实证明它也改变了EDX
寄存器。
要解决此问题,我更改为使用EBX
注册表,cinvoke printf,formatstring,eax
修改了 。
我希望这有助于某人。
编辑:melpomene发布了一个更好的答案。答案 1 :(得分:2)
ecx
是"来电者保存的"之一寄存器,意味着任何函数调用都可以修改ecx
,并且在必要时保存/恢复它是调用者的工作。
根据绝大多数编译器符合的英特尔ABI,EAX,EDX和ECX可以在程序或功能中免费使用,无需保留。
您在循环中对printf
的来电可能是clobbers ecx
。