作为ASM编程的入门者我需要在Assembly中获得2的结果,并且我需要你帮助理解为什么我的程序不能产生我需要的结果(它打印4十进制):
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\msvcrt.inc
includelib \masm32\lib\msvcrt.lib
.data
formatstr db "%d",0
.code
start:
mov eax , 2
mov ecx , 38
mov esi , eax
mov edx , 0
.while TRUE
mul esi
mov esi, edx
add esi, eax
mov edx, 0
mov eax, 2
dec ecx
.break .if (!ecx)
.endw
invoke crt__cprintf, addr formatstr, esi
end start
你可以看到我正在使用masm32编写它(如果在那种情况下有任何问题)。
THX。
答案 0 :(得分:8)
2^38
显然不适合一个32位寄存器,例如eax
。
要存储值2^38
(274877906944
),您需要39位。在32位代码中,您可以使用例如。两个32位寄存器,如edx:eax
。但是,在32位代码mul
中只接受32位因子(例如寄存器,其他的总是eax
),所以使用32位{{1}循环中的中间结果不起作用,因为即使mul
存储64位,也无法将中间结果存储在32位寄存器中再次再次 mul
中的结果。
但您可以使用rcl
来计算,例如。 32位代码中的edx:eax
:
2^38
编辑:受@Jagged O'Neill回答启发的非循环实现。这个没有指数> = 32的跳跃,指数的一次跳跃< 32,也适用于 xor edx,edx
mov eax,2 ; now you have 2 in edx:eax
mov ecx,38 ; 2^n, in this case 2^38 (any value x, 1 <= x <= 63, is valid).
x1: dec ecx ; decrease ecx by 1
jz ready ; if it's 2^1, we are ready.
shl eax,1 ; shift eax left through carry flag (CF) (overflow makes edx:eax zero)
rcl edx,1 ; rotate edx through carry flag (CF) left
jmp x1
ready: ; edx:eax contains now 2^38.
0,ecx
大于63 ecx
到edx:eax
。
0
答案 1 :(得分:2)
在x86上进行乘法运算时,edx
将保留结果的前32位,而eax
将保持最低32位。当你这样做时:
mul esi
mov esi, edx
add esi, eax
结果仅在edx
为0的情况下才有意义,因此mov
/ add
基本上正在mov esi, eax
。如果前32位非零,那么你最终会得到一个相当无意义的上位和下位的混合。