Sorgente NASM Completo
; factorial.asm - Calcola n! (n ≤ 8 per risultato a 16 bit) ; Build: nasm -f bin factorial.asm -o factorial.com ; Run: DOSBox / FreeDOS / MASM org 100h ; formato .COM section .data prompt db 'Inserisci n (0-8): $' resultMsg db 13,10,'Fattoriale = $' newline db 13,10,'$' num db 0 fact dw 1 section .text start: ; --- Stampa prompt --- mov ah, 09h mov dx, prompt int 21h ; --- Legge una singola cifra (0-9) --- mov ah, 01h int 21h sub al, '0' ; ASCII a binario mov [num], al cmp al, 8 ja error ; n > 8 overflow a 16 bit ; --- Ciclo fattoriale --- mov cx, 1 ; accumulatore = 1 mov bl, [num] ; contatore = n test bl, bl jz print_result ; 0! = 1 fact_loop: mul bl ; AX = AL * BL (ma vogliamo CX * BL) ; Meglio: usa mul a 16 bit mov ax, cx mul bx ; DX:AX = CX * BL mov cx, ax ; risultato in CX (supponi < 65536) dec bl jnz fact_loop print_result: mov ah, 09h mov dx, resultMsg int 21h ; --- Stampa CX come decimale (semplificato: supponi < 10000) --- mov ax, cx call print_ax_dec mov ah, 09h mov dx, newline int 21h ret error: mov ah, 09h mov dx, newline int 21h mov dx, prompt ; riuso come "Non valido" int 21h ret ; --- Subroutine: stampa AX come decimale senza segno --- print_ax_dec: push ax push bx push cx push dx mov bx, 10 mov cx, 0 div_loop: xor dx, dx div bx ; AX/=10, DX=resto push dx ; salva cifra inc cx test ax, ax jnz div_loop print_digits: pop dx add dl, '0' mov ah, 02h int 21h loop print_digits pop dx pop cx pop bx pop ax ret
Spiegazione
- Input: singola cifra (0–8) tramite DOS INT 21h/01h.
- Ciclo: moltiplicazione a 16 bit (MUL BX) accumula in CX.
- Output: stampa decimale tramite divisione ripetuta per 10.
- Limite: 8! = 40.320 rientra a 16 bit; 9! = 362.880 richiede 32 bit.
Alternativa Moderna (Linux x86-64)
; factorial64.asm - NASM, syscall Linux global _start section .data n dq 8 section .text _start: mov rax, 1 mov rcx, [n] test rcx, rcx jz .done .loop: mul rcx dec rcx jnz .loop .done: ; rax = n! (stampa omessa per brevità) mov rax, 60 xor rdi, rdi syscall