Hi there, obviously a newb to these forums and like many other beginners am struggling and in need of some assistance.
I have been asked to write an assembler program to allow conversion of 2 base numbers, unusualy i have been asked to convert base 4 to base 6 and vice versa, the scenario is an alien race one of whom has 4 fingers the other has 6, and they are building an intergalactic space stationa nd need a program to do conversions, very strange scenario i know but our tutor is quite out there if you know what i mean!!
I have compiled in the past a template to help with previous assignments, can i use the code in this template, the routine readnum and displaynum?
TITLE (.asm)
; This program
; Last update:
.model large
.stack 4096
.386
.data
firstno word 0000h
.code
main PROC
mov ax,@data
mov ds,ax
call readnum
mov firstno,bx
call readnum
add bx,firstno
call dispnum
stop:
mov ah,4ch
int 21h
main ENDP
;-----------------------------------------------------------------
readNum PROC
.data
numin word 0000h
.code
push dx
push cx
; push bx
push ax
push si
push di
; read digit
L1:
mov ah,1
int 21h
; check for <ESC> or <RET>
cmp al,1bh
je Onward
cmp al,0dh
je Onward
; check for digit
and ax,000fh
cmp al,09h
jg onward
; multiply stored value by 10
; and add digit read
mov bx,numin
sal bx,3
add bx,numin
add bx,numin
add bx,ax
mov ax,bx
; store result
mov numin,ax
jmp L1
Onward:
mov bx,numin
pop di
pop si
pop ax
; pop bx
pop cx
pop dx
ret
readNum ENDP
;-----------------------------------------------------------------
dispNum PROC
.data
thou byte 30h
cent byte 30h
tens byte 30h
unit byte 30h
vthou word 03e8h
vcent word 0064h
vtens word 000ah
vunit word 0001h
value word 0000h
toobigno byte "number too large",0dh,0ah,"$"
leadzf byte 00h
.code
; save registers
push dx
push cx
push bx
push ax
push si
push di
; reset digit values to 0
mov al,30h
mov thou,al
mov cent,al
mov tens,al
mov unit,al
; check whether number is less than 9,999
xor ax,ax
mov leadzf,al
cmp bx,0000h
jl toobig
cmp bx,270Fh
jg toobig
; determine no of thousands
dec thou
L1000:
inc thou
sub bx,vthou
jge L1000
add bx,vthou
mov ah,6
mov dl,thou
cmp dl,30h
je Over1
int 21h
mov leadzf,1
over1:
xor ax,ax
dec cent
L100:
inc cent
sub bx,vcent
jge L100
add bx,vcent
mov ah,6
mov dl,cent
cmp dl,30h
je Over2
o2:
int 21h
mov leadzf,1
jmp o2a
over2:
cmp leadzf,0
jne o2
o2a:
xor ax,ax
dec tens
L10:
inc tens
sub bx,vtens
jge L10
add bx,vtens
mov ah,6
mov dl,tens
cmp dl,30h
je Over3
o3:
int 21h
mov leadzf,1
jmp o3a
over3:
cmp leadzf,0
jne o3
o3a: xor ax,ax
dec unit
L1:
inc unit
sub bx,vunit
jge L1
add bx,vunit
mov ah,6
mov dl,unit
int 21h
mov ah,6
mov dl," "
int 21h
pop di
pop si
pop ax
pop bx
pop cx
pop dx
ret
toobig:
mov ah,9
mov dx,OFFSET toobigno
int 21h
pop di
pop si
pop ax
pop bx
pop cx
pop dx
ret
dispNum ENDP
;-----------------------------------------------------------------
registers PROC
.data
Axmsg byte "AX: $"
Bxmsg byte "BX: $"
Cxmsg byte "CX: $"
Dxmsg byte "DX: $"
crlf byte 0dh,0ah,"$"
.code
push dx
push cx
push bx
push ax
push dx
push cx
push bx
push ax
mov ah,9
mov dx,OFFSET crlf
int 21h
mov ah,9
mov dx,OFFSET Axmsg
int 21h
pop ax
call display
mov ah,9
mov dx,OFFSET Bxmsg
int 21h
pop ax
call display
mov ah,9
mov dx,OFFSET Cxmsg
int 21h
pop ax
call display
mov ah,9
mov dx,OFFSET Dxmsg
int 21h
pop ax
call display
mov ah,9
mov dx,OFFSET crlf
int 21h
pop ax
pop bx
pop cx
pop dx
ret
registers ENDP
display PROC
.data
msg2 byte "h ","$"
hex byte "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"
.code
push ax
push bx
push cx
push dx
; display first nibble
mov bx,ax
shr ax,12
lea di,hex
add di,ax
mov dl,[di]
mov ah,2
int 21h
; display second nibble
mov ax,bx
shr ax,8
shl ax,12
shr ax,12
lea di,hex
add di,ax
mov dl,[di]
mov ah,2
int 21h
; display third nibble
mov ax,bx
shr ax,4
shl ax,12
shr ax,12
lea di,hex
add di,ax
mov dl,[di]
mov ah,2
int 21h
; display fourth nibble
mov al,bl
shl ax,12
shr ax,12
lea di,hex
add di,ax
mov dl,[di]
mov ah,2
int 21h
mov ah,9
mov dx,OFFSET msg2
int 21h
pop dx
pop cx
pop bx
pop ax
ret
display ENDP
END main
I take it the conversion is a question of multiplying or dividing by 2? Is that with shift instructions? Also the maximum value to avoid overflowing is 330(6) or 1332(4).
Am a bit stuck and im not asking anyone to do the work for me but give me some pointers, been 4 months since i touched assembly language and am really struggling.
Maybe you can help me along whilst i complete it?? Any help appreciated, thanks guys
Paul
If you are starting and ending with strings, then the conversion could consist of converting a base 4 or 6 string to a binary value, and then converting the binary value to a base 4 or 6 string. Your readNum code could be easily adapted to do the first conversion, but your dispNum code would require major changes to accommodate a different base. One simple, easy to understand method of converting a numeric value to a string is to extract the digit values in reverse order by taking the remainder when the number is divided by the base, continuing until the quotient is zero. For example, using base 10:
123 / 10 = 12 remainder 3
12 / 10 = 1 remainder 2
1 / 10 = 0 remainder 1
Then starting with the last value extracted, convert each digit value to a character code (by adding the character code value for "0" for base <=10) and either display each character or add it to a string. The stack provides a convenient method of reversing the order of the digit values. This method could be implemented as two loops. The first loop would perform the divisions, push the digit values onto the stack, and update a digit counter that would be used to control the second loop. The second loop would pop the digit values from the stack, convert them to characters, and display the characters or add them to a string.
A version extremely similar to what MichaelW described, only used arrays instead of the stack
with full source code in MASM32 and Turbo Pascal (16 bit DOS)/Delphi (32 bit Windows)
along with the MASM32 executable.
.data
fbase dd 4
tbase dd 6
farr db 8 dup (255)
tarr db 8 dup (255)
szbf db 8 dup (0)
szC db "Base Conversion", 0
.code
start:
mov farr+0, 1 ; fill in base 4 value as a series of bytes ending with a 255 byte
mov farr+1, 3
mov farr+2, 3
mov farr+3, 2
mov esi, 0 ; copy to a zero terminated string for display in a MessageBox
.repeat
.if farr[esi] != 255
mov al, farr[esi]
mov szbf[esi], al
add szbf[esi], 48
inc esi
.endif
.until farr[esi] == 255
invoke MessageBox, NULL, addr szbf, addr szC, MB_OK
mov edx, 0 ; convert base 4 byte series into a value held in eax
mov eax, 0
mov esi, 0
mov ecx, fbase
.repeat
.if byte ptr farr[esi] != 255
mul ecx
movzx ebx, byte ptr farr[esi]
add eax, ebx
inc esi
.endif
.until byte ptr farr[esi] == 255
mov ebx, eax ; convert to a base 6 value as a series of bytes with a 255 byte terminator
mov ecx, tbase
mov esi, 0
.if ebx == 0
mov tarr[esi], 0
inc esi
.else
.repeat
.if ebx > 0
mov edx, 0
mov eax, ebx
div ecx
mov tarr[esi], dl
mov ebx, eax
inc esi
.endif
.until ebx == 0
.endif
mov dword ptr szbf+0, 0
mov dword ptr szbf+4, 0
mov edi, 0 ; copy in reverse order using length of base 6 bytes to a zero terminated string for the MessageBox
dec esi
.repeat
.if esi >= 0
mov al, tarr[esi]
add szbf[edi], al
add szbf[edi], 48
inc edi
dec esi
.endif
.until esi == -1
invoke MessageBox, NULL, addr szbf, addr szC, MB_OK
invoke ExitProcess,0
end start
[attachment deleted by admin]
Hey guys, you lot are ace, very helpful indeed, 2 approaches to the same problem, will have a play about this weekend with it all. Just finshed work so time for a few beers, if i lived by you i would buy you both one!! Thanks again for the help, will let you know how i got on with it all.
Diolch ym fawr
Paul :U