如何在 NASM 中添加两个数字,整数和浮点数?
How to add two numbers, integer and a float in NASM?
我有这段代码,假设要添加两个数字,一个浮点数 (3.25) 和一个整数 (2)。
已编辑:
extern _printf, _scanf
global _main
section .bss
num1: resb 4
section .data
format_num: db "%f", 10, 0
section .text
_main:
mov dword [num1], __float32__(3.25)
add num1, 2
sub esp, 8
fld dword [num1]
mov dword [num1], eax
fstp qword [esp]
push format_num
call _printf
add esp, 12
ret
我得到的输出是:
test.asm:11:error: invalid combination of opcode and operands
我期望的输出是:
5.250000
解决方法是:
extern _printf
global _main
section .bss
num1: resb 4
num2: resb 4
section .data
format_float: db "The result is %f", 10, 0
_main:
mov dword [num1], 2
mov dword [num2], __float32__(3.25)
sub esp, 8
fild dword [num1]
fadd dword [num2]
fstp qword [esp]
push format_float
call _printf
add esp, 12
ret
我得到的输出是:
5.250000
fild
将2作为2.0000000压入ST0
,则fadd
可以将两个浮点数相加。结果是一个浮点数。 int + float = float
.
x87 FPU 的优秀教程超出了 Whosebug 的范围,但我可以推荐 MASM forums. Another good source is the Intel Instruction Set Reference 上的教程。特别是大多数以 F
开头的函数都是与 x87 浮点单元 (FPU) 相关的指令。
一般来说,您不能只将浮点值与整数相加。它们是两种不同的表示。您可以做的是将整数转换为浮点值,然后用它进行浮点计算。特别是,以 FI
开头的指令是浮点运算,涉及将整数内存操作数转换为浮点数。
给猫剥皮的方法有很多种,但如果您查看上面链接的 FPU 教程,您可能会发现一种简单的方法就是这样做:
sub esp, 8 ; Allocate space on stack to store integer
mov dword [esp], 2 ; Move the 32-bit integer value onto stack temporarily
fild dword [esp] ; Load integer 2 from stack into top of FPU stack at st(0)
; Converting it to 2.0 in the process
mov dword [esp], __float32__(3.25)
; Move 3.25 onto stack temporarily
fadd dword [esp] ; Add 3.25 to st(0). Result in st(0). So st(0)=5.25
fstp qword [esp] ; Store 64-bit double to stack for printf and pop FPU stack.
我没有使用全局变量在主内存中临时存储值,而是使用堆栈 space 我们保留作为临时暂存区 load/operate 使用 x87 FPU。
如果您使用的 CPU 支持 SSE2 指令集(这包括 32 位模式下的任何 X86-64 处理器),那么您还有其他选择。一种是使用 SIMD 指令和寄存器进行 32 位和 64 位浮点运算。使用指令集参考,您可以找到一些有用的指令,例如:
- cvtsi2sd:将双字整数转换为标量Double-Precision FP 值
- cvtss2sd:将标量 Single-Precision FP 值转换为标量 Double-Precision FP 值
- addsd : 添加标量 Double-Precision Floating-Point 值
- movsd : 移动标量 Double-Precision Floating-Point 值
标量 Single-Precision FP 值是 32 位浮点数。标量 Double-Precision 是 64 位双精度数。
sub esp, 8
mov dword [esp], 2 ; Load integer 2 (32-bit signed value) onto stack temporarily
cvtsi2sd xmm0, [esp] ; Convert 2 on stack to 64-bit float and store in XMM0
mov dword [esp], __float32__(3.25)
; Load 32-bit float value of 3.25 onto stack
cvtss2sd xmm1, [esp] ; Load 32-bit single and convert it to 64-bit double. Store in XMM1
addsd xmm0, xmm1 ; Add 64-bit float in XMM0 and XMM1 store XMM0
movsd qword [esp], xmm0 ; Move 64-bit float back onto stack to be printed by printf
我有这段代码,假设要添加两个数字,一个浮点数 (3.25) 和一个整数 (2)。
已编辑:
extern _printf, _scanf
global _main
section .bss
num1: resb 4
section .data
format_num: db "%f", 10, 0
section .text
_main:
mov dword [num1], __float32__(3.25)
add num1, 2
sub esp, 8
fld dword [num1]
mov dword [num1], eax
fstp qword [esp]
push format_num
call _printf
add esp, 12
ret
我得到的输出是:
test.asm:11:error: invalid combination of opcode and operands
我期望的输出是:
5.250000
解决方法是:
extern _printf
global _main
section .bss
num1: resb 4
num2: resb 4
section .data
format_float: db "The result is %f", 10, 0
_main:
mov dword [num1], 2
mov dword [num2], __float32__(3.25)
sub esp, 8
fild dword [num1]
fadd dword [num2]
fstp qword [esp]
push format_float
call _printf
add esp, 12
ret
我得到的输出是:
5.250000
fild
将2作为2.0000000压入ST0
,则fadd
可以将两个浮点数相加。结果是一个浮点数。 int + float = float
.
x87 FPU 的优秀教程超出了 Whosebug 的范围,但我可以推荐 MASM forums. Another good source is the Intel Instruction Set Reference 上的教程。特别是大多数以 F
开头的函数都是与 x87 浮点单元 (FPU) 相关的指令。
一般来说,您不能只将浮点值与整数相加。它们是两种不同的表示。您可以做的是将整数转换为浮点值,然后用它进行浮点计算。特别是,以 FI
开头的指令是浮点运算,涉及将整数内存操作数转换为浮点数。
给猫剥皮的方法有很多种,但如果您查看上面链接的 FPU 教程,您可能会发现一种简单的方法就是这样做:
sub esp, 8 ; Allocate space on stack to store integer
mov dword [esp], 2 ; Move the 32-bit integer value onto stack temporarily
fild dword [esp] ; Load integer 2 from stack into top of FPU stack at st(0)
; Converting it to 2.0 in the process
mov dword [esp], __float32__(3.25)
; Move 3.25 onto stack temporarily
fadd dword [esp] ; Add 3.25 to st(0). Result in st(0). So st(0)=5.25
fstp qword [esp] ; Store 64-bit double to stack for printf and pop FPU stack.
我没有使用全局变量在主内存中临时存储值,而是使用堆栈 space 我们保留作为临时暂存区 load/operate 使用 x87 FPU。
如果您使用的 CPU 支持 SSE2 指令集(这包括 32 位模式下的任何 X86-64 处理器),那么您还有其他选择。一种是使用 SIMD 指令和寄存器进行 32 位和 64 位浮点运算。使用指令集参考,您可以找到一些有用的指令,例如:
- cvtsi2sd:将双字整数转换为标量Double-Precision FP 值
- cvtss2sd:将标量 Single-Precision FP 值转换为标量 Double-Precision FP 值
- addsd : 添加标量 Double-Precision Floating-Point 值
- movsd : 移动标量 Double-Precision Floating-Point 值
标量 Single-Precision FP 值是 32 位浮点数。标量 Double-Precision 是 64 位双精度数。
sub esp, 8
mov dword [esp], 2 ; Load integer 2 (32-bit signed value) onto stack temporarily
cvtsi2sd xmm0, [esp] ; Convert 2 on stack to 64-bit float and store in XMM0
mov dword [esp], __float32__(3.25)
; Load 32-bit float value of 3.25 onto stack
cvtss2sd xmm1, [esp] ; Load 32-bit single and convert it to 64-bit double. Store in XMM1
addsd xmm0, xmm1 ; Add 64-bit float in XMM0 and XMM1 store XMM0
movsd qword [esp], xmm0 ; Move 64-bit float back onto stack to be printed by printf