home *** CD-ROM | disk | FTP | other *** search
- ;---------------------------------------------------------------;
- ; Convert.com - Converts either a number or character ;
- ; to complementary radices. ;
- ; Decimal, Hexadecimal, Octal and Binary supported; ASCII too. ;
- ; PC Magazine * Michael J. Mefford ;
- ;---------------------------------------------------------------;
- ;
- ; v1.2 (TapirSoft Gisbert W.Selke):
- ; - expanded to accept 32 bit unsigned integers
- ;
- ; v1.1 (TapirSoft Gisbert W.Selke)
- ; - fixed a bug that screwed up hex input containing the digit B
-
- _Text segment public 'CODE'
- assume cs:_Text,ds:_Text,es:_Text,ss:_Text
- org 100H
- Start: jmp Main
-
- ; DATA AREA
- ; ---------
- Syntax db CR
- Copyright db "CONVERT 1.2 (C) 1989 Ziff Communications Co.",CR,LF
- Programmer db "PC Magazine ",BOX," Michael J. Mefford"
- db "/TapirSoft Gisbert W.Selke",CR,LF,LF
-
- db "Usage: CONVERT <from>[-<to>] | "
- db Quotes,"<char(s)>",Quotes,CR,LF
- db "numbers may have radix (one of b,d,h,o) appended; "
- db "default is d"
- db Ctrl_Z,Backspace,Blank,'$'
-
- Backspace equ 8
- Tab equ 9
- CR equ 13
- LF equ 10
- Ctrl_Z equ 26
- Blank equ ' '
- Quotes equ 34
- Box equ 254
- Space_Cnt equ 5
-
- Invalid_Msg db "Invalid parameter; number range: 0..4294967295"
- db CR,LF,"$"
-
- Radix_Type db "HOB" ;Hex, octal, binary.
- Radix_Cnt equ $ - Radix_Type
-
- Input_Calls dw Decimal_Input, Hex_Input, Octal_Input, Binary_Input
- CALLS_end equ $ - 2
-
- ;
- ; CODE AREA
- ; ---------
-
- Main proc near
- cld ;All string moves forward.
- cmp byte ptr ds:[80H],0 ;Are there parameters?
- jnz Parse ;If yes, continue.
- jmp Error_Exit ;Else, exit with syntax message.
-
- ;------------------------------------------------------------------------------;
- ; Parse the parameters by looking for either carriage return, quotes, or dash. ;
- ;------------------------------------------------------------------------------;
- Parse: mov si,82H ;Point to parameters again.
- Next_Input: mov bp,si ;parameter start.
- NEXT_PARSE: lodsb ;Get a byte.
- cmp al,CR ;Is it carriage return?
- jz Evaluate ;If yes, done here.
- cmp al,Quotes ;Is it quotes?
- jz Character ;If yes, character entry.
- cmp al,"-" ;Is it delimiting dash?
- jnz Next_Parse ;If no, find parameter end.
- cmp bp,82H ;Else, is this first dash?
- jnz Evaluate ;If no, evaluate just the two.
- push si ;Save our position.
- call Get_Number ;Get the parameter.
- pop si ;Restore our position.
- push bx ;Save the number.
- push dx
- jmp short Next_Input ;Get second parameter.
-
- ;-----------------------------------------------------------------------;
- ; If quotes were detected, store up to four characters to be evaluated. ;
- ;-----------------------------------------------------------------------;
- Character: xor bx,bx ;Assume no characters.
- xor dx,dx
- Character1: lodsb ;Get a byte.
- cmp al,CR ;End of parameter?
- jz Got_Char
- cmp al,Quotes ;Is it quotes?
- jnz Character2 ;If no, valid character.
- cmp byte ptr [si],Quotes ;Is it followed by quotes?
- jnz Got_Char ;If no, not quotes in quotes.
- inc si ; skip 2nd quotes
- Character2: or dh,dh ; overflow?
- jnz Error_Exit ; if yes, error exit
- mov dh,dl ; shift new letter in
- mov dl,bh
- mov bh,bl
- mov bl,al
- jmp short Character1 ; netx character
-
- Got_Char: mov ax,bx ;duplicate argument
- mov cx,dx
- jmp short Output ;Convert the string
-
- ;-------------------------------------------------------------;
- ; Find range of numbers and display the complementry radices. ;
- ;-------------------------------------------------------------;
- Evaluate: call Get_Number ;Get the parameter.
- mov ax,bx ; and save it
- mov cx,dx
- cmp bp,82H ;Where there more than one?
- jz Output ;If no, convert just the one.
- pop cx ;Else, retrieve the first one.
- pop ax
- cmp cx,dx ;Is it the larger of the two?
- ja Output ;If yes, find range.
- jb Swap_Range
- cmp ax,bx
- jae Output
- Swap_Range: xchg dx,cx ;Else, swap numbers.
- xchg bx,ax
-
- Output: push ax ; Save upper limit
- push cx
- xor si,si ; si=0: 4-byte; si=1: 2-byte form
- or cx,cx
- jne Output1
- inc si
- Output1: call Decimal_Output ; Display decimal, hexadecimal,
- call Space_It ; octal and binary equivalents
- call Hex_Output ; with spaces in between.
- call Spacing
- call Octal_Output
- call Spacing
- call Binary_Output
- call Spacing
- call Ascii_Output
- mov al,CR
- call PRINT_Char
- mov al,LF
- call Print_Char
- add bx,1 ; Get ready for next number.
- adc dx,0
- pop cx ; get back upper limit
- pop ax
- cmp dx,cx ; are we through?
- jb Output ; no -> loop
- ja Output2 ; yes -> exit
- cmp bx,ax ; maybe; another test...
- jbe Output ; no after all; loop
-
- Output2: xor al,al ;Exit with ErrorLevel of zero.
- jmp short Exit
-
- ;---------------------------------------------------------------------------;
- ; Exit with syntax message and ErrorLevel of 1 if error, else ErrorLevel 0. ;
- ;---------------------------------------------------------------------------;
- Error_Exit: mov dx,offset Syntax ;Display syntax.
- mov ah,9
- int 21h
- mov al,1 ; ErrorLevel 1
- Exit: mov ah,4CH
- int 21H ; Terminate.
- Main endp
-
- ; *************
- ; *SUBROUTINES*
- ; *************
-
- ;------------------------------------------------------------------------------;
- ; INPUT: SI points to byte after parameter end; BP points to parameter start. ;
- ; OUTPUT: DX:BX = number. ;
- ; CALLS: Decimal_Input, Hex_Input, Octal_Input, Binary_Input. ;
- ;------------------------------------------------------------------------------;
- Get_Number proc near
- dec si ;Adjust pointer to parameter end.
- mov cx,si ;Save SI.
- mov si,bp ;Point to parameter start.
- xor ah,ah ; initialize radix to default
- Next_Cap: cmp si,cx ;Are we at end of parameter?
- jz String_Length ;If yes, done here.
- lodsb ;Get a byte.
- cmp al,Blank ; skip blanks
- jz Next_Cap
- cmp al,Tab ; skip tabs
- jz Next_Cap
- cmp al,'a' ; need to capitalize?
- jb Next_Cap1
- cmp al,'z'
- ja Next_Cap1
- and al,5Fh
- mov byte ptr[si-1],al
- Next_Cap1: mov ah,al ; tentatively jot down radix
- jmp short Next_Cap
-
- String_Length: mov si,bp ;Point to parameter start.
- sub cx,bp ;Find parameter length.
- push cx ;Save it.
-
- Next_Radix: mov cx,Radix_Cnt ; Count of radices in CX.
- mov di,offset Radix_Type ; Point to radix collection
- mov al,ah ; retrieve possible radix
- repnz scasb ; Is it one?
- jz Input ;If yes, evaluate.
- mov cx,Radix_Cnt ;default radix
-
- Input: shl cx,1 ;Convert count to word pointer.
- mov di,offset Calls_End ;Point to input calls end.
- sub di,cx ;Point to appropriate call.
- pop cx ;Retrieve parameter length.
- mov si,bp ;Point to parameter start.
- xor bx,bx ;Start with a zero number.
- xor dx,dx
- call [di] ;Get the number.
- jnc End_Number
- mov dx,offset Invalid_Msg ;Print error message if invalid
- mov ah,9
- int 21h
- jmp short Error_Exit
- End_Number: ret ;Else, return with number in BX.
- Get_Number endp
-
- ;----------------------------------------------------------------------;
- ; INPUT: SI points to parameter start; CX = parameter length; BX,DX=0.;
- ; OUTPUT: DX:BX=number; CY= 0 if valid entry; CY = 1 if invalid entry. ;
- ;----------------------------------------------------------------------;
- Decimal_Input proc near
- Next_Decimal: lodsb ;Get a character.
- sub al,"0" ;ASCII to binary.
- jc Loop_Decimal ;If not between 0 and 9, skip.
- cmp al,9
- ja Loop_Decimal
- cbw ;Convert to word.
- shl bx,1 ; multiply old dx:bx by 10
- rcl dx,1
- jc End_Decimal ;If carry, too big.
- push dx
- add ax,bx
- shl bx,1
- rcl dx,1
- jc End_Dec1 ;If carry, too big.
- shl bx,1
- rcl dx,1
- jc End_Dec1 ;If carry, too big.
- add bx,ax
- pop ax
- adc dx,ax
- jc End_Decimal ;If carry, too big.
- Loop_Decimal: loop Next_Decimal
- clc
- jmp short End_Decimal
- End_Dec1: pop ax ; clean up stack
- End_Decimal: ret
- Decimal_Input endp
-
- ;-----------------------------------------------------------------------;
- ; INPUT : SI points to parameter start; CX = parameter length; BX,DX=0.;
- ; OUTPUT : DX:BX=number; CY= 0 if valid entry; CY = 1 if invalid entry. ;
- ;-----------------------------------------------------------------------;
- Binary_Input proc near
- Next_Bin: lodsb ;Get a byte.
- sub al,"0" ;ASCII to binary.
- jc Loop_Bin ;If not 0 or 1, skip.
- cmp al,1
- ja Loop_Bin
- shl bx,1 ;Shift old number left one bit.
- rcl dx,1
- jc End_Bin ;If carry, too big.
- or bl,al ;Else, add it to the number.
- Loop_Bin: loop Next_Bin
- clc
- End_Bin: ret
- Binary_Input endp
-
- ;-----------------------------------------------------------------------;
- ; INPUT : SI points to parameter start; CX = parameter length; BX,DX=0.;
- ; OUTPUT : DX:BX=number; CY= 0 if valid entry; CY = 1 if invalid entry. ;
- ;-----------------------------------------------------------------------;
- Hex_Input proc near
- Next_Hex: lodsb ;Get a byte.
- sub al,"0" ;ASCII to binary.
- jc Loop_Hex ;If below 0, skip.
- cmp al,9 ;Is it 9 or below?
- jle Not_Alpha ;If yes, OK.
- sub al,7 ;Else, adjust for alpha.
- cmp al,10 ;Is it punctuation?
- jb Loop_Hex ;If yes, skip.
- cmp al,15 ;Is it valid?
- ja Loop_Hex ;If no, skip.
- Not_Alpha: test dx,0F000h ;Is the number going to overflow?
- stc ;Assume yes.
- jnz End_Hex ;If yes, too big.
- shl bx,1 ; shift old number left 4 bits
- rcl dx,1
- shl bx,1
- rcl dx,1
- shl bx,1
- rcl dx,1
- shl bx,1
- rcl dx,1
- or bl,al ;Add to number.
- Loop_Hex: loop Next_Hex
- clc
- End_Hex: ret
- Hex_Input endp
-
- ;-----------------------------------------------------------------------;
- ; INPUT : SI points to parameter start; CX = parameter length; BX,DX=0.;
- ; OUTPUT : DX:BX=number; CY= 0 if valid entry; CY = 1 if invalid entry. ;
- ;-----------------------------------------------------------------------;
- Octal_Input proc near
- Next_Octal: lodsb ;Get a byte.
- sub al,"0" ;ASCII to binary.
- jc Loop_Octal ;If not 0 through 7, skip.
- cmp al,7
- ja Loop_Octal
- test dx,0E000h ;Is the number going to overflow?
- stc ;Assume yes.
- jnz End_Octal ;If yes, too big.
- shl bx,1 ; shift old number left 3 bits
- rcl dx,1
- shl bx,1
- rcl dx,1
- shl bx,1
- rcl dx,1
- or bl,al ;Add to number.
- Loop_Octal: loop Next_Octal
- clc
- End_Octal: ret
- Octal_Input endp
-
- ;----------------------------------------;
- ; display number in decimal format ;
- ; INPUT: DX:BX = number ;
- ;----------------------------------------;
- Decimal_Output proc near
- push bx ; save number
- push dx
- xor cx,cx ; zero digit count
- mov ax,10 ; divisor
- mov di,ax
-
- Get_Digits: mov ax,dx ; hi word first;
- xor dx,dx ; supplement with 0 on the left
- div di ; divide; remainder in dx
- xchg ax,bx ; result -> bx; lo word -> ax
- div di ; divide lower half
- xchg dx,bx ; remainder -> bx; hi result->dx
- xchg bx,ax ; remainder -> ax; lo result->bx
- push ax ; one digit on stack
- inc cx ; increment digit count
- or dx,dx ; more to do?
- jnz Get_Digits ; yes -> loop
- or bx,bx
- jnz Get_Digits ; yes -> loop
- mov bl,cl ; Save the number of characters.
-
- Next_Number: pop ax ; Retrieve digit
- call Print_Hex ; And write it
- loop Next_Number ; repeat...
- mov cx,11 ; max # width (assume 4-byte)
- or si,si ; check for 2-byte form
- je Next_Num2 ; skip if 4-byte
- mov cl,Space_Cnt+5 ; no, use 2-byte
- Next_Num2: sub cl,bl ; return with tabbing count
- pop dx ; restore number
- pop bx
- ret
- Decimal_Output endp
-
- ;----------------------------------------;
- ; display number in hex format ;
- ; INPUT: DX:BX = number ;
- ;----------------------------------------;
- Hex_Output proc near
- push bx ; save number
- push dx
- mov cx,0804h ; ch: 8 digits; cl: 4-bit shifts
- mov ax,680Fh ; ah: 'h' radix; al: 1111b mask
- or si,si ; 4-byte form?
- je Hex_Out2 ; yes, skip
- mov dx,bx ; no; shift in lo word
- mov ch,4 ; 4 digits only
- Hex_Out2: call Display_Number
- pop dx ; restore number
- pop bx
- ret
- Hex_Output endp
-
- ;----------------------------------------;
- ; display number in octal format ;
- ; INPUT: DX:BX = number ;
- ;----------------------------------------;
- Octal_Output proc near
- push bx ; save number
- push dx
- mov cx,0A03h ; ch: 10 digits; cl: 3bit shifts
- mov al,03h ; al: 11b mask(!)
- cmp ah,dh ; left bit is special!
- rcl bx,1
- rcl dx,1
- or si,si ; 4-byte form?
- jne Octal_Out1 ; no -> skip
- cmp ah,dh ; yes; 2nd-left bit special, too
- rcl bx,1
- rcl dx,1
- jmp short Octal_Out2
- Octal_Out1: mov ch,5 ; 5 digits for 2-byte form
- mov al,1 ; al: 1b mask(!)
- mov dx,bx ; shift in lo word
- Octal_Out2: and al,bl ; mask bit(s)
- call Print_Hex ; display hi bit(s)
-
- mov ax,6F07h ; ah: 'o' radix; al: 111b mask
- call Display_Number
- pop dx ; retrieve number
- pop bx
- ret
- Octal_Output endp
-
- ;----------------------------------------;
- ; display number in binary format ;
- ; INPUT: DX:BX = number ;
- ;----------------------------------------;
- Binary_Output proc near
- push bx ; save number
- push dx
- mov cx,622Dh ; ch: 'b' radix; cl: '-'separator
- or si,si ; 4-byte form?
- je Binary_Out2 ; yes -> skip
- Binary_Out1: mov dx,bx ; shift in lo word
- xchg ch,cl ; no separator after 16 bits
- Binary_Out2: push cx ; save separators
- mov cx,16 ; digit count (first half)
- Binary_Out3: rol dx,1 ; shift by 1 bit
- mov al,dl ; move for output
- and al,1 ; mask lo bit
- call Print_Hex ; show it
- cmp cl,9 ; mid-word?
- jne Binary_Out4 ; no -> skip
- mov al,'-' ; yes, show separator
- call Print_Char
- Binary_Out4: loop Binary_Out3 ; loop through this word
- pop cx ; get back separators
- mov al,cl ; show one
- call Print_Char
- cmp cl,'b' ; done?
- jne Binary_Out1 ; go for lo word
- pop dx ; retrieve number
- pop bx
- ret
- Binary_Output endp
-
- ;----------------------------------------;
- ; INPUT: DX:BX = number ;
- ;----------------------------------------;
- Ascii_Output proc near
- push bx ; save number
- push dx
- mov dx,bx ; lo word
- mov bx,0070h ;Page zero.
- mov ax,0E22H ;Write TTY a quote mark.
- int 10H ; via BIOS.
-
- mov cx,5 ;Display 5 quotation marks and
- or si,si
- je Ascii_Out2
- mov cl,3
- Ascii_Out2: mov ax,0A22H ; do not update cursor position.
- int 10H
- dec cx ; Display the lowest byte 4 times
- mov al,dl
- int 10H
- dec cx ;Display byte #2 three times
- mov al,dh ; at current cursor position
- int 10H
- pop dx ; get back hi word
- or si,si
- jne Ascii_Out3
- dec cx ;Display byte #3 twice
- mov al,dl
- int 10H
- dec cx ;Display the high byte once
- mov al,dh ; at current cursor position
- int 10H
- Ascii_Out3: pop bx ; retrieve lo word
- ret
- Ascii_Output endp
-
-
- ;----------------------------------------------------------------------------;
- ; Display a complete number ;
- ; INPUT: dx:bx : number to display; ch : number of digits; cl : shift amount ;
- ; ah : terminating radix designator; al : bit mask ;
- ;----------------------------------------------------------------------------;
- Display_Number proc near
- Disp_Num1: push cx ; save masks
- push ax
- xor ch,ch ; first, shifts only
- mov ah,7Fh ; for testing hi bit
- Rotate_Num: cmp ah,dh ; do the shifts
- rcl bx,1
- rcl dx,1
- loop Rotate_Num
- and al,bl ; mask bits
- call Print_Hex ; show digit
- pop ax ; retrieve masks
- pop cx
- dec ch ; are we through?
- jne Disp_Num1 ; no, loop
- mov al,ah ; yes; show radix
- call Print_Char
- Disp_Num2: ret
- Display_Number endp
-
- ;----------------------------------------;
- ; INPUT: al : hex byte to display ;
- ;----------------------------------------;
- Print_Hex proc near
- add al,"0" ;Convert to ASCII.
- cmp al,"9" ;Is it above 9?
- jle Print_Char ;If no, print it.
- add al,7 ;Else, adjust.
-
- ;------------------------------;
- ; Display the character in al ;
- ;------------------------------;
- Print_Char: push dx ; save dx
- mov dl,al
- mov ah,2 ; display on StdOut
- int 21H
- pop dx ; retrieve dx
- ret
- Print_Hex endp
-
- ;---------------------------------------------------------------------------;
- ; print a few spaces: Spacing: standard width; Space_It: as indicated by cx ;
- ;---------------------------------------------------------------------------;
- Spacing proc near
- mov cx,1 ; default: 1
- or si,si ; 2-byte form?
- je Space_It ; no, skip
- mov cx, Space_Cnt ; yes, use wider tabs
- Space_It: mov ah,02 ; outputs and print via DOS.
- push dx ; save dx
- mov dl,Blank ; show blanks
- Space_Loop: int 21h
- loop Space_Loop
- pop dx ; retrieve dx
- ret
- Spacing endp
-
- _Text ends
- end Start
-