;This is the example from page 145 of the Byte by Byte text.
;Notice the use of more procedures. Also, there are a couple
;of errors in the text that have been corrected:
;	disp_char must not destroy the ax register
;	the statement ja 9 should be jae 9
		DOSSEG
                .MODEL	SMALL
                .STACK
cr		EQU	0DH
lf		EQU	0AH                                
                .DATA      
msg1		DB	cr,lf,'The binary value of 55379 is $'
msg2		DB	cr,lf,'The binary value of 55379 is $'                                
                .CODE
start:		mov	ax,@DATA                
		mov	ds,ax
                
		lea	dx,msg1
                call	disp_strg
                
		mov	ax,55379
                call	disp_bin
                
		lea	dx,msg2
                call	disp_strg
                
		mov	ax,107
                call	disp_bin
                
		mov	ax,4c00h
                int	21h
                
;set_size sets si equal to 1 or 0, depending on ah
;  si=0 if ah is 0
;  si=1 if ah is not 0                 
;if ah is 0, then the number in ax can be represented
;in a byte. This information will be used later to
;suppress printing the upper byte.          
set_size	proc	near
		xor	si,si	;clear si, assume ah <> 0
                cmp	ah,0
                jne	ss_done
                mov	si,1	;ah = 0, so ax is a byte
ss_done:	ret               
set_size	endp


;print_space determines when to print the space separating
;the upper byte from the lower byte. Only print the space
;if ax is a word and if the first 8 bits have already been
;processed.
;si indicates if ax is a word, cx equal to 8 indicates that
;the bit positions 9 - 15 have already been processed.
print_space	proc	near
		cmp	cx,8		;cx=8 means high byte
                jne	ps_done         ;has been printed already
                cmp	si,1		;si=1 means ax is a byte
                je	ps_done
                mov	dl,' '          ;print space
                call	disp_char
ps_done:	ret
print_space	endp                


;This is the most important procedure. It rotates the number in ax,
;examining the highest bit in ax each time. If the bit is a 1, then
; a '1' is printed, if the bit is a 0, then '0' is printed.
;Also, if the ah register is 0, then only the low byte is processed.
;Also, if ax needs the whole word, then there is a space printed
;between the high byte and the low byte.
disp_bin	proc	near
		push	ax		;be polite:save all registers
                push	bx		;that disp_bin uses
                push	cx		;they will be restored later
                push	dx
                push	si
		
		call	set_size	;si=1 means ax is a byte
                			;si=0 means ax is a word
		mov	cx,16		;16 bits in a register
                			;so set loop counter to 16
                                        ;to process each bit                                        
db_top:		cmp	si,1		;test if ax is a byte
		jne	db_test         ;if not, then process bit
                cmp	cx,9		;test if processing a bit in
                jae	db_bottom       ;in the high byte. If yes then
                			;don't process it
                                        
db_test:	call	print_space	;test if time to print space
		push	ax		;save number on stack
                and	ax,8000h	;isolate highest bit
                jnz	db_one		;if not 0, then print '1'
                mov	dl,'0'		;print '0'               
                jmp	db_print
db_one:		mov	dl,'1'
db_print:	call	disp_char
		pop	ax
db_bottom:	rol	ax,1		;move next bit into high bit
		loop	db_top		;process next bit
                
		pop	si		;be nice
                pop	dx		;restore registers in reverse
                pop	cx		;order of how they were saved
                pop	bx
                pop	ax
		ret
disp_bin	endp


disp_char	proc	near
                push	ax              ;it is very important to be
		mov	ah,02h          ;polite here. If not, then                      
                int	21h             ;this procedure will destroy
                pop	ax              ;the ax register which holds
                ret			;the number being processed
disp_char	endp


disp_strg	proc	near 
                push	ax
		mov	ah,09h
                int	21h
                pop	ax
                ret
disp_strg	endp

		end	start