Assembly 保留汇编寄存器值?
我认为在汇编中创建的函数中使用printf会有一些问题。我的作用是:Assembly 保留汇编寄存器值?,assembly,x86,printf,Assembly,X86,Printf,我认为在汇编中创建的函数中使用printf会有一些问题。我的作用是: printnstars: movl $0, %edi movl 4(%esp), %ebx starloop: cmpl %ebx, %edi je exitloop incl %edi pushl $star call printf addl $4, %esp jmp starloop exitloop: ret 该函数接受一个数字作为参数
printnstars:
movl $0, %edi
movl 4(%esp), %ebx
starloop:
cmpl %ebx, %edi
je exitloop
incl %edi
pushl $star
call printf
addl $4, %esp
jmp starloop
exitloop:
ret
该函数接受一个数字作为参数,我将其移动到%ebx,并使用以下命令打印该数量的“*”s:
函数执行它应该执行的操作,但当我尝试执行以下操作时遇到问题:
pushl (%ecx)
call printnstars
pushl (%ecx)
call printnstars
其中(%ecx)是2。如果我只做一次调用,它的行为和预期的一样,并打印出两颗星,但当我再次调用它时,它打印出无限多颗星。很明显,%ecx一定是被printf内部搞乱了,因为我在创建的任何东西中都没有使用该寄存器。如何确保(%ecx)在多次调用printnstars时保持不变
另外,值得注意的是,这是在一个函数中使用的,该函数正在打印一个直方图,其中每行上都有星号,表示一个数字出现的时间。我所有的频率值都是基于%ecx,所以我使用(%ecx)
如何确保(%ecx)在多次调用printnstars时保持不变
将寄存器值保存在堆栈上的局部变量中
另外,请记住,
printf()
接受数量可变的参数,并且由于它事先不知道有多少参数以及参数的类型,因此它不会删除堆栈上的参数并将其从堆栈中删除(通过调整esp
)成为呼叫者的责任。好的,那么我应该在第一次呼叫之前添加PUSH%ecx,然后在第二次呼叫之前添加popl%ecx吗?另外,我确实在printf调用之后添加了$4,%esp,所以我没有正确地这样做吗…?您可以推两次,然后再调用两次函数。怎么样?处理堆栈参数上的printf。addl$4%esp不处理吗?啊,我错过了。可能是的。好吧,我推了两下,然后打了两次电话,这似乎奏效了:)谢谢。杰克,请不要诋毁你的问题。我不会删除这个,因为这是一个很好的问题,有一个很好的答案。
pushl (%ecx)
call printnstars
pushl (%ecx)
call printnstars