2017-02-11 118 views
1

我有這個代碼是假設添加兩個數字,一個浮點數(3.25)和一個整數(2)。如何在NASM中添加兩個數字,整數和浮點數?

編輯:

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

+0

在存儲任何東西之前,您先從num1加載0,然後將該零置於堆棧中。你不必用浮點加載和順便存儲。 – harold

+0

@harold我編輯了這個問題,謝謝,我還有一個錯誤。 –

+0

好吧,現在你正在嘗試添加到常數 – harold

回答

2

x87 FPU的一個很好的教程超出了Stackoverflow的範圍,但我可以推薦一個MASM forums。另一個好的來源是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. 

而不是使用全局變量來存儲值在主內存中,我暫時使用了我們預留的堆棧空間作爲臨時暫存區域來加載/操作x87 FPU。

如果您位於支持SSE2指令集(包括32位模式下的任何X86-64處理器)的CPU上,則還有其他選項。一種是使用SIMD指令和寄存器來執行32位和64位浮點運算。使用指令集參考你發現像一些有用的指示:

  • cvtsi2sd:將DWORD整到標量雙精度浮點值
  • cvtss2sd:將標量單精度FP值,標量雙精度FP值
  • addsd:添加標量雙精度浮點值
  • movsd:移動標量雙精度浮點值

標量單精度FP值是一個32位浮點數。標量雙精度是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 
+0

謝謝邁克爾,這是一個很好的解釋。 :) –

+0

雖然'fld1' +'faddp'比之前出現的示例代碼更快,但更快(更明顯)的方法是使用'fld'加載常量2.0。它只會消耗二進制文件中的一小部分空間。 –

1

解決的辦法是:

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

對不起,我的英語不好。