装配功率(A,b)功能

时间:2016-10-18 17:56:34

标签: c assembly x86 nasm

我正在尝试根据此c代码制作装配功能(a,b)功能:

int power(int x, int y)
{
    int z;

    z = 1;
    while (y > 0) {
        if ((y % 2) == 1) {
            y = y - 1;
            z = z * x;
        } else {
            y = y / 2;
            x = x * x;
        }
    }

    return z;
}

虽然,由于某种原因,它只能得到一些输出,我无法弄清楚问题出在哪里。这是我的汇编代码:

;* int power(int x, int y);                                                  *
;*****************************************************************************
%define y [ebp+12]
%define x [ebp+8]
%define z [ebp-4]



 power:
push   ebp
mov    ebp,esp
sub    esp,16
mov    byte[ebp-4], 1
jmp    L3;

L1:
mov    eax,[ebp+12]
and    eax,0x1
test   eax,eax
je     L2;
sub    byte[ebp+12],1
mov    eax,[ebp-4]
imul   eax, [ebp+8]
mov    [ebp-4],eax
jmp    L3;

L2:
mov    eax,[ebp+12]
mov    edx,eax
shr    edx,31
 add    eax,edx
sar    eax,1
 mov    [ebp+12],eax
mov    eax,[ebp+8]
imul   eax,[ebp+8]
mov    [ebp+8],eax

L3:
cmp    byte[ebp+12],0
jg     L1;
mov    eax,[ebp-4]
leave  
ret 

当我运行它时,这是我的输出:

power(2, 0) returned -1217218303 - incorrect, should return 1
power(2, 1) returned 2 - correct
power(2, 2) returned -575029244 - incorrect, should return 4
power(2, 3) returned 8 - correct

有人可以帮我弄清楚我哪里出错了,或者纠正我的代码,我们将不胜感激。

1 个答案:

答案 0 :(得分:2)

您正在存储单个字节,然后读回该字节+3个垃圾字节。

%define z [ebp-4]    ; what's the point of this define if you write it out explicitly instead of  mov eax, z?
                     ; should just be a comment if you don't want use it

mov    byte[ebp-4], 1     ; leaves [ebp-3..ebp-1] unmodified
...
mov    eax, [ebp-4]       ; loads 4 bytes, including whatever garbage was there

使用调试器会向您显示此时您在EAX中遇到了垃圾。您可以使用movzx eax, byte [ebp-4]或首先存储4B来修复它。

或者,更好的是,根本不使用任何额外的堆栈内存,因为您可以使用ECX,甚至无需在通常的32位调用约定中保存/恢复它。将您的数据保存在寄存器中,这是他们所需要的。

您的解决方案"使用[ebp+16]正在写入调用者拥有的堆栈空间。你好,我很幸运,碰巧有3个字节的高位归零,我猜,而且它的破坏并没有导致崩溃。

and    eax,1
test   eax,eax

是多余的:test eax, 1就足够了。 (或者如果你想销毁eax,and eax, 1根据结果设置标志。)

您的代码中存在大量其他低效率。