dos_compilers/Microsoft MASM v5/E.ASM
2024-07-24 21:33:05 -07:00

244 lines
5.7 KiB
NASM

; 8086 assembly to compute e to n digits.
; When DIGITS is 200, the first 192 digits are displayed:
; 271828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319
;
; equivalent to:
; program e;
; const
; DIGITS = 200;
; type
; arrayType = array[ 0..DIGITS ] of integer;
; var
; high, n, x : integer;
; a : arrayType;
; begin
; high := DIGITS;
; x := 0;
; n := high - 1;
; while n > 0 do begin
; a[ n ] := 1;
; n := n - 1;
; end;
;
; a[ 1 ] := 2;
; a[ 0 ] := 0;
;
; while high > 9 do begin
; high := high - 1;
; n := high;
; while 0 <> n do begin
; a[ n ] := x MOD n;
; x := 10 * a[ n - 1 ] + x DIV n;
; n := n - 1;
; end;
;
; Write( x );
; end;
;
; writeln; writeln( 'done' );
; end.
; build with masm 5.0 like this:
; ntvdm -h masm /Zi /Zd /z /l %1,,,;
; ntvdm -h link %1,,%1,,nul.def
;
dosseg
.model small
.stack 100h
; DOS constants
dos_write_char equ 2h
dos_realtime_clock equ 1ah
dos_exit equ 4ch
; app constants
true equ 1
false equ 0
digits equ 200
e_dataseg segment para public 'data'
assume ds: e_dataseg
crlfmsg db 13,10,0
donemsg db 'done',13,10,0
align 16
array db digits dup( ? )
e_dataseg ends
.code
start:
mov ax, e_dataseg
mov ds, ax
; while n > 0 do begin
; a[ n ] := 1;
; n := n - 1;
; end;
mov al, 1
mov ah, 1
push ds
pop es
mov di, offset array
mov cx, ( digits / 2 )
cld
rep stosw
; a[ 1 ] := 2;
; a[ 0 ] := 0;
mov di, offset array
mov byte ptr[ di + 1 ], 2
mov byte ptr[ di ], 0
mov cl, 10
; register bx is n. register si is high. register di is x at the start of each inner loop
mov si, DIGITS
outerloop:
dec si ; high := high - 1;
mov bx, si ; n := high;
xor di, di ; x := 0;
innerloop:
mov ax, di
div bl ; computes both x MOD n and x DIV n. ah has remainder, al has quotient
mov byte ptr[ offset array + bx ], ah ; a[ n ] := x MOD n;
xor ah, ah
mov di, ax ; save the quotient in di.
mov al, byte ptr [ offset array + bx - 1 ] ; load a[ n - 1 ]
mul cl
add di, ax ; x := 10 * a[ n - 1 ] + x DIV n;
dec bx ; n := n - 1;
jnz innerloop ; if n isn't 0 then loop again
mov ax, di
call printint ; show the next digit(s) of e
cmp si, 9 ; while high > 9 do begin (re-written as a do until loop)
jnz outerloop
call printcrlf
mov dx, offset donemsg
call printstring
mov al, 0
mov ah, dos_exit
int 21h
;start endp
; print the integer in ax
printint proc near
test ah, 80h
push ax
push bx
push cx
push dx
push di
push si
jz _prpositive
neg ax ; just one instruction for complement + 1
push ax
mov dx, '-'
mov ah, dos_write_char
int 21h
pop ax
_prpositive:
xor cx, cx
xor dx, dx
cmp ax, 0
je _przero
_prlabel1:
cmp ax, 0
je _prprint1
mov bx, 10
div bx
push dx
inc cx
xor dx, dx
jmp _prlabel1
_prprint1:
cmp cx, 0
je _prexit
pop dx
add dx, 48
mov ah, dos_write_char
int 21h
dec cx
jmp _prprint1
_przero:
mov dx, '0'
mov ah, dos_write_char
int 21h
_prexit:
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
printint endp
printcrlf proc near
push ax
push bx
push cx
push dx
push di
push si
mov dx, offset crlfmsg
call printstring
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
printcrlf endp
printstring proc near
push ax
push bx
push cx
push dx
push di
push si
mov di, dx
_psnext:
mov al, byte ptr [ di ]
cmp al, 0
je _psdone
mov dx, ax
mov ah, dos_write_char
int 21h
inc di
jmp _psnext
_psdone:
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
printstring endp
end