(ASSEMBLY MASM) 中大于 12 的数的阶乘
factorial of number greater than 12 in (ASSEMLBY MASM)
我想在 masm 中编写一个程序来查找 1 到 20 之间的任何数字的阶乘,但我的程序对 1 到 12 之间的数字工作正常但不能更大,我的女士告诉我因为你'重新使用不能保存大于 32 位的整数值的 eax 寄存器,因此它将存储你的高位将在 edx 中,低位在 eax 中。
这是我的代码:
.model small
.stack 100h
.386
.data
.code
main proc
mov eax, 13 ;user input, for 12 fac= 479001600, for 13 incorrect
mov ecx,eax
sub eax,eax
mov eax,1
loop1:
mul ecx
loop loop1
call outdec; it will print whatever in eax
main endp
;--------------------------------------------------------------
outdec proc ; Start of my outdec proc working accurately.
push eax
push ebx
push ecx
push edx
cmp eax,0
jge end_if
push eax
mov ah,2
mov dl,'-'
int 21h
pop ax
neg ax
end_if:
mov ebx,10
mov cx,0
rep_loop:
mov dx,0
div ebx
push edx
inc cx
cmp eax,0
jne rep_loop
mov ah,2
prent_loop:
pop edx
add dl,30h
int 21h
loop prent_loop
pop edx
pop ecx
pop ebx
pop eax
ret
outdec endp
end main
;---------------------------------------------------------------
按照女士的建议,我相应地修改了我的代码,但仍然无法得到任何东西
这是我修改后的代码,在 outdec proc
.
中没有发生任何变化
main proc
mov eax, 13 ;user input, for 12 fac= 479001600, for 13 incorrect
mov ecx,eax
sub eax,eax
mov eax,1
loop1:
mul ecx
loop loop1
push edx ; storing numbers of edx in stack
call outdec ; it will print whatever in eax
pop eax ; supplanting values from stack to eax
call outdec ; again calling outdec
main endp
但它除了在最后打印 0 什么也没做。
您没有跟踪循环的每次迭代的 mul
结果的高位双字。由于您要乘以 "backwards"(从 13 开始下降到 1),当您达到 n==2
时,您将得到一个超过 32 位的乘积。那时 eax
变为 1932053504,edx
变为 1。但是您不会在任何地方保存该 1,然后执行循环的最后一次迭代,计算 1932053504 * 1,这将给你 eax == 1932053504
和 edx == 0
.
另一个问题是您将 64 位结果打印为两个单独的 32 位数字。如果您以 base 2 或 base 16 打印它们(尽管在这种情况下您应该先打印 edx
),那会没问题,但是对于 base 10,您将无法获得正确的输出。打印时需要将结果视为单个 64 位值。
这是一个工作实施的示例,以及一些解释更改的注释:
mov ecx, 13 ; n
mov eax,1
xor esi,esi ; will be used to hold the high dword of the 64-bit product
loop1:
mul ecx ; multiply the low dword by ecx
xchg esi,eax ; swap eax and esi temporarily
mov ebx,edx ; save the high dword of eax*ecx
mul ecx ; multiply the high dword by ecx
add eax,ebx ; and add the carry from the low-order multiplication
xchg esi,eax ; swap eax and esi back
loop loop1
call outdec64 ; it will print whatever is in esi:eax
mov ax,0x4c00
int 0x21
;--------------------------------------------------------------
outdec64:
push eax
push ebx
push ecx
push edx
mov ebx,10
mov cx,0
rep_loop:
xor edx,edx ; clear edx prior to the high-order division
xchg esi,eax
div ebx ; divide the high dword of our input by 10, the remainder will carry over to the low-order division
xchg esi,eax
div ebx ; divide the low dword of our input by 10
push edx ; and save the remainder for printing
inc cx
cmp eax,0
jne rep_loop
mov ah,2
prent_loop:
pop edx
add dl,30h
int 21h
loop prent_loop
pop edx
pop ecx
pop ebx
pop eax
ret
我想在 masm 中编写一个程序来查找 1 到 20 之间的任何数字的阶乘,但我的程序对 1 到 12 之间的数字工作正常但不能更大,我的女士告诉我因为你'重新使用不能保存大于 32 位的整数值的 eax 寄存器,因此它将存储你的高位将在 edx 中,低位在 eax 中。 这是我的代码:
.model small
.stack 100h
.386
.data
.code
main proc
mov eax, 13 ;user input, for 12 fac= 479001600, for 13 incorrect
mov ecx,eax
sub eax,eax
mov eax,1
loop1:
mul ecx
loop loop1
call outdec; it will print whatever in eax
main endp
;--------------------------------------------------------------
outdec proc ; Start of my outdec proc working accurately.
push eax
push ebx
push ecx
push edx
cmp eax,0
jge end_if
push eax
mov ah,2
mov dl,'-'
int 21h
pop ax
neg ax
end_if:
mov ebx,10
mov cx,0
rep_loop:
mov dx,0
div ebx
push edx
inc cx
cmp eax,0
jne rep_loop
mov ah,2
prent_loop:
pop edx
add dl,30h
int 21h
loop prent_loop
pop edx
pop ecx
pop ebx
pop eax
ret
outdec endp
end main
;---------------------------------------------------------------
按照女士的建议,我相应地修改了我的代码,但仍然无法得到任何东西
这是我修改后的代码,在 outdec proc
.
main proc
mov eax, 13 ;user input, for 12 fac= 479001600, for 13 incorrect
mov ecx,eax
sub eax,eax
mov eax,1
loop1:
mul ecx
loop loop1
push edx ; storing numbers of edx in stack
call outdec ; it will print whatever in eax
pop eax ; supplanting values from stack to eax
call outdec ; again calling outdec
main endp
但它除了在最后打印 0 什么也没做。
您没有跟踪循环的每次迭代的 mul
结果的高位双字。由于您要乘以 "backwards"(从 13 开始下降到 1),当您达到 n==2
时,您将得到一个超过 32 位的乘积。那时 eax
变为 1932053504,edx
变为 1。但是您不会在任何地方保存该 1,然后执行循环的最后一次迭代,计算 1932053504 * 1,这将给你 eax == 1932053504
和 edx == 0
.
另一个问题是您将 64 位结果打印为两个单独的 32 位数字。如果您以 base 2 或 base 16 打印它们(尽管在这种情况下您应该先打印 edx
),那会没问题,但是对于 base 10,您将无法获得正确的输出。打印时需要将结果视为单个 64 位值。
这是一个工作实施的示例,以及一些解释更改的注释:
mov ecx, 13 ; n
mov eax,1
xor esi,esi ; will be used to hold the high dword of the 64-bit product
loop1:
mul ecx ; multiply the low dword by ecx
xchg esi,eax ; swap eax and esi temporarily
mov ebx,edx ; save the high dword of eax*ecx
mul ecx ; multiply the high dword by ecx
add eax,ebx ; and add the carry from the low-order multiplication
xchg esi,eax ; swap eax and esi back
loop loop1
call outdec64 ; it will print whatever is in esi:eax
mov ax,0x4c00
int 0x21
;--------------------------------------------------------------
outdec64:
push eax
push ebx
push ecx
push edx
mov ebx,10
mov cx,0
rep_loop:
xor edx,edx ; clear edx prior to the high-order division
xchg esi,eax
div ebx ; divide the high dword of our input by 10, the remainder will carry over to the low-order division
xchg esi,eax
div ebx ; divide the low dword of our input by 10
push edx ; and save the remainder for printing
inc cx
cmp eax,0
jne rep_loop
mov ah,2
prent_loop:
pop edx
add dl,30h
int 21h
loop prent_loop
pop edx
pop ecx
pop ebx
pop eax
ret