以下是汇编语言类的作业问题。我们要通过读取gdb中从C生成的X86代码来创建Y86代码。该函数的目的是对链表的元素求和。
目前的功能,它的工作原理!程序终止时,%eax寄存器中包含正确的值。不幸的是,它只是正确的,因为黑客。我在函数末尾添加了halt
指令,就在ret
指令之前。如果我取消注释,那么似乎发生的是当它执行ret
指令时,PC被设置为0x0。换句话说,它似乎从一开始就重新开始,当它应该做的是返回它被调用的点。它进入了无限循环。
代码如下。如果您安装了Y86模拟器,它是独立的。
.pos 0
init: irmovl Stack, %esp
irmovl Stack, %ebp
jmp Main
Main:
irmovl ele1, %eax
pushl %eax
call sum_list
halt
sum_list:
pushl %ebp
rrmovl %esp, %ebp
irmovl $16, %edx
subl %edx, %esp
irmovl $0, %edx
rmmovl %edx, -4(%ebp)
jmp L2
L3:
mrmovl 8(%ebp), %eax
mrmovl (%eax), %eax
mrmovl -4(%ebp), %edx
addl %eax, %edx
rmmovl %edx, -4(%ebp)
mrmovl 8(%ebp), %eax
mrmovl 4(%eax), %eax
rmmovl %eax, 8(%ebp)
L2:
irmovl $0, %ecx
mrmovl 8(%ebp), %edx
subl %ecx, %edx
jne L3
mrmovl -4(%ebp), %eax
rrmovl %esp, %ebp
popl %ebp
halt #THIS DOESN'T BELONG. COMMENT OUT TO SEE BAD BEHAVIOR.
ret
#linked list
.align 4
ele1:
.long 0x00a
.long ele2
ele2:
.long 0x0b0
.long ele3
ele3:
.long 0xc00
.long 0
.pos 0x300
Stack:
感谢您的帮助!
答案 0 :(得分:4)
这可能是也可能不是错误的原因,但我认为你正在错误地拆除sum_list
的堆栈帧。您可以按如下方式进行设置:
pushl %ebp
rrmovl %esp, %ebp
然后你把它撕下来:
rrmovl %esp, %ebp
popl %ebp
请注意,在这两种情况下都要从%esp
复制到%ebp
,这是不正确的,因为拆除应该撤消设置的操作。相反,尝试
rrmovl %ebp, %esp
popl %ebp
或只是
leave
做同样的事情。
答案 1 :(得分:0)
mrmovl -4(%ebp), %edx
这是问题所在。在ebp - 4处有返回地址,所以你要覆盖它。使用不同的位置,一切都会好的:)
答案 2 :(得分:-1)
有两个(和一半)与堆栈操作相关的问题:
框架设置正确,但解构件失败(程序执行rrmovl%esp,%ebp而不是rrmovl%ebp,%esp)
尝试访问存储在前一帧中的参数(即调用者的帧)失败。堆栈从顶部向下运行,堆栈中存储的最后一个元素是返回地址和旧帧指针,因此一旦ebp寄存器被更改,被调用者可以通过渐进式偏移直接引用调用函数的参数8(%EBP)。
有一半的错误是主函数在终止之前没有弹出堆栈的存储参数。
我的Y86博客http://y86tutoring.wordpress.com/2012/10/31/functioning-stacks/
讨论了来电者 - 被叫者惯例