提前感谢您的时间!我目前正在制作迷你pascal编译器。扫描,解析和语义分析正在运行,我处于代码生成阶段。我遇到了一些我生成的代码,我不完全理解为什么它不起作用。它可以编译,但输出完全关闭。我将首先链接示例程序,然后链接生成的汇编代码。
type recordType = record of {
x: int,
y: int
};
func a(x : int, y : int) : recordType
var p2 : recordType;
allocate p2;
p2.x = x;
p2.y = y;
return p2;
end a
var p1 : recordType;
p1 = a(10,2);
write p1.x / p1.y;
由于汇编程序代码非常大(由于尚未进行优化),我将链接函数a的代码,因为我认为问题就在那里。如果你想要完整的例子,我很乐意发布它,但除非被要求,否则我不会垃圾论坛。
函数a的汇编代码如下所示:
a:
pushl %ebp
movl %esp, %ebp
lea -8(%ebp), %eax
pushl %eax
popl %eax
imul $8, %eax
pushl %eax
call malloc
addl $4, %esp
movl %eax, -8(%ebp)
lea -8(%ebp), %eax
pushl %eax
popl %eax
addl $4, %eax
pushl %eax
movl 12(%ebp), %eax
pushl %eax
popl %eax
popl %ebx
movl %eax, (%ebx)
lea -8(%ebp), %eax
pushl %eax
popl %eax
addl $0, %eax
pushl %eax
movl 8(%ebp), %eax
pushl %eax
popl %eax
popl %ebx
movl %eax, (%ebx)
movl -8(%ebp), %eax
pushl %eax
popl %eax
jmp aend
aend:
movl %ebp, %esp
popl %ebp
ret
现在在你说什么之前。我知道有很多冗余代码,这是因为我还没有优化代码。话虽如此,我想谈谈所使用的惯例。根据它们的大小(int,bool和array是4个字节,其中记录的总大小等于其成员大小的总和)和参数x和y保存+偏离basepointer(%ebp)+根据basepointer使用-offset保存局部变量(params从+8开始,locals从-4开始)。请记住,AT& T样式的汇编程序使用常规movl src,dst,它与普通汇编程序不同。
我认为问题可能在于根据basepointer在lea指令和movl或我的索引之间的混合。无论如何它可以编译并给我一个3的一致结果,当它应该是5.我已经测试了我的分区,它似乎与"正常"整数。
非常感谢任何帮助。提前谢谢!
此致 马格努斯
答案 0 :(得分:0)
由于lea -8(%ebp),%eax
计算地址,指令imul $8,%eax
将地址乘以8 ...为什么?
代码movl %eax,-8(%ebp)
将%eax存储在stackpointer下方。所以这个价值将无法存活很长时间!
代码movl %eax,(%ebx)
也存储在stackpointer下面,因为%ebx现在包含有效地址-4(%ebp)。当%ebx包含有效地址-8(%ebp)时,会发生第10次这种情况。
也许您需要做的是用subl $8,%esp
和movl %esp,%eax
替换第三条指令。这确实会为您的局部变量建立一个区域。