装配模数

时间:2012-11-24 17:31:25

标签: c assembly modulo

我已经尝试了3个多小时来弄清楚下一个程序出了什么问题。 我所要做的就是将y除以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寄存器中,为什么它不起作用? 非常感谢! d:

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

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

我希望它看起来像这样:

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

2 个答案:

答案 0 :(得分:2)

EAX,ECX和EDX是调用者保存的寄存器,这意味着必须在调用printf之前保存它们,{{1}}可以自由更改任何这些寄存器而无需恢复它们。

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

答案 1 :(得分:2)

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

这就是说,format2中有错误。你应该把它改成:

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

文字%必须在格式字符串中写为%%,否则它将被printf描述为格式说明符。