2015-05-21 2 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)*...*1. bignum_mul сам умножает каждую цифру на заданное целое число, затем разбивает ее на две части, деля на 10, чтобы получить правильную цифру в качестве остатка и перенос в качестве частного. Последний перемещается в bx и добавляется в следующую итерацию.

bignum_add здесь не используется, это добавило бы два бонуса, используя аналогичную логику для умножения. Остальные - просто помощники, делающие очевидные вещи.

Смежные вопросы