首页 > 解决方案 > AMD64 程序集:从函数正确返回浮点数

问题描述

作为一个学习练习/小项目,我正在编写一个简单的编译器。这是我正在编译的源代码(我自己的语言):

fn: main(arg: float) ~ float {
    return arg * 4.0;
}

如所见,此函数采用浮点数,并返回乘以 4 作为结果。
这是假设 x64 linux 上的默认调用约定,其中浮点参数在 xmm 寄存器中传递和返回。该代码当前编译为以下内容:

pushq  %rbp
movq   %rsp, %rbp
subq   $0x4, %rsp ; increment stack
movss  %xmm0, 0x4(%rsp) ; and save the float argument
subq   $0x4, %rsp 
movl   0x8(%rsp), %r11d ; expressions copy their parameters. this is what happens here
movl   %r11d, 0x4(%rsp)
subq   $0x4, %rsp
movb   $0x0, 0x4(%rsp) ; inefficient: but my compiler loads the float
movb   $0x0, 0x3(%rsp) ; byte-by-byte here
movb   $-0x80, 0x2(%rsp)
movb   $0x40, 0x1(%rsp)
flds   0x8(%rsp) ; load the floats
flds   0x4(%rsp)
fmulp  %st, %st(1); multiply
subq   $0x4, %rsp ; increment space for the result
fsts   0x4(%rsp) ; store it on the stack
movl   0x4(%rsp), %r11d
movl   %r11d, 0xc(%rsp) ; copy the return value to the start of this expressions stack frame
addq   $0x8, %rsp
movss  0x4(%rsp), %xmm0  ; copy the float on the top of the stack frame to the xmm0 register
addq   $0x8, %rsp ; pop the entire stackframe
popq   %rbp
retq ; return

请原谅长批量的汇编 - 我的编译器产生了非常未优化的代码。为了清楚起见,我发表了一些评论。
现在 - 上面的代码有效......但它产生了一个虚假的结果。它基本上总是返回
一个虚假的浮点值。而且我不明白为什么-只要我正确理解了SysV-ABI,这应该可以吗?任何帮助将不胜感激。

标签: assemblyfloating-pointx86-64calling-convention

解决方案


推荐阅读