Metropoli BBS
VIEWER: d2h.asm MODE: TEXT (ASCII)
;****************************************************************************
; D2H displays a decimal number in hexadecimal format. Its syntax is:
;
;       D2H decimal-value
;
; where "decimal-value" is a decimal value from 0 to 4,294,967,295.
;****************************************************************************

code            segment
                assume  cs:code,ds:code
                org     100h
begin:          jmp     main

helpmsg         db      "Displays a decimal number in hexadecimal format."
                db      13,10,13,10
                db      "D2H decimal-value",13,10,"$"

errmsg1         db      "Syntax: H2D decimal-value",13,10,"$"
errmsg2         db      "Invalid digit",13,10,"$"
errmsg3         db      "Number too large (cannot exceed 4,294,967,295)"
crlf            db      13,10,"$"

ten             dw      10                      ;Base 10 multiplier
sixteen         dw      16                      ;Base 16 divisor
loword          dw      0                       ;Accumulator (low word)
hiword          dw      0                       ;Accumulator (high word)

;****************************************************************************
; Procedure MAIN
;****************************************************************************

main            proc    near
                cld                             ;Clear direction flag
                mov     si,81h                  ;Point SI to the command line
                call    scanhelp                ;Scan for a "/?" switch
                jnc     main1                   ;Branch if not found

                mov     ah,09h                  ;Display help text
                mov     dx,offset helpmsg
                int     21h
                jmp     exit                    ;Exit

main1:          call    findchar                ;Find the start of the string
                jc      error1                  ;Error if there is no string

main2:          lodsb                           ;Get the next digit
                cmp     al,","                  ;Ignore commas
                je      main2
                cmp     al,20h                  ;Exit if it's a space, tab,
                je      main4                   ;or end-of-line character
                cmp     al,09h
                je      main4
                cmp     al,0Dh
                je      main4

                cmp     al,"0"                  ;Error if digit is invalid
                jb      error2
                cmp     al,"9"
                ja      error2

                xor     ah,ah                   ;Byte to word in AX
                sub     al,"0"                  ;Convert ASCII to binary
                push    ax                      ;Save result for later

                mov     ax,loword               ;Add the digit to what
                mul     ten                     ;we've already accumulated
                push    dx
                mov     bx,ax                   ;Low word
                mov     ax,hiword
                mul     ten
                jo      error3
                pop     dx
                add     ax,dx
                jc      error4
                mov     cx,ax                   ;High word
                pop     ax
                add     bx,ax
                adc     cx,0
                jc      error5
                mov     loword,bx
                mov     hiword,cx
                jmp     main2

main4:          mov     bx,loword               ;Display the number in
                mov     ax,hiword               ;hex format
                call    bin2hex

exit:           mov     ax,4C00h                ;Return to DOS
                int     21h
;
; Error handling routines.
;
error1:         mov     dx,offset errmsg1
                jmp     short error
error2:         mov     dx,offset errmsg2
                jmp     short error
error3:         add     sp,2
error4:         add     sp,2
error5:         mov     dx,offset errmsg3
error:          mov     ah,09h
                int     21h
                jmp     exit
main            endp

;****************************************************************************
; BIN2HEX displays the number in AX:BX in hexadecimal format.
;****************************************************************************

bin2hex         proc    near
                xor     cx,cx

b2h1:           xor     dx,dx
                div     sixteen
                mov     si,ax
                mov     ax,bx
                div     sixteen
                mov     bx,ax
                mov     ax,si
                inc     cx
                push    dx
                or      ax,ax
                jnz     b2h1
                or      bx,ax
                jnz     b2h1

b2h2:           mov     ah,02h
                pop     dx
                add     dl,"0"
                cmp     dl,"9"
                jbe     b2h3
                add     dl,7
b2h3:           int     21h
                loop    b2h2

                mov     ah,09h
                mov     dx,offset crlf
                int     21h
                ret
bin2hex         endp

;****************************************************************************
; FINDCHAR advances SI to the next non-white-space character. On return,
; carry set indicates EOL was encountered; carry clear indicates it was not.
;****************************************************************************

findchar        proc    near
                lodsb                           ;Get the next character
                cmp     al,09h                  ;Loop if tab
                je      findchar
                cmp     al,20h                  ;Loop if space
                je      findchar
                cmp     al,2Ch                  ;Loop if comma
                je      findchar
                dec     si                      ;Point SI to the character
                cmp     al,0Dh                  ;Exit with carry set if end
                je      eol                     ;of line is reached

                clc                             ;Clear carry and exit
                ret

eol:            stc                             ;Set carry and exit
                ret
findchar        endp

;****************************************************************************
; SCANHELP scans the command line for a /? switch. If the switch is found,
; carry returns set and SI contains the switch offset. If the switch is not
; found, carry returns clear.
;****************************************************************************

scanhelp        proc    near
                push    si                      ;Save SI
scanloop:       lodsb                           ;Get a character
                cmp     al,0Dh                  ;Exit if end of line
                je      scan_exit
                cmp     al,"?"                  ;Loop if not "?"
                jne     scanloop
                cmp     byte ptr [si-2],"/"     ;Loop if not "/"
                jne     scanloop

                add     sp,2                    ;Clear the stack
                sub     si,2                    ;Adjust SI
                stc                             ;Set carry and exit
                ret

scan_exit:      pop     si                      ;Restore SI
                clc                             ;Clear carry and exit
                ret
scanhelp        endp

code            ends
                end     begin
[ RETURN TO DIRECTORY ]