2012-11-27 116 views
0

我在裝配中遇到了一些麻煩。 我正在使用程序集IA32。假設-4(%ebp)= x和-8(%ebp)= y,我已經從用戶那裏獲得它們(都是32位長)。 這是代碼:彙編乘法操作64位

format1: .string "Multiply : %u * %u = %llu\n" 
format2: .string "Divide : %u/%u = %u\n" 

# operation multiply 
movl -4(%ebp), %eax 
mull -8(%ebp) 
pushl %edx 
pushl %eax 
pushl -8(%ebp) 
pushl -4(%ebp) 
pushl $format1 
call printf 

# operation divide 
movl -4(%ebp), %eax 
divl -8(%ebp) 
pushl %eax 
pushl -8(%ebp) 
pushl -4(%ebp) 
pushl $format2 
    call printf 

原因乘法的結果是%LLU是因爲我希望能夠乘2個長數字和打印結果,即使達到64個字節。 而且在%edx中,mull命令保存了64字節結果的「其他32個字節」,因此我需要將它推送到堆棧以及printf。 例如我想要這個輸出:

Multiply : 4000000000 * 2 = 16000000000 

另外,我想用4的除法運算返回X.YZ結果。 (在尾數中不超過2個數字,並且不捨入) 例如

Divide : 3/4 = 0.75 

19和1000:

Divide : 19/1000 = 0.01 

和8和2:

Divide : 8/2 = 4.00 

我真的努力了很多得到的結果,但沒有成功。 謝謝ALOT! :)

+2

'4000000000 * 2 = 16000000000'?星球大戰:奔騰反擊? –

+0

只是想舉個例子,我需要能夠得到最大64位的結果。我無法讓這個例子在我的代碼中工作:/ – Jjang

+1

爲什麼?你爲什麼標記這個C或C++?如果你堅持C,你問過你的本地C專家,也就是你的C編譯器,他會怎麼做這樣的事情? (例如使用gcc或clang選項-S產生相當不錯的彙編代碼) –

回答

0

mull爲整數乘法和divl爲整數除法。對於浮點數,您可以使用浮點指令fmulfdiv

的另一種方式做到這一點是因爲傑裏棺材他的意見建議,擴大之前整數乘法每個例如因素。乘以100並將所得整數視爲100 * 100 = 10000倍太大。

0

乘法should work as-is。 如何劃分得到浮點結果我已經answered in your other question。 如果您只需要將它們打印爲兩位數字,則可以使用適當的格式字符串。

更新:工作顯示截斷碼兩位數:

.comm x,4,4 
.comm y,4,4 

.section .rodata 

format1: .string "Div : %d/%d = %.2f\n" 
format2: .string "Mod : %d %% %d = %d\n" 
format3: .string "Multiply : %u * %u = %llu\n" 
format4: .string "%d %d" 
const100: .int 100 

.text 
.globl main 
.type main, @function 
main: 
    subl $32, %esp # allocate space, preserve alignment 

    movl $format4, (%esp) 
    movl $x, 4(%esp) 
    movl $y, 8(%esp) 
    call scanf 

# operation divide 
    fildl x 
    fimul const100 
    fidivl y 
# truncate to integer 
# use this if current FPU rounding mode 
# is known to be truncate 
# frndint 
# otherwise use this 
    fnclex 
    fnstcw (%esp)  # save a copy to modify 
    fnstcw 2(%esp)  # and a copy to preserve 
    orw $0x0c00, (%esp) # rounding mode = truncate 
    fldcw (%esp)  # activate 
    frndint    # do the truncate 
    fldcw 2(%esp)  # restore original 
# end of truncate code 
    fidiv const100 
    fstpl 12(%esp) # x/y 

    movl $format1, (%esp) 
    movl x, %eax 
    movl %eax, 4(%esp) 
    movl y, %eax 
    movl %eax, 8(%esp) 
    call printf 

# operation modulo 
    movl x, %eax 
    cltd 
    idivl y 
    movl $format2, (%esp) 
    movl x, %eax 
    movl %eax, 4(%esp) 
    movl y, %eax 
    movl %eax, 8(%esp) 
    movl %edx, 12(%esp) 
    call printf 

# operation multiply 
    movl x, %eax 
    mull y 
    movl $format3, (%esp) 
    movl x, %ecx 
    movl %ecx, 4(%esp) 
    movl y, %ecx 
    movl %ecx, 8(%esp) 
    movl %eax, 12(%esp) 
    movl %edx, 16(%esp) 
    call printf 

    addl $32, %esp 
    xor %eax, %eax 
    ret 

See in operation

+0

好吧,穆爾不工作:S和關於分歧,我明白你的答案,但我只需要2位數字。你在談論什麼適當的格式? – Jjang

+0

請參見[您的乘法代碼在此處運行](http://ideone.com/nBcKkI)。至於格式字符串,請嘗試使用'%.2f'打印兩位數字。 – Jester

+0

浮動四捨五入的結果,嘗試19和1000.而不是給0.1它給出0.2 .. – Jjang

0

你可以找到一些有用的實例here

下面是一個例子如何相乘 32比特數與輸出位結果[Linux中,GCC]:

#include <stdio.h> 

char *fr = "MUL %u * %u = %llu\n"; 

int main() 
{ 
     __asm__ (
         "subl $0x14, %esp\n\t" 
         "movl $10, %eax\n\t" 
         "movl %eax, 0x4(%esp)\n\t" 
         "movl $100, %ebx\n\t" 
         // Multimpy two 32bit values and save 64bit result in edx:eax 
         "mull %ebx\n\t" 

         // Call printf 
         "movl fr, %esi\n\t" 
         "movl %esi, (%esp)\n\t" 
         "movl %ebx, 0x8(%esp)\n\t" 
         "movl %eax, 0xC(%esp)\n\t" 
         "movl %edx, 0x10(%esp)\n\t" 
         "call printf\n\t" 
         "addl $0x14, %esp\n\t"); 

     return 0; 
} 

gcc -m32 ./ttt.c; ./a.out 
MUL 10 * 100 = 1000 

對於除法,則需要將數據轉換爲浮點值並使用fdiv指令。

PS。 push更改%esp因此您必須對pop執行相同次數的還原堆棧指針。否則,你會得到未定義的行爲。