RosettaCodeData/Task/Binary-digits/8086-Assembly/binary-digits.8086

86 lines
1.7 KiB
Plaintext

.model small
.stack 1024
.data
TestData0 byte 5,255 ;255 is the terminator
TestData1 byte 5,0,255
TestData2 byte 9,0,0,0,255
.code
start:
mov ax,@data
mov ds,ax
cld ;String functions are set to auto-increment
mov ax,2 ;clear screen by setting video mode to 0
int 10h ;select text mode - We're already in it, so this clears the screen
mov si,offset TestData0
call PrintBinary_NoLeadingZeroes
mov si,offset TestData1
call PrintBinary_NoLeadingZeroes
mov si,offset TestData2
call PrintBinary_NoLeadingZeroes
ExitDOS:
mov ax,4C00h ;return to dos
int 21h
PrintBinary_NoLeadingZeroes proc
;input: DS:SI = seg:offset of a 255-terminated sequence of unpacked BCD digits, stored big-endian
;setup
mov bx,8000h
;bl will be our "can we print zeroes yet" flag.
;bh is the "revolving bit mask" - we'll compare each bit to it, then rotate it right once.
; It's very handy because it's a self-resetting loop counter as well!
NextDigit:
lodsb
cmp al,255
je Terminated
NextBit:
test al,bh ;is the bit we're testing right now set?
jz PrintZero
;else, print one
push ax
mov dl,'1' ;31h
mov ah,2
int 21h ;prints the ascii code in DL
pop ax
or bl,1 ;set "we've printed a one" flag
jmp predicate
PrintZero:
test bl,bl
jz predicate
push ax
mov dl,'0' ;30h
mov ah,2
int 21h
pop ax
predicate:
ror bh,1
jnc NextBit
;if the carry is set, we've rotated BH back to 10000000b,
; so move on to the next digit in that case.
jmp NextDigit
Terminated:
push ax
mov ah,2
mov dl,13 ;carriage return
int 21h
mov dl,10 ;linefeed
int 21h
pop ax
ret
PrintBinary_NoLeadingZeroes endp