在汇编中打印一个浮点数

7 浏览
0 Comments

在汇编中打印一个浮点数

我有以下程序来使用C的printf打印一个浮点数的asm代码:

.section .rodata
format: .ascii "你的数字是:%f\n\0"
.section .text
.globl main
main:
    lea format(%rip), %rdi
    mov $0b1000000001011001100110011001101, %xmm0 # 数字2.7
    mov $0, %eax
    add $-8, %rsp
    call printf@plt
    add $8, %rsp
    mov $0, %eax
    ret

然而,当我用以下方式汇编它时,我遇到了一个错误:

int_c.s:7: Error: 不支持的指令`mov'

你不能将立即数添加到xmm寄存器中吗?或者以上程序有什么问题吗?


更新:我设法编译了它,但我觉得我的问题在于movq只能接受8个字节,而我想要将一个4字节的浮点数放入fp寄存器中:

mov $2.7, %eax # 使用'2.7'更易读
movq %eax, %xmm0

在执行printf之前,经过逐步执行指令,它看起来是正确的:

>>> p $xmm0

$2 = {

v4_float = {[0] = 2.70000005, [1] = 0, [2] = 0, [3] = 0},

v2_double = {[0] = 5.3194953090036137e-315, [1] = 0},

...

}

0
0 Comments

问题的出现原因是希望在汇编语言中打印一个浮点数,但是直接将浮点数存储在寄存器中并打印会出现错误的结果。解决方法是将浮点数存储在内存中,并使用"cvtss2sd"指令将其转换为双精度浮点数后再进行打印。

下面是解决该问题的一个工作示例,其中将浮点数写入内存,然后使用"cvtss2sd"将浮点数转换为双精度浮点数:

format: .ascii "Your number is: %f\n\0"

.section .text

.globl main

main:

push %rbp

mov %rsp, %rbp

lea format(%rip), %rdi

# move float to memory and upgrade to 8 bytes

movl $0b1000000001011001100110011001101, -4(%rbp)

cvtss2sd -4(%rbp), %xmm0

mov $1, %eax

call printf

mov $0, %eax

mov %rbp, %rsp

pop %rbp

ret

在这个示例中,使用了"cvtss2sd"指令将存储在内存中的浮点数转换为双精度浮点数,并使用printf函数进行打印。

解决这个问题的另一个方法是直接使用寄存器进行转换和打印,而不需要将浮点数存储在内存中。下面是使用寄存器的方法:

movl $0b1000000001011001100110011001101, %eax

movd %eax, %xmm0

cvtss2sd %xmm0, %xmm0

然而,这种方法需要额外的指令来将浮点数加载到寄存器中,因此编译器通常会从内存中加载浮点常数,而不是直接使用立即数。

总结起来,要在汇编语言中打印浮点数,可以将浮点数存储在内存中,并使用"cvtss2sd"指令将其转换为双精度浮点数后再进行打印,或者直接使用寄存器进行转换和打印,但需要注意额外的指令开销。

0