2015-05-21 30 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這裏沒有用到,它會添加兩個使用類似邏輯的乘法運算。其餘的只是助手做着明顯的事情。