0

我在装配中的以下操作时遇到了一些麻烦。我正在组装 IA32。假设 -4(%ebp)=x 和 -8(%ebp)=y 我已经从用户那里得到它们。这是代码:

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

另外,我希望 3 与 4 的除法运算返回 X.YZ 结果。(尾数中不超过 2 个数字,并且不四舍五入)例如

Divide : 3 / 4 = 0.75

对于 19 和 1000:

Divide : 19 / 1000 = 0.01

对于 8 和 2:

Divide : 8 / 2 = 4.00

我真的很努力地得到结果,但没有成功。多谢!:)

4

1 回答 1

1

是的,您当然可以使用scanf,只需传递正确的参数即可。如您所知,对于浮点结果,您需要使用一些浮点除法和浮点格式进行打印。

请注意,根据调用约定,您应该保留ebx寄存器的值。此外,您应该保持堆栈平衡,最好对齐。

一个可能的解决方案:

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

.section    .rodata

format1:    .string "Div : %d / %d = %g\n"
format2:    .string "Mod : %d %% %d = %d\n"
format3:    .string "%d %d"

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

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

# operation divide
    fildl x
    fidivl y
    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

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

请参阅运行中的代码

于 2012-11-25T20:02:20.030 回答