3

我已经尝试了 3 个多小时来弄清楚下一个程序出了什么问题。我要做的就是将x除以y,然后打印除法和模数的结果。此外,模数的 printf 和里面的 % 都搞砸了。有谁知道如何解决这个问题?我正在组装 IA32。假设我已经从用户那里得到了 x 和 y。

.section    .rodata
format1:    .string "Div : %d / %d = %d\n"
format2:    .string "Mod : %d % %d = %d\n"

    .text
.globl  main    
    .type   main, @function 

# operation divide
movl    x,  %eax
cltd
idivl   y
pushl   %eax
pushl   y
pushl   x
pushl   $format1
call    printf

# operation modulo
pushl   %edx
pushl   y
pushl   x
pushl   $format2
call    printf

我知道模数应该保存在 %edx 寄存器中,为什么它不起作用?非常感谢!丁:

编辑:好的,所以我将 %edx 保存在 %ebx 中,现在模可以正常工作。(如果我打印 %edx 中的内容,它会给出正确的模数)但是打印到屏幕上仍然不是我想要的。这是 x=2, y=4 的输出:

Divide : 2 / 4 = 0
Modulo : 2 %d = 4

我希望它看起来像这样:

Divide : 2 / 4 = 0.50
Modulo : 2 % 4 = 2
4

2 回答 2

2

EAX、ECX 和 EDX 是调用者保存的寄存器,这意味着必须在调用之前保存它们printf,这可以随意更改这些寄存器中的任何一个而不恢复它们。

另一方面,EBX、ESI 和 EDI 是被调用者保存的,这意味着每个函数都需要将它们恢复到调用前的原始内容。

于 2012-11-24T17:45:17.260 回答
2

根据Intel386 的 System V ABI,允许使用函数%ecx并将%edx其作为临时寄存器,并且被调用者不必为调用者保留它们的值。这意味着,printf允许覆盖 的值%edx,从而破坏 reminer 的值。您可以通过转移%edxto%esi或的值来保存它%edi,根据规范,它们的值必须由被调用者保留(它们“属于”调用者)。

这就是说,你有一个错误format2。您应该将其更改为:

format2:    .string "Mod : %d %% %d = %d\n"

字面%量必须按照%%格式字符串的形式写入,否则将被 . 解释为格式说明符printf

于 2012-11-24T17:46:03.583 回答