x86-64组件XMM1寄存器丢失其值

问题描述 投票:2回答:1

所以我正在处理这种汇编代码段,但遇到一个奇怪的问题:XMM1寄存器似乎在执行过程中失去了它的值,即使我认为我在这里不使用任何指令可能会改变其价值。下面是有问题的代码段。

    MOVSD QWORD [RSP], XMM1 ;Copy to stack
    MOV RDI, QWORD [RSP]
    CALL printfcallfloat;Prints floating point value from the RDI register, preserves all registers

    ;Load 10 to the fpu stack
    PUSH 10
    FILD QWORD [RSP]
    POP RDI

    MOVSD QWORD [RSP], XMM0 ;Copy to stack
    FLD QWORD [RSP];Load number float from XMM0 to the x87

    ;Do the math y = xmm0 (2), x=10 X*LOG2(Y)
    FYL2X

    ;We now have the result of x*log2(y) in ST(0)
    FSTP QWORD [RSP];Pop the result from the logarithm to the stack
    MOVSD XMM0, QWORD [RSP];Move the result back to xmm0

    ;print XMM0 and XMM1
    MOVSD QWORD [RSP], XMM0 ;Copy to stack
    MOV RDI, QWORD [RSP]
    CALL printfcallfloat;This preserves all registers

    MOVSD QWORD [RSP], XMM1 ;Copy to stack
    MOV RDI, QWORD [RSP]
    CALL printfcallfloat;This preserves all registers

这将提供以下输出:

10.000000
10.000000
-nan

我对这里发生的事情感到非常困惑。

编辑:打印功能的实现如下:

printfcallfloat:

    ;Value is passed here in RDI
    PUSH RDI ;Preserve value of rdi
    PUSH RAX ;Preserve value of RAX
    pushxmm XMM0 ;Preserve XMM0
    ;Double is passed to printf in XMM0
    ;Now we move the value from the reg to the XMM0 using stack
    PUSH RDI
    popxmm XMM0
    MOV AL, 1;We are passing one argument so al should be 1
    MOV RDI, formatStrf ;Format string is passed in RDI
    CALL printf

    ;Restore XMM0
    popxmm XMM0
    POP RAX
    POP RDI
    RET
assembly floating-point x86-64 sse
1个回答
0
投票

很好,这是一个堆栈未对齐问题,而printf方法实际上覆盖了XMM1中的值。我没有考虑到我的汇编代码的被调用方在堆栈上压入的返回值(使堆栈未对齐),因此在添加了XMM1 reg的压入和弹出之后,我开始遇到段错误。只需将SUB RSP, 8添加到我的代码的开头即可将堆栈对齐为16个字节,这似乎是事实上的标准,并且对于我也在代码中使用的SSE寄存器来说,对齐也足够大。我进行了以下更改(在代码注释中)。打印子程序:

printfcallfloat:

    ;Value is passed here in RDI
    PUSH RDI ;Preserve value of rdi
    PUSH RAX ;Preserve value of RAX
    pushxmm XMM0
    pushxmm XMM1 ;Added this to make sure XMM1 is surely preserved after call

    PUSH RDI
    popxmm XMM0
    MOV AL, 1;We are passing one argument so al should be 1
    MOV RDI, formatStrf ;Format string is passed in RDI

    CALL printf ;Does not necessarily preserve SSE registers

    ;Restore XMM anmd other regs
    popxmm XMM1 ;Pop the XMM1 reg also
    popxmm XMM0
    POP RAX
    POP RDI
    RET

在主代码中,添加了以下内容以在进入后对齐堆栈,尽管我不确定这是否是正确的方法,请让我知道我做错了什么:

    ;Align the stack
    SUB RSP, 8 ;8 bytes return address
© www.soinside.com 2019 - 2024. All rights reserved.