2012-07-15 67 views
0

我在linux下使用AT彙編語言和AT & t語法。 我需要分割和乘以3個數字(a,b,c)。 該操作可能是a/b * c,我嘗試過使用idiv和imul istruction,但是當然這些工作在整數上,所以我得到的結果總是不準確。 我也嘗試使用fidiv和fimul istruction在計算中使用浮點數,但我得到完全錯誤的結果。所以可能我在做錯誤的寄存器操作。 有人可以請我做一個關於如何在AT & T下使用fidiv/fimul的例子嗎?這些結構使用哪些寄存器?彙編程序浮點運算

在此先感謝。

+1

「我也嘗試過使用fidi v和fimul ......「然後向我們展示你的嘗試。 – 2012-07-15 00:07:50

回答

0

AT AT & T是gas(GNU Assembler)的輸出語法,你不應該想太長時間。只需將它寫入C中,並使用-S開關生成彙編程序輸出。

例:

如果在源文件abc.c

main(){ 
    int a = 7; 
    int b = 3; 
    int c = 2; 
    return (double)a/(double)b*(double)c; 
} 

鍵入以下程序,然後使用編譯gcc -S abc.c

我得到下面的彙編代碼:

.file "abc.c" 
.text 
.globl main 
.type main, @function 
main: 
.LFB0: 
.cfi_startproc 
pushq %rbp 
.cfi_def_cfa_offset 16 
.cfi_offset 6, -16 
movq %rsp, %rbp 
.cfi_def_cfa_register 6 
movl $7, -4(%rbp) 
movl $3, -8(%rbp) 
movl $2, -12(%rbp) 
cvtsi2sd -4(%rbp), %xmm0 
cvtsi2sd -8(%rbp), %xmm1 
movapd %xmm0, %xmm2 
divsd %xmm1, %xmm2 
movapd %xmm2, %xmm1 
cvtsi2sd -12(%rbp), %xmm0 
mulsd %xmm1, %xmm0 
cvttsd2si %xmm0, %eax 
popq %rbp 
.cfi_def_cfa 7, 8 
ret 
.cfi_endproc 
.LFE0: 
.size main, .-main 
.ident "GCC: (Debian 4.6.3-1) 4.6.3" 
.section .note.GNU-stack,"",@progbits 

它的功能應該足夠清楚:re在堆棧中爲3 int提供空間,在它們中存儲常數值,將它們轉換爲double(cvtsi2sd),執行除法(注意:你寫的順序爲div b, a,結果在第二個寄存器中)。等等。顯而易見的是,編譯器現在不用費時地使用舊的FPU 8087指令集,有更簡單的方法來執行浮點運算而無需使用FPU堆棧。由於這個問題在目標系統上沒有提出任何問題,我將按照我的編譯器的說法來執行此類計算。由於對某些人來說可能還不清楚(我的回答是downvoted),所以我對gcc輸出進行了一些重新排序(以避免無用地移動)並添加了評論。唯一可能的缺陷是div的參數順序。在哪個寄存器中放置數據並得到結果取決於讀者。

.file "abc.c" 
    .text 
    .globl main 
    .type main, @function 
    main: 
    .LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 

    # Load integer 7 (variable a), convert it to double 
    movl $7, -4(%rbp) 
    cvtsi2sd -4(%rbp), %xmm0 

    # Load integer 3, (variable b) convert it to double 
    movl $3, -8(%rbp) 
    cvtsi2sd -8(%rbp), %xmm1 

    # Load integer 2, (variable c) convert it to double 
    movl $2, -12(%rbp) 
    cvtsi2sd -12(%rbp), %xmm2 

    # a/b -> written "div b, a" result goes in a (%xmm0) 
    divsd %xmm1, %xmm0 

    # b * c -> result goes in c (%xmm2) 
    mulsd %xmm0, %xmm2 

    # convert result back to integer 
    cvttsd2si %xmm2, %eax 
    popq %rbp 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
    .LFE0: 
    .size main, .-main 
    .ident "GCC: (Debian 4.6.3-1) 4.6.3" 
    .section .note.GNU-stack,"",@progbits 

在Linux上,你可以編譯運行並顯示結果(截斷爲int,並截斷爲256,因爲它是處理結果)簡單地做:

gcc abc.s ; ./a.out ; echo $? 

爲了使答案更完整,您可以輕鬆地使用舊的FPU寫一個等效的程序(它沒有打擾設置FPU的截斷模式,所以你可能會得到5而不是4是其截斷到最接近的整數):

.file "abc.c" 
    .text 
    .globl main 
    .type main, @function 
main: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 

    # Load integer 7 (variable a), convert it to double 
    movl $7, -4(%rbp) 

    # Load integer 3, (variable b) convert it to double 
    movl $3, -8(%rbp) 

    # Load integer 2, (variable c) convert it to double 
    movl $2, -12(%rbp) 

    fild -12(%rbp) 
    fild -8(%rbp) 
    fild -4(%rbp) 

    # a/b -> written "div b, a" result goes in a (%mm0) 
    fdivp %st(0), %st(1) 

    # b * c -> result goes in c (%mm2) 
    fmulp %st(0), %st(1) 

    # convert result back to integer 
    fist -4(%rbp) 
    movl -4(%rbp), %eax 
    popq %rbp 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE0: 
    .size main, .-main 
    .ident "GCC: (Debian 4.6.3-1) 4.6.3" 
    .section .note.GNU-stack,"",@progbits 
+0

謝謝,你的答案澄清了我很多事情,我正在做整數寄存器操作:\ 無論如何似乎我有麻煩使用rbp寄存器,在網上搜索它似乎是一個64位寄存器,而我必須只使用32 (這是一個學校項目,所以它必須編譯時不需要鏈接引用或修改環境變量)。我試着理解[這個代碼](http://pastebin.com/ArsiDWTx),但我不明白它在「 fmulp%st,%st(1)「有什麼想法?謝謝。 – user1526262 2012-07-15 10:42:49

+0

[這是我到目前爲止](http:// pastebin。COM/KdSpaCEf),但結果是錯誤的,使用X = -1和K1 = 5,它給了我65534而不是-2.5或-2/-3(用於強制轉換) – user1526262 2012-07-15 10:56:51

+0

好吧,我已經解決了[使用此代碼]( http://pastebin.com/T029wpJd),i使用了錯誤的ebp偏移量。 非常感謝解釋kriss,它真的非常有用! – user1526262 2012-07-15 12:53:30