; ToBin.asm

; this program inputs a decimal number 
; and prints out its binary equivalent. 

; convertion is done by convert_to_bin procedure, 
; all other stuff is just for input/output. 


name "ToBin"

org 100h

; skipt data area: 
jmp start

; ascii buffer holds 16 bits of binary equivalent: 
result db 16 dup('x'), 'b'
msg1 db "supported values from -32768 to 65535", 0Dh,0Ah
     db "enter the number: $"

msg2 db 0Dh,0Ah, "converted to binary: $"



start:
; print the message1: 
mov dx, offset msg1
mov ah, 9
int 21h


call scan_num ; get the number to cx. 

mov bx, cx

call convert_to_bin ; convert number in bx to result. 

; print the message2: 
mov dx, offset msg2
mov ah, 9
int 21h


; print the result string backwards: 
mov si, offset result  ; set buffer's address to si. 
mov ah, 0eh            ; teletype function of bios. 
mov cx, 17             ; print 16 bits + suffix 'b'. 
print_me:
	mov al, [si]
	int 10h ; print in teletype mode. 
	inc si
loop print_me



; wait for any key.... 
mov ah, 0
int 16h


ret ; return to operating system. 





; procedure to convert number in bx to its binary equivalent. 
; result is stored in ascii buffer string. 
convert_to_bin    proc     near
pusha

lea di, result

; print result in binary: 
mov cx, 16
print: mov ah, 2   ; print function. 
       mov [di], '0'
       test bx, 1000_0000_0000_0000b  ; test first bit. 
       jz zero
       mov [di], '1'
zero:  shl bx, 1
       inc di
loop print

popa
ret
convert_to_bin   endp




; this macro prints a char in al and advances the current cursor position: 
putc    macro   char
        push    ax
        mov     al, char
        mov     ah, 0eh
        int     10h
        pop     ax
endm

; this procedure gets the multi-digit signed number from the keyboard, 
; and stores the result in cx register: 
scan_num        proc    near
        push    dx
        push    ax
        push    si

        mov     cx, 0

        ; reset flag: 
        mov     cs:make_minus, 0

next_digit:

        ; get char from keyboard 
        ; into al: 
        mov     ah, 00h
        int     16h
        ; and print it: 
        mov     ah, 0eh
        int     10h

        ; check for minus: 
        cmp     al, '-'
        je      set_minus

        ; check for enter key: 
        cmp     al, 13  ; carriage return? 
        jne     not_cr
        jmp     stop_input
not_cr:


        cmp     al, 8                   ; 'backspace' pressed? 
        jne     backspace_checked
        mov     dx, 0                   ; remove last digit by 
        mov     ax, cx                  ; division: 
        div     cs:ten                  ; ax = dx:ax / 10 (dx-rem). 
        mov     cx, ax
        putc    ' '                     ; clear position. 
        putc    8                       ; backspace again. 
        jmp     next_digit
backspace_checked:


        ; allow only digits: 
        cmp     al, '0'
        jae     ok_ae_0
        jmp     remove_not_digit
ok_ae_0:
        cmp     al, '9'
        jbe     ok_digit
remove_not_digit:
        putc    8       ; backspace. 
        putc    ' '     ; clear last entered not digit. 
        putc    8       ; backspace again.         
        jmp     next_digit ; wait for next input.        
ok_digit:


        ; multiply cx by 10 (first time the result is zero) 
        push    ax
        mov     ax, cx
        mul     cs:ten                  ; dx:ax = ax*10 
        mov     cx, ax
        pop     ax

        ; check if the number is too big 
        ; (result should be 16 bits) 
        cmp     dx, 0
        jne     too_big

        ; convert from ascii code: 
        sub     al, 30h

        ; add al to cx: 
        mov     ah, 0
        mov     dx, cx      ; backup, in case the result will be too big. 
        add     cx, ax
        jc      too_big2    ; jump if the number is too big. 

        jmp     next_digit

set_minus:
        mov     cs:make_minus, 1
        jmp     next_digit

too_big2:
        mov     cx, dx      ; restore the backuped value before add. 
        mov     dx, 0       ; dx was zero before backup! 
too_big:
        mov     ax, cx
        div     cs:ten  ; reverse last dx:ax = ax*10, make ax = dx:ax / 10 
        mov     cx, ax
        putc    8       ; backspace. 
        putc    ' '     ; clear last entered digit. 
        putc    8       ; backspace again.         
        jmp     next_digit ; wait for enter/backspace. 


stop_input:
        ; check flag: 
        cmp     cs:make_minus, 0
        je      not_minus
        neg     cx
not_minus:

        pop     si
        pop     ax
        pop     dx
        ret
make_minus      db      ?       ; used as a flag. 
ten             dw      10      ; used as multiplier. 
scan_num        endp




; - Other Assembler Source Codes -



; - asm2html by emu8086 -