我正在努力使组装时的打印精度提高一倍,但我失败了。调用自己计划用作帮助程序的双打打印功能时,我遇到了段错误。我正在关注以下printf
示例:https://www.csee.umbc.edu/portal/help/nasm/sample.shtml
我的代码当前看起来像这样:
section .data
formatStrf: db `The number is %f\n`,0
section .text
extern printf
printfcallfloat:
;Pass in RDI
PUSH RDI ;Preserve value of rdi
PUSH RAX ;Preserve value of RAX
PUSH RDI;The value we want to print
PUSH DWORD formatStrf
CALL printf ;Segfault
POP RAX;Pop the stack back (too lazy to manually change the RSP value)
POP RAX
POP RAX;Restore the RAX and RDI
POP RDI
RET
我将浮点值传递给RDI
reg,如下所示:
MOVSD QWORD [RSP], XMM0 ;Copy to stack
MOV RDI, QWORD [RSP]
CALL printfcallfloat
编辑:我正在linux上运行它。
在x86_64上,参数在寄存器中传递,而不在堆栈中传递(仅当参数的大小太大而无法容纳在寄存器中时,才使用堆栈)。所有gory细节1都列在SYSV ABI for x86_64
中基本原理是,前6个整数/指针参数在RDI / RSI / RDX / RCX / R8 / R9中传递,而前8个浮点/双精度参数在XMM0..XMM7中传递。此外,您需要指定用于AL 2中的参数的XMM寄存器的number。因此,您需要使用RDI中的格式,XMM0中的double值和AL中的1]
wikipedia page对此也有很多不错的信息。
1
对于非Microsoft系统-MS为MS,它们以自己不兼容的方式进行操作2
您实际上只需要为使用至少一个XMM寄存器的varargs函数设置此项。对于非varargs函数,它将被忽略,如果对于varargs函数将其设置得太大,结果将是一些浪费的周期(保存未使用的XMM regs),但实际上不会破坏任何内容。您链接到的页面具有x86
(32位体系结构的示例)。 x86_64
体系结构在将参数传递给函数的方式上有所不同。