【问题标题】:Access floating-point return of assembly function访问汇编函数的浮点返回
【发布时间】:2014-10-20 13:43:09
【问题描述】:

我们的课程练习要求我们在 GNU 汇编中创建一个 delta = b2 - 4ac 函数,并从 C 中访问它。由于这是一门关于编译器的课程,而不是关于汇编的课程,教授选择只演示整数功能,并且需要一个整数函数。

但是,我希望个人学习能够超越职责要求,并创建一个返回浮点而不是整数的可用函数。

我想出了这个C(不要介意全局变量,下一个练习的目的是要有一个带参数的适当函数):

# include <stdio.h>

extern float delta();
float a, b, c;

int main() {
    a = 3;
    b = 5;
    c = 4;
    printf("δ = %f\n", delta());
    return 0;
}

还有这个 GNU GAS:

.globl a
.globl b
.globl c
.globl delta
.f4: .float 4.0     # constante 4

.text
delta:
    fld b           # b sur la pile
    fmul b          # b2 sur la pile
    fld .f4         # 4 sur la pile 
    fmul a          # 4a sur la pile
    fmul c          # 4ac sur la pile
    fsubp           # b2 - 4ac sur la pile
ret

谷歌让我相信我应该在浮点堆栈的顶部留下一个浮点结果,但这不起作用,并且在 C 调用程序中打印的结果总是 0.0000000。

我必须错过一个非常小的东西,但是没有多少谷歌搜索可以找到它,有人能指出我正确的方向吗? 感谢您的关注。

【问题讨论】:

    标签: c assembly gnu-assembler x87


    【解决方案1】:

    它确实对我有用。确保您没有意外使用 64 位模式,因为那里的调用约定不同。即使用gcc -g -m32 foo.c bar.s进行编译。

    也就是说,我也看到了一些应该解决的潜在问题。

    • 由于您的全局变量是在 C 代码中定义的,因此您不应在程序集中使用 .globl。如果有的话,您应该使用.extern,但 GAS 不需要这样做。
    • 不应依赖默认操作数大小。当你有内存操作数时,你应该明确地使用 s 后缀作为浮点数和 l 后缀作为双精度数。例如,flds b 以确保它作为浮点数加载。
    • 你应该使用fsubrp,因为栈顶是你的4ac,所以你使用fsubp计算的是4ac-b^2

    【讨论】:

    • 谢谢,m32 选项是我错过的,我现在将以一种压力较小的方式阅读其余有用的 cmets。非常感谢。
    • 如果使用as组装,对应的标志位为--32,如命令as --32 -o delta.o delta.s中的@
    猜你喜欢
    • 1970-01-01
    • 2013-08-10
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    • 2019-10-10
    相关资源
    最近更新 更多