home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
math
/
numvert.asm
< prev
next >
Wrap
Assembly Source File
|
1992-12-07
|
22KB
|
399 lines
;; NUMVERT.ASM
;;
;; Useful decimal, hexidecimal and binary conversion routines.
;;
;; This program can be assembled using the A86 or TASM assemblers
;;
;; Not tested with Masm, should work?
;;
;; This code is "PUBLIC DOMAIN"
;;
;; by William Cravener 12/07/92
;;
;---------------------------------------------------------
;;
code SEGMENT
ASSUME cs:code, ds:code, es:code, ss:code
ORG 100h ; COM files begin here
start:
jmp begin
;;
;----------------------------------------------------------------
;;
input_buffer DB 18 ; maximum of 18 numbers
DB 0 ; actual length of input
DB 19 DUP (0) ; room for carriage
;;
decimal DB 'DECIMAL = ', 0
hexidecimal DB ' HEX = ', 0
binary DB ' BINARY = ', 0
;;
explain DB 0dh, 0ah, 'Number Conversion by »-Swift-Ware-', 0dh, 0ah
DB 0dh, 0ah, 'Decimal to - 65535'
DB 0dh, 0ah, 'Hexidecimal to - FFFFH'
DB 0dh, 0ah, 'Binary to - 1111111111111111B'
DB 0dh, 0ah, 'Include H or B at end of number.'
DB 0dh, 0ah, 0ah, 'Enter number: $'
;;
;----------------------------------------------------------------;
;;
begin:
call clear_screen ; first clear the screen
mov dx, OFFSET explain ; point to explanation
mov ah, 9 ; display string function
int 21h ; the interrupt
mov dx, OFFSET input_buffer ; point to buffer storage
push dx ; save pointer on stack
mov ah, 0ah ; use DOS buffered input
int 21h ; the interrupt
pop di ; pop pointer into DI
inc di ; point to input length
push di ; save new pointer location
mov cl, BYTE PTR [di] ; place input length in CL
add di, cx ; add length to offset
cmp BYTE PTR [di], 'a' ; is it uppercase?
jb isup ; if neccessary
cmp BYTE PTR [di], 'z' ; make it so
ja isup ; by -
sub BYTE PTR [di], 20h ; subtraction
isup:
cmp BYTE PTR [di], 'B' ; is it a binary number?
je be_binary_number ; yes - need binary convert
cmp BYTE PTR [di], 'H' ; is it a hexidecimal number
je be_hexidecimal_number ; yes - need hex convert
be_decimal_number:
inc di ; wasn't the above must be decimal
mov BYTE PTR [di], 0 ; end input string with a "0"
pop si ; pop saved pointer into SI
inc si ; point to beginning of string
call ascdec_2_bin ; make it a binary value
jmp show_the_numbers ; show all three converted formats
be_binary_number:
mov BYTE PTR [di], 0 ; end input string with a "0"
pop si ; pop saved pointer into SI
inc si ; point to beginning of string
dec cx ; binary routine needs number of chars
call ascbin_2_bin ; make it a binary value
jmp show_the_numbers ; show all three converted formats
be_hexidecimal_number:
mov BYTE PTR [di], 0 ; end input string with a "0"
pop si ; pop saved pointer into SI
inc si ; point to beginning of string
call aschex_2_bin ; make it a binary value
show_the_numbers:
call cr_lf ; do a CR LF pair
call show_decimal ; display as a ASCII decimal
call show_hexidecimal ; display as a ASCII hexidecimal
call show_binary ; display as a ASCII binary
int 20h ; finished exit to DOS
;----------------------------------
show_decimal: ; routine displays ascii decimal
push dx ; save binary value on stack
call cr_lf ; do a CR LF pair
push si ; save buffer pointer
mov si, OFFSET decimal ; point to DECIMAL =
call write_string ; write it to screen
pop si ; pop buffer pointer off stack
call bin_2_ascdec ; make DX value a ascii decimal
call write_string ; write it to screen
call cr_lf ; do a CR LF pair
pop dx ; retrieve binary value off stack
ret
show_hexidecimal: ; routine displays ascii hexidecimal
push dx ; save binary value on stack
call cr_lf ; do a CR LF pair
push si ; save buffer pointer
mov si, OFFSET hexidecimal ; point to HEX =
call write_string ; write it to screen
pop si ; pop buffer pointer off stack
call bin_2_aschex ; make DX value a ascii decimal
call write_string ; write it to screen
call cr_lf ; do a CR LF pair
pop dx ; retrieve binary value off stack
ret
show_binary: ; routine displays ascii binary
push dx ; save binary value on stack
call cr_lf ; do a CR LF pair
push si ; save buffer pointer
mov si, OFFSET binary ; point to BINARY =
call write_string ; write it to screen
pop si ; pop buffer pointer off stack
call bin_2_ascbin ; make DX value a ascii decimal
call write_string ; write it to screen
call cr_lf ; do a CR LF pair
pop dx ; retrieve binary value off stack
ret
;----------------------------------
write_string: ; BIO's teletype function
push si ; save SI on stack
mov ah, 0eh ; to monitor
mov bh, 0 ; page 0
num_jump:
lodsb ; get character
cmp al, 0 ; 0 if end of string
je done ; done if so
int 10h
jmp num_jump ; get another character
done:
pop si ; retrieve SI from stack
ret
;----------------------------------
cr_lf: ; CR LF routine
mov ah, 0eh ; BIO's teletype function
mov bh, 0
mov al, 0dh ; carriage
int 10h ; do it
mov ah, 0eh
mov al, 0ah ; linefeed
int 10h ; do it
ret
;----------------------------------
clear_screen: ; clears screen routine
mov ah, 8 ; retrieve attribute function
mov bh, 0 ; page 0
int 10h
mov bh, ah ; current screen color
mov ah, 6 ; scroll function
mov al, 0 ; whole screen
mov cx, 0 ; upper left
mov dx, 184fh ; lower right
int 10h
mov ah, 2 ; set cursor
mov bh, 0 ; page 0
mov dx, 0 ; top left
int 10h
ret
;================================================================;
;================================================================;
; NUMBER CONVERTING SUBROUTINES FROM HERE DOWN. ;
; ;
; BIN_2_ASCDEC ----- binary to ascii decimal. ;
; ;
; BIN_2_ASCHEX ----- binary to ascii hexidecimal. ;
; ;
; BIN_2_ASCBIN ----- binary to ascii binary. ;
; ;
; ASCDEC_2_BIN ----- ascii decimal to binary. ;
; ;
; ASCHEX_2_BIN ----- ascii hexidecimal to binary. ;
; ;
; ASCBIN_2_BIN ----- ascii binary to binary. ;
; ;
;================================================================;
;================================================================;
;----------------------------------------------------------------;
; Convert 16-bit binary in DX register to ASCII decimal number. ;
; ;
; On entry: ;
; SI - points to 6 byte output buffer. ;
; DX = 16 bit binary number. ;
; On return: ;
; SI - points to resulting ASCII decimal number. ;
;----------------------------------------------------------------;
bin_2_ascdec:
mov di, si ; copy SI into DI
mov cx, 6 ; 6 digits to clear
mov al, 0 ; fill it with "0"s
cld ; forward direction
repe stosb ; clear 6 places
sub di, 2 ; left 2 for start address
std ; store in reverse order
make_it_ascii:
mov ax, dx ; add in numerator
mov dx, 0 ; clear top half
mov cx, 10 ; enter decimal divisor
div cx ; perform division AX/CX
xchg ax, dx ; get quotient
add al, 30h ; make digit ASCII
stosb ; store digit in buffer
cmp dx, 0 ; test for end of binary
jnz make_it_ascii ; continue if not end
inc di ; right 1 for beginning
mov si, di ; SI = start of number string
cld ; restore direction flag
ret
;----------------------------------------------------------------;
; Convert a 16-bit binary in the DX register to an ASCII ;
; hexadecimal number. ;
; ;
; On entry: ;
; SI - points to 6 byte output buffer. ;
; DX = 16 bit binary number. ;
; On return: ;
; SI - points to resulting ASCII hexidecimal number. ;
; ( number ends with H ) ;
;----------------------------------------------------------------;
bin_2_aschex:
mov di, si ; copy SI into DI
push di ; save user's buffer pointer
mov cx, 6 ; 6 digits to clear
mov al, 0 ; fill it with "0"s
cld ; forward direction
repe stosb ; clear 6 places
sub di, 2 ; left 2 for "H"
mov BYTE PTR [di], 'H' ; place "H" in buffer
pop di ; restore buffer pointer
mov cx, 4 ; count 4 digits
hex_cvr:
push cx ; save counter
mov cl, 4 ; 4 digits
rol dx, cl ; rotate source left
mov al, dl ; move digit into AL
and al, 15 ; clear high nibble
daa ; adjust AL if A through F
add al, 240 ; and bump the carry
adc al, 40h ; convert hex to ASCII
stosb ; store in buffer
pop cx ; restore digit counter
loop hex_cvr ; continue with next digit
ret
;-------------------------------------------------------------------;
; Convert a 16-bit binary number in DX into 16 ASCII binary digits. ;
; ;
; On entry: ;
; SI - points to 18 byte output buffer. ;
; DX = 16 bit binary number. ;
; On return: ;
; SI - points to resulting ASCII binary number. ;
; ( number ends with B ) ;
;-------------------------------------------------------------------;
bin_2_ascbin:
mov di, si ; copy SI into DI
push di ; save user's buffer pointer
mov cx, 18 ; 18 digits to clear
mov al, 0 ; fill it with "0"s
cld ; forward direction
repe stosb ; clear 18 digits
sub di, 2 ; left 2 for "B"
mov BYTE PTR [di], 'B' ; place "B" in buffer
pop di ; start of buffer
mov cx, 8 ; convert 8 bits of MSB
bin_cvr_dh:
test dh, 128 ; test high-order bit
jnz set_1_dh ; go set bit
mov BYTE PTR [di], '0' ; set bit to 0
jmp next_bin_dh
set_1_dh:
mov BYTE PTR [di], '1' ; set bit to 1
next_bin_dh:
inc di ; bump pointer
sal dh, 1 ; shift bits left once
loop bin_cvr_dh ; do all of DH
mov cx, 8 ; convert 8 bits of LSB
bin_cvr_dl:
test dl, 128 ; test high-order bit
jnz set_1_dl ; go set bit
mov BYTE PTR [di], '0' ; set bit to 0
jmp next_bin_dl
set_1_dl:
mov BYTE PTR [di], '1' ; set bit to 1
next_bin_dl:
inc di ; bump pointer
sal dl, 1 ; shift bits left once
loop bin_cvr_dl ; do all of DL
ret
;------------------------------------------------------;
; Convert an ASCII decimal number to a binary value. ;
; ;
; On entry: ;
; SI - points to 5 digit ASCII decimal string. ;
; ( range 0 to 65535 ) ;
; On return: ;
; DX = resulting binary value. ;
;------------------------------------------------------;
ascdec_2_bin:
push si ; save pointer to buffer
mov dx, 0 ; Clear binary output
ascdecbin:
lodsb ; get ascii value into AL
sub al, 30h ; ASCII to decimal
jl not_ascii ; exit if invalid ASCII
cmp al, 9 ; test for highest value
jg not_ascii ; exit if larger than 9
cbw ; byte to Word
push ax ; save digit in stack
mov ax, dx ; move into output register
mov cx, 10 ; decimal multiplier
mul cx ; perform AX = AX * 10
mov dx, ax ; move product to output register
pop ax ; restore decimal digit
add dx, ax ; add in digit
jmp ascdecbin ; continue
not_ascii:
pop si ; restore start of buffer
ret
;----------------------------------------------------------;
; Convert an ASCII hexidecimal number to a binary value. ;
; ;
; On entry: ;
; SI - points to 4 digit ASCII hexidecimal string. ;
; ( range 0 to FFFF ) ;
; On return: ;
; DX = resulting binary value. ;
;----------------------------------------------------------;
aschex_2_bin:
push si ; save pointer to buffer
mov dx, 0 ; clear binary output
aschexbin:
lodsb ; get ASCII digit
cmp al, '0' ; is it less then "0"
jb ascii_not ; yes - invalid character
cmp al, '9' ; equal or less then "9"
jbe strip ; yes - go strip high 4 bits
and al, 5fh ; make letter upper case
cmp al, 'A' ; less then ascii "A"
jb ascii_not ; yes - invalid character
cmp al, 'F' ; greater then ascii "F"
ja ascii_not ; yes - invalid character
add al, 9 ; its good add 9 for strip
strip:
and al, 0fh ; strip off the high 4 bits
mov cl, 4 ; set shift count
shl dx, cl ; rotate DX 4 bits
xor ah, ah ; zero out AH
add dx, ax ; add digit to value
jmp aschexbin ; continue
ascii_not:
pop si ; restore start of buffer
ret
;-----------------------------------------------------------;
; Convert a 16-digit ASCII binary number to a binary value. ;
; ;
; On entry: ;
; SI - points to 16 character ASCII binary string. ;
; ( range 0 to 1111111111111111 ) ;
; CX = Length of ASCII binary string. ;
; On return: ;
; DX = resulting binary value. ;
;-----------------------------------------------------------;
ascbin_2_bin:
mov di, si ; copy SI into DI
add di, cx ; point to end of string
mov bx, 2 ; 2 = binary base value
mov cx, 1 ; Initialize multiplier
xor ax, ax ; zero out AX
nxt_cvt:
cmp di, si ; at front of string yet?
je at_front ; if equal - have it all!
dec di ; next character to left
mov dl, [di] ; load the character
sub dl, 30h ; convert to decimal
xor dh, dh ; ZERO out DH
push cx ; save CX on stack
xchg ax, cx ; AX = multiplier
; CX = partial value
mul dx ; digit value * multiplier
add cx, ax ; add to partial value
pop ax ; restore multiplier
mul bx ; base times multiplier
xchg ax, cx ; AX = paritial value
; CX = new multiplier
jmp nxt_cvt ; go do next digit
at_front:
mov dx, ax ; copy result into DX
ret
;------------------------------------------------------------
code ENDS
END start