2012-11-27 118 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执行相同次数的还原堆栈指针。否则,你会得到未定义的行为。