这有点奇怪,但今天我正在寻找GNU汇编程序(我希望能够至少阅读语法),并且试图让我的这个有点人为的例子工作.也就是说我只想从0到100,一直打印数字.几分钟后,我想出了这个:
# count.s: print the numbers from 0 to 100. .text string: .asciz "%d\n" .globl _main _main: movl $0, %eax # The starting point/current value. movl $100, %ebx # The ending point. _loop: # Display the current value. pushl %eax pushl $string call _printf addl $8, %esp # Check against the ending value. cmpl %eax, %ebx je _end # Increment the current value. incl %eax jmp _loop _end:
我从中得到的只是一遍又一遍地打印出来.就像我说的,只是一个有点人为的例子,所以不要太担心它,这不是生死攸关的问题.
(格式有点混乱,但没什么大不了的).
你无法相信任何被调用的程序对任何寄存器的作用.将寄存器压入堆栈并在调用printf后将其弹回,或者将增量和终点值保存在存储器中,并根据需要读/写寄存器.
我希望以下工作.我假设pushl有一个等价的popl,你可以将多个数字推到堆栈上.
# count.s: print the numbers from 0 to 100. .text string: .asciz "%d\n" .globl _main _main: movl $0, %eax # The starting point/current value. movl $100, %ebx # The ending point. _loop: # Remember your registers. pushl %eax pushl %ebx # Display the current value. pushl %eax pushl $string call _printf addl $8, %esp # reinstate registers. popl %ebx popl %eax # Check against the ending value. cmpl %eax, %ebx je _end # Increment the current value. incl %eax jmp _loop _end:
我对_printf不太熟悉,但可能是它修改了eax吗?Printf应返回打印的字符数,在本例中为2:'0'和'\n'.我认为它在eax中返回,当你递增它时,你得到3,这就是你要打印的内容.你可能最好为计数器使用不同的寄存器.
您可以安全地使用"被调用者保存"的寄存器,而无需自己保存.在x86上,这些是edi,esi和ebx; 其他架构有更多.
这些内容记录在ABI参考文献中:http://math-atlas.sourceforge.net/devel/assembly/