在此先感谢您的时间!我目前正在制作迷你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
现在在你说什么之前 . 我知道有很多冗余代码,这是因为我还没有优化代码 . 话虽如此,我想谈谈所使用的惯例 . 参数x和y根据它们的大小(int,bool和数组是4个字节,其中记录的总大小等于其成员大小的总和)和本地大小来保存,偏离basepointer(%ebp) . 根据basepointer使用-offset保存变量(params从8开始,locals从-4开始) . 请记住,AT&T样式的汇编程序使用常规movl src,dst,它与普通汇编程序不同 .
我认为问题可能在于根据basepointer在lea指令和movl或我的索引之间的混合 . 无论如何它可以编译并给我一个3的一致结果,当它应该是5.我已经测试了我的分区,它似乎与“正常”整数一起工作 .
任何帮助深表感谢 . 提前致谢!
关心马格努斯
1 回答
因为
lea -8(%ebp),%eax
计算地址,指令imul $8,%eax
将地址乘以8 ...为什么?代码
movl %eax,-8(%ebp)
将%eax存储在stackpointer下面 . 所以这个 Value 将无法存活很长时间!代码
movl %eax,(%ebx)
也存储在stackpointer下面,因为%ebx现在包含有效地址-4(%ebp) . 当%ebx包含有效地址-8(%ebp)时,第二次发生10行 .也许您需要做的是用
subl $8,%esp
和movl %esp,%eax
替换第三条指令 . 这确实会为您的局部变量 Build 一个区域 .