我正在尝试根据此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
有人可以帮我弄清楚我哪里出错了,或者纠正我的代码,我们将不胜感激。
答案 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
根据结果设置标志。)
您的代码中存在大量其他低效率。