16-bit Asm – String and Numeric Conversions

I have this old magazine from the late 80’s called “The Assembly Language Magazine”, it has a lot of l337 16 bit code. 2 of them are sub-procedures to convert a string to a 4 byte number and vise-versa. Those labels accepted values to be input to registers, but I’ve converted them into function that you can call by pushing the required arguments to the stack. 3 New functions to add to your 16-bit asm library:

dec2hex:     ;push szStr; returns 4 byte value in ax
push bp
mov bp,sp
push bx
push cx
push dx
push si
push di
mov si,word [bp+4]
push si
call strlen
mov cx,ax
xor dx,dx
xor ax,ax
dec2hex_try:
cmp cl,1
jbe dec2hex_lasta
mov dl,byte [si]
sub dl,30h
add ax,dx
mov bx,ax
shl ax,1
shl ax,1
shl ax,1
add ax,bx
add ax,bx
inc si
loop dec2hex_try
dec2hex_lasta:
mov dl,byte [si]
sub dx,30h
add ax,dx
add sp,2
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

hex2dec:       ;push szOutBuff; push short;
push bp        ;Converts short into string and stores it
mov bp,sp      ;in szOutBuff
push bx
push cx
push dx
push si
push di
mov ax,word [bp+4]
xor bx,bx
xor cx,cx
xor dx,dx
hex2dec_a10k:
cmp ax,10000
jb hex2dec_a1k
sub ax,10000
inc bh
jmp hex2dec_a10k
hex2dec_a1k:
cmp ax,1000
jb hex2dec_hundreds
sub ax,1000
inc bl
jmp hex2dec_a1k
hex2dec_hundreds:
cmp ax,100
jb hex2dec_tens
sub ax,100
inc dh
jmp hex2dec_hundreds
hex2dec_tens:
cmp ax,10
jb hex2dec_units
sub ax,10
inc dl
jmp hex2dec_tens
hex2dec_units:
mov ah,30h
add bh,ah
add bl,ah
add dh,ah
add dl,ah
add al,ah
cmp bh,ah
jnz hex2dec_uend
mov bh,20h
hex2dec_u1:
cmp bl,ah
jnz hex2dec_uend
cmp bh,20h
jnz hex2dec_uend
mov bl,20h
cmp dh,ah
jnz hex2dec_uend
cmp bl,20h
jnz hex2dec_uend
mov dh,20h
cmp dl,ah
jnz hex2dec_uend
cmp dh,20h
jnz hex2dec_uend
mov dl,020H
hex2dec_uend:
mov si,word [bp+6]
mov byte [si],bh
inc si
mov byte [si],bl
inc si
mov byte [si],dh
inc si
mov byte [si],dl
inc si
mov byte [si],al
inc si
mov byte [si],0
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

strlen:       ;push szStr
push bp       ;Returns length of string in ax
mov bp,sp
push bx
push cx
push dx
push si
push di
mov si,word [bp+4]
xor dx,dx
xor ax,ax
strlen_loop:
mov dl,byte [si]
cmp dl,0
je strlen_break
inc ax
inc si
jmp strlen_loop
strlen_break:
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

The third function is “strlen” which gets the length of a string. dec2hex function depends on the strlen function.

Now here’s a working fasm example:

org 100h
use16
main:
push msg0
call prints
push msg1     ;Address of prompt
call prints   ;Print input prompt
push 5        ;Length of buffer (excluding ending null)
push buff1    ;Address of buffer
call inputs   ;Get input into buffer
push msg1
call prints
push 5
push buff2
call inputs
push buff1
call dec2hex  ;Convert first number to integer
mov cx,ax     ;Place returned value into cx
push buff2
call dec2hex  ;Convert second number to integer
mul cx        ;Multiply them (ax = cx * ax)
push buff1    ;Output buffer
push ax       ;Integer value
call hex2dec  ;Convert to string (output to buffer)
push msg2
call prints
push buff1
call prints
mov ah,08
int 21h
int 20h

msg0 db "Multiplier, use 5 digit base-10 numbers whose product will",0dh,0ah,"not be greater than 65535",0dh,0ah,0
msg1 db 0dh,0ah,"Enter base-10 number: ",0
msg2 db 0dh,0ah,"Product is: ",0
buff1 db 6 dup (0)
buff2 db 6 dup (0)

dec2hex:     ;push szStr; returns 4 byte value in ax
push bp
mov bp,sp
push bx
push cx
push dx
push si
push di
mov si,word [bp+4]
push si
call strlen
mov cx,ax
xor dx,dx
xor ax,ax
dec2hex_try:
cmp cl,1
jbe dec2hex_lasta
mov dl,byte [si]
sub dl,30h
add ax,dx
mov bx,ax
shl ax,1
shl ax,1
shl ax,1
add ax,bx
add ax,bx
inc si
loop dec2hex_try
dec2hex_lasta:
mov dl,byte [si]
sub dx,30h
add ax,dx
add sp,2
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

hex2dec:       ;push szOutBuff; push short;
push bp        ;Converts short into string and stores it
mov bp,sp      ;in szOutBuff
push bx
push cx
push dx
push si
push di
mov ax,word [bp+4]
xor bx,bx
xor cx,cx
xor dx,dx
hex2dec_a10k:
cmp ax,10000
jb hex2dec_a1k
sub ax,10000
inc bh
jmp hex2dec_a10k
hex2dec_a1k:
cmp ax,1000
jb hex2dec_hundreds
sub ax,1000
inc bl
jmp hex2dec_a1k
hex2dec_hundreds:
cmp ax,100
jb hex2dec_tens
sub ax,100
inc dh
jmp hex2dec_hundreds
hex2dec_tens:
cmp ax,10
jb hex2dec_units
sub ax,10
inc dl
jmp hex2dec_tens
hex2dec_units:
mov ah,30h
add bh,ah
add bl,ah
add dh,ah
add dl,ah
add al,ah
cmp bh,ah
jnz hex2dec_uend
mov bh,20h
hex2dec_u1:
cmp bl,ah
jnz hex2dec_uend
cmp bh,20h
jnz hex2dec_uend
mov bl,20h
cmp dh,ah
jnz hex2dec_uend
cmp bl,20h
jnz hex2dec_uend
mov dh,20h
cmp dl,ah
jnz hex2dec_uend
cmp dh,20h
jnz hex2dec_uend
mov dl,020H
hex2dec_uend:
mov si,word [bp+6]
mov byte [si],bh
inc si
mov byte [si],bl
inc si
mov byte [si],dh
inc si
mov byte [si],dl
inc si
mov byte [si],al
inc si
mov byte [si],0
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

strlen:       ;push szStr
push bp       ;Returns length of string in ax
mov bp,sp
push bx
push cx
push dx
push si
push di
mov si,word [bp+4]
xor dx,dx
xor ax,ax
strlen_loop:
mov dl,byte [si]
cmp dl,0
je strlen_break
inc ax
inc si
jmp strlen_loop
strlen_break:
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

;Jakash3's basic i/o library. Unless otherwise commented,
;each function returns the current cursor position.
;return values placed in ax after function call.
;arguments for functions pushed to stack.

printc:                     ;printc(byte c)
push bp
mov bp,sp
push bx
push cx
push dx
push si
push di
mov ah,0fh
int 10h
mov ah,0ah
mov al,byte [bp+4]
cmp al,0dh
je printc_cr
cmp al,0ah
je printc_lf
jmp printc_continue
printc_cr:
mov ah,03
int 10h
mov dl,0
mov ah,02
int 10h
jmp printc_done
printc_lf:
mov ah,03
int 10h
inc dh
mov ah,02
int 10h
jmp printc_done
printc_continue:
mov cx,1
int 10h
call inccur
printc_done:
mov ah,03
int 10h
mov ah,dh
mov al,dl
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

prints:                     ;prints(word str_ptr)
push bp
mov bp,sp
push bx
push cx
push dx
push si
push di
mov bx,word [bp+4]
sub sp,1
prints_loop:
mov dl,byte [bx]
cmp dl,0
jz prints_done
mov byte [bp-11],dl
call printc
inc bx
jmp prints_loop
prints_done:
mov ah,03
int 10h
mov ah,dh
mov al,dl
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

inputc:                     ;byte inputc()
push bp                     ;returns byte value of single character input
mov bp,sp
push bx
push cx
push dx
push si
push di
mov ah,00
int 16h
sub sp,2
mov byte [bp-11],al
mov byte [bp-12],al
call printc
mov ah,0
mov al,byte [bp-11]
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

inputs:                     ;byte inputs(byte len,word buff_ptr)
push bp                     ;returns number of bytes read from input
mov bp,sp
push bx
push cx
push dx
push si
push di
sub sp,1
mov bx,word [bp+4]
mov ch,byte [bp+6]
xor cl,cl
input_L1:
mov ah,0
int 16h
cmp al,08
je input_bksp
cmp al,0dh
je input_br1
cmp cl,ch
jge input_L1
mov byte [bx],al
inc bx
mov byte [bp-11],al
call printc
inc cl
jmp input_L1
input_bksp:
cmp cl,0
je input_L1
mov byte [bx],0
dec bx
mov byte [bx],0
mov byte [bp-11],0
call printc
call deccur
call deccur
call printc
call deccur
dec cl
jmp input_L1
input_br1:
mov byte [bx],0
mov ah,0
mov al,cl
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

deccur:             ;decrease cursor position
push bp
mov bp,sp
push bx
push cx
push dx
push si
push di
sub sp,1
mov ah,0fh
int 10h
mov byte [bp-11],ah
mov ah,03
int 10h
cmp dl,0
jne deccur_continue
mov dl,byte [bp-11]
dec dh
jmp deccur_done
deccur_continue:
dec dl
deccur_done:
mov ah,02
int 10h
add sp,1
mov ah,03
int 10h
mov ah,dh
mov dl,dl
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

inccur:            ;increase cursor position
push bp
mov bp,sp
push bx
push cx
push dx
push si
push di
sub sp,1
mov ah,0fh
int 10h
mov byte [bp-11],ah
mov ah,03
int 10h
cmp dl,byte [bp-11]
jne inccur_continue
mov dl,0
inc dh
jmp inccur_done
inccur_continue:
inc dl
inccur_done:
mov ah,02
int 10h
add sp,1
mov ah,03
int 10h
mov ah,dh
mov al,dl
pop di
pop si
pop dx
pop cx
pop bx
mov sp,bp
pop bp
ret

One thought on “16-bit Asm – String and Numeric Conversions

  1. It is the best time to make some plans for the future and it’s time to be happy. I have read this post and if I could I desire to suggest you some interesting things or tips. Maybe you can write next articles referring to this article. I desire to read more things about it!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: