题
这是有点古怪,但我闲逛与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:
所有我从这是3印刷一遍又一遍。就像我说的,只是一点点做作的例子,所以不要太担心,它不是一个生死攸关的问题。
(格式是一个有点搞砸了,但没什么大不了的).
解决方案
你不能相信什么,任何所谓程序不会对任何登记册。无论是推动登记册栈和弹出他们的背后叫printf或有所增加和终点值保持在存和读写入注册为你需要他们。
我希望以下工作的。我假设pushl有equivalant 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应的回报的数字印刷,在这种情况下是两个:'0'和' '。我认为这返回这eax,当你增加它,你得到3,这是什么你进行打印。你可能会更好使用不同的登记柜台上。
你可以安全地使用登记册,是"被叫保存",而不具有拯救他们自己。在x86这些是电子数据交换,esi,并ebx;其他体系结构有更多的。
这些都记录在《参考文献: http://math-atlas.sourceforge.net/devel/assembly/
写得很好的功能通常会把所有注册栈和出他们的时候他们这样做,他们仍然保持不变的期间的功能。唯一的例外将是eax包含返回值。图书馆的功能,如printf是最有可能编写这种方式,所以我不会做,因为楔建议:
你会需要这样做对任何其他变量。使用寄存器储存地的变量是相当多的保留体系结构有足够的注册,以支持它的(例如史诗,amd64,等等。)
事实上,从我所知道的,编译器通常编制职能的方式来处理正是这个问题。
@seanyboy,你的解决方案是大材小用。所有需要的是更换eax与其他一些寄存器等ecx.
内森是在正确的轨道。你不能想当然地认为登记册的价值将会未经修改后呼吁一个子程序。事实上,这是最好的假设他们将被修改,其他的子程序不能够做到这一点的工作(至少对低寄存器计体系结构等x86).如果你想要保留一个值应储存在存储器(例如把它推到叠,并跟踪它的位置)。
你会需要这样做对任何其他变量。使用寄存器储存地的变量是相当多的保留体系结构有足够的注册,以支持它的(例如史诗,amd64,等等。)
你可以改写,以便使用登记册,是不是假设的变化,例如 %ebp
.只要确定你把它们拖到堆叠在一开始,和流行他们在你的程序。
# count.s: print the numbers from 0 to 100.
.text
string: .asciz "%d\n"
.globl _main
_main:
push %ecx
push %ebp
movl $0, %ecx # The starting point/current value.
movl $100, %ebp # The ending point.
_loop:
# Display the current value.
pushl %ecx
pushl $string
call _printf
addl $8, %esp
# Check against the ending value.
cmpl %ecx, %ebp
je _end
# Increment the current value.
incl %ecx
jmp _loop
_end:
pop %ebp
pop %ecx