2015-05-21 105 views
0

我在旧网站上发现了这个代码(无法访问所有者),它计算用户输入数字的阶乘(最高255),并且它工作正常。我的问题是,我可以弄清算法是如何工作的,但我不明白。如果有人会告诉我它如何在人类语言中起作用,我将不胜感激。这段代码的算法是如何工作的?

data segment 
b1 db 512 dup(0) 
b2 db 512 dup(0) 
msg db 0dh,0ah,"Number:$" 
fac db 0dh,0ah,"Factorial",0dh,0ah,"$" 
data ends 

bignum_get macro var 
local exit,get,loo,skip 
xor cx,cx 
lea si,var 
mov di,si 
mov ah,01h 
get: 
int 21h 
cmp al,0dh 
je exit 
sub al,30h 
mov [si],al 
inc si 
inc cx 
jmp get 
exit: 
shr cx,1 
jz skip 
dec si 
loo: 
mov ah,[si] 
mov al,[di] 
mov [si],al 
mov [di],ah 
dec si 
inc di 
loop loo 
skip: 
endm 

geti macro 
local exit,get 
xor bx,bx 
mov dx,bx 
mov cx,00ah 
get: 
push bx 
;Read character 
mov ah,01h 
int 21h 
xor ah,ah 
pop bx 
;If enter stop 
cmp al,0dh 
jz exit 
sub al,30h 
;Multply By 10 
push ax 
mov ax,bx 
mul cx 
mov bx,ax 
pop ax 
;add 
add bx,ax 
;redo 
jmp get 
exit: 
mov ax,bx 
endm 

bignum_put macro var 
local put,en,nxt,exit 
lea si,var 
mov di,si 
mov cx,0200h 
add di,cx 
dec di 
en: 
cmp BYTE PTR [di],00h 
jne nxt 
dec di 
jmp en 
nxt: 
mov ah,02h 
put: 
mov dl,[di] 
add dl,30h 
int 21h 
cmp si,di 
je exit 
dec di 
loop put 
exit: 
endm 



bignum_add macro b1,b2 
local ader,exit 
lea si,b1 
lea di,b2 

mov cx,0200h 
mov bl,10 
ader: 
mov al,[di] 
mov ah,[si] 
add al,ah 
jz exit 
xor ah,ah 
div bl 
mov [si],ah 
inc si 
add [si],al 
inc di 
loop ader 
exit: 
endm 

bignum_mul macro b1 
local loo,exit 
cmp dl,01h 
jz exit 
lea si,b1 
mov dh,10 
xor bx,bx 
mov cx,0200h 
loo: 
mov al,[si] 
xor ah,ah 
mul dl 
add ax,bx 
div dh 
mov [si],ah 
inc si 
mov bl,al 
loop loo 
exit: 
endm 

puts macro msg 
push ax 
push dx 
mov dx,offset msg 
mov ah,09h 
int 21h 
pop dx 
pop ax 
endm 


assume cs:code,ds:data 
code segment 
start: 
mov ax,data 
mov ds,ax 

lea si,b1 
mov BYTE PTR [si],01h 

puts msg 
geti 
mov dl,al 
loo: 
push dx 
bignum_mul b1 
pop dx 
dec dl 
jnz loo 

puts fac 
bignum_put b1 
mov ah,4ch 
int 21h 
code ends 
end start 

回答

1

哪一部分不清楚? 首先它使用geti读取一个整数,该整数利用众所周知的x = 10*x + c - '0'公式将字符串转换为数字。 然后它将bignum累加器初始化为1,并将其乘以输入数字,使用bignum_mul作为循环,倒数至1,计算1*x*(x-1)*(x-2)*...*1bignum_mul本身将每个数字乘以给定的整数,然后通过除以10将它分成两个,因此它获得正确的数字作为余数和进位作为商。后者转移到bx并在下一次迭代中添加。

bignum_add这里没有用到,它会添加两个使用类似逻辑的乘法运算。其余的只是助手做着明显的事情。