RosettaCodeData/Task/Nth/8086-Assembly/nth.8086
2023-07-01 13:44:08 -04:00

58 lines
1.7 KiB
Text

bits 16
cpu 8086
segment .text
org 100h
jmp demo
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Given a number in AX, return string with ordinal suffix
;; in DX.
nth: mov cx,10 ; Divisor
mov bx,.sfx ; Pointer to end of number
.digit: xor dx,dx ; Zero DX
div cx ; AX = DX:AX/10; DX=remainder
add dl,'0' ; Make digit
dec bx ; Back up the pointer
mov [bx],dl ; Store digit
and ax,ax ; Done yet? (AX=0?)
jnz .digit ; If not, get next digit
mov dx,bx ; Keep string pointer in DX
xor bx,bx ; Default suffix is 'th'.
cmp byte [.num+3],'1' ; Is the tens digit '1'?
je .setsfx ; Then the suffix is 'th'.
mov cl,[.num+4] ; Get the ones digit
cmp cl,'4' ; Is it '4' or higher?
jae .setsfx ; Then the suffix is 'th'.
mov bl,cl
sub bl,'0' ; Calculate offset.
shl bl,1 ; [0..3]*2 + .ord
.setsfx: mov ax,[bx+.ordsfx] ; Set suffix
mov [.sfx],ax
ret
.ordsfx: db 'thstndrd'
.num: db '*****'
.sfx: db '**$'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Print numbers.
demo: mov ax,0 ; Starting at 0...
mov bl,26 ; ...print 26 numbers [0..25]
call printn
mov ax,250 ; Starting at 250...
mov bl,16 ; ...print 16 numbers [250..265]
call printn
mov ax,1000 ; Starting at 1000...
mov bl,26 ; ...print 26 numbers [1000..1025]
;; Print BL numbers starting at AX
printn: push ax ; Keep number
push bx ; Keep counter
call nth ; Get string for current AX
mov ah,9 ; MS-DOS print string
int 21h
mov dl,' ' ; Separate numbers by spaces
mov ah,2 ; MS-DOS print character
int 21h
pop bx ; Restore counter
pop ax ; Restore number
inc ax ; Next number
dec bl ; Are we done yet?
jnz printn
ret