这段代码的算法是如何工作的?
How does the algorithm of this code work?
我在一个旧网站上找到了这段代码(无法访问所有者),它计算用户输入数字的阶乘(最多 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
哪一部分不清楚?
首先,它使用 geti
读取一个整数,该整数利用众所周知的 x = 10*x + c - '0'
公式将字符串转换为数字。
然后它将 bignum 累加器初始化为 1
并在循环中使用 bignum_mul
将其乘以输入数字,倒数到 1
,计算 1*x*(x-1)*(x-2)*...*1
。 bignum_mul
本身将每个数字乘以给定的整数,然后通过除以 10 将其分成两部分,从而得到正确的数字作为余数,进位作为商。后者移入 bx
并在下一次迭代中添加。
bignum_add
在这里没有使用,它会使用与乘法类似的逻辑添加两个 bignums。其余的只是帮手做一些显而易见的事情。
我在一个旧网站上找到了这段代码(无法访问所有者),它计算用户输入数字的阶乘(最多 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
哪一部分不清楚?
首先,它使用 geti
读取一个整数,该整数利用众所周知的 x = 10*x + c - '0'
公式将字符串转换为数字。
然后它将 bignum 累加器初始化为 1
并在循环中使用 bignum_mul
将其乘以输入数字,倒数到 1
,计算 1*x*(x-1)*(x-2)*...*1
。 bignum_mul
本身将每个数字乘以给定的整数,然后通过除以 10 将其分成两部分,从而得到正确的数字作为余数,进位作为商。后者移入 bx
并在下一次迭代中添加。
bignum_add
在这里没有使用,它会使用与乘法类似的逻辑添加两个 bignums。其余的只是帮手做一些显而易见的事情。