Loops 我的简单汇编程序中的无限循环
我正在学习组装中的循环和跳跃,我试着做一个简单的循环。我希望调用Loops 我的简单汇编程序中的无限循环,loops,assembly,x86,Loops,Assembly,X86,我正在学习组装中的循环和跳跃,我试着做一个简单的循环。我希望调用printf命令10次。我已将计数器变量设置为1。我还将%edx设置为1,然后在每次迭代中递增它。如果它等于10,那么我们应该退出循环。但现在循环是无限的。我已经用gdb进行了调试,%edx似乎在printf函数中被覆盖。这就是为什么我将%edx推到堆栈中,然后在printf调用后将其弹出,但它不起作用。我错过了什么 .section .data output: .asciz "Value is %d\n" val1:
printf
命令10次。我已将计数器
变量设置为1。我还将%edx
设置为1,然后在每次迭代中递增它。如果它等于10,那么我们应该退出循环。但现在循环是无限的。我已经用gdb
进行了调试,%edx
似乎在printf
函数中被覆盖。这就是为什么我将%edx
推到堆栈中,然后在printf
调用后将其弹出,但它不起作用。我错过了什么
.section .data
output:
.asciz "Value is %d\n"
val1:
.int 123
counter:
.int 1
.section .text
.globl _start
_start:
nop
movl counter, %edx # start at 1
gohere:
movl val1, %ebx # move value 123 to %ebx
pushl %edx # push %edx to stack
pushl %ebx # push %ebx to stack
pushl $output
call printf # call printf
popl %edx # pop %edx value
inc %edx
cmp $10, %edx # if %edx is less than 10...
jl gohere # ... go to gohere, otherwise exit
movl $0, %ebx
movl $1, %eax
int $0x80
您在最后一次按下时按下了output
,因此第一次弹出将弹出output
。这是堆栈,这是后进先出。在您的代码中,弹出后,输出
将进入edx
。
要解决此问题,请在popl edx之前放置两个POP:
popl output
popl ebx
printf()是一个使用cdecl调用约定的C函数。这需要你弹出你推的参数。因此,popl%edx实际上没有恢复edx寄存器值,堆栈不平衡。添加两个pop。哦,我添加了popl%edx
的次数与我将值推送到堆栈中的次数一样多,而且成功了!请看我在上面代码中所做的编辑。但像这样多次流行价值观似乎有点丑陋。没有更简单的方法吗?我回滚了您的编辑,因为如果您编辑问题以包含答案中给出的解决方案(例如添加到popl
说明),那么对于未来的读者来说,答案将变得毫无意义。因此,不应编辑问题的基本内容(如代码)以匹配答案。是的,几秒钟前我注意到了这一点。:-)正如我在上面的评论中所问的:难道没有比在推送值时多次弹出值更简单的方法了吗?我不能直接指向堆栈中的位置以将值弹出到%edx吗?当然可以,它是程序集,可以指向内存中的任何位置。但它比两个POP更复杂(应该指向堆栈基后的2个字节)。数据结构原则说不要这样做,输出
似乎是13个字节(13个字符),而val1
是4个字节的整数。如果我做了-17(%esp)
我应该能够直接将-17(%esp)的值设置为%edx,但是我想我计算字节数的方法是错误的,因为它不起作用。是的,但是“output”的地址(偏移量)只有4个字节。请在通话后尝试添加$8,%esp
,然后您应该能够按预期添加%edx。(我不擅长at&T stntax,所以可能把事情搞砸了)