组装幂(A,b)函数
Assembly Power(A,b) function
我正在尝试根据以下 C 代码制作一个汇编 power(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
谁能帮我找出我哪里出错了,或者更正我的代码,我们将不胜感激。
您正在存储一个字节,然后读回该字节 + 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 来修复它。
或者,更好的是,根本不使用任何额外的堆栈内存,因为在通常的 32 位调用约定中,您甚至可以在没有 saving/restoring 的情况下使用 ECX。将您的数据保存在寄存器中,这就是它们的用途。
您使用 [ebp+16]
的 "solution" 正在写入调用者拥有的堆栈 space。你只是很幸运,我猜它恰好将高 3 个字节归零,并且破坏它不会导致崩溃。
and eax,1
test eax,eax
是多余的:test eax, 1
就足够了。 (或者如果你想销毁 eax,and eax, 1
根据结果设置标志)。
您的代码中还有大量其他低效率问题。
我正在尝试根据以下 C 代码制作一个汇编 power(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
谁能帮我找出我哪里出错了,或者更正我的代码,我们将不胜感激。
您正在存储一个字节,然后读回该字节 + 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 来修复它。
或者,更好的是,根本不使用任何额外的堆栈内存,因为在通常的 32 位调用约定中,您甚至可以在没有 saving/restoring 的情况下使用 ECX。将您的数据保存在寄存器中,这就是它们的用途。
您使用 [ebp+16]
的 "solution" 正在写入调用者拥有的堆栈 space。你只是很幸运,我猜它恰好将高 3 个字节归零,并且破坏它不会导致崩溃。
and eax,1
test eax,eax
是多余的:test eax, 1
就足够了。 (或者如果你想销毁 eax,and eax, 1
根据结果设置标志)。
您的代码中还有大量其他低效率问题。