Hello Assembly community! Currently I'm an engineering student that tried solving a few of my homework questions, most of them were simply enough, but one question haunts me for 10 hours now.
The question asks that I create a routine that receives a 16bit unsigned number in HEX format Using the stack and print the number in decimal format such that each row represents each prefix, for example for input 'B26Eh' We should get:
The program must implement a recursion and we must provide the input through the stack.
I have written the following code:
.model small
.data
.stack 100h
.code
START:
; Setting screen data into ES register
MOV AX, 0B800h
MOV ES, AX
; Setting the data segment
MOV AX, @data
MOV DS, AX
; Screen offset
MOV CX, 0d
MOV BX, 340h
; Testing result
MOV AX, 746FH
PUSH AX
CALL numPrefix
; Exit and print both runs
MOV AX, 4C00h
INT 21h
numPrefix PROC
; Save registers
PUSH BP
PUSH DX
MOV BP, SP
MOV AX, [BP+6d]
; Base condition
CMP AX, 0
JE baseCase
; Else, divide the input by 16d to get the quotient and remainder
PUSH CX ; Save print address
mov cx, 10 ; Divisor
xor dx, dx ; Clear dx for the quotient
div cx ; Divide ax by cx, quotient in ax, remainder in dx
POP CX
; Call numPrefix recursively with the quotient
push ax ; Push the quotient onto the stack
call numPrefix
; PRINT LOGIC #################################################################################
; Now we print what we got for each row in the recursion
MOV DH, 2Eh
SUB BX, 0A0h
PUSH BX
PUSH CX
CMP CX, 0d
JE equalZero
printLoop:
; For each row in the recursion, print the appropriate row of numbers
MOV SI, BX
MOV DI, [BX+0A0h]
PUSH AX
MOV AX, ES:[SI]
MOV ES:[DI], AX
POP AX
ADD BX, 1
loop printLoop
equalZero:
POP CX
; Add new member
ADD BX, 1
MOV ES:[BX], DX
POP BX
INC CX
; PRINT LOGIC #################################################################################
; Finish and restore registers
; Also Base case where we only print and not do recursion again
baseCase:
pop DX
pop BP
ret 2
numPrefix ENDP
END START
The logic in my mind was quite simple, I will use the fact that dividing by 16h will give me the new AX (the quotient) and the remainder (DX) is to be printed. Each time recursively I tried re-calling this routine and using the 'print' function for each level of the recursion I am copying the previous row and adding the new remainder (DX) to the new row.
The code won't work, I tried debugging it with DOSBOX for hours now, each time I think I figure it out but eventually the debugger just jumps to random places in the memory after I do the call-back of the recursion. I've been debugging it for hours now and I hope I can have some help.
Thank you!
EDIT: It seems I fixed some of the issues, I think the recursion traces back to it's normal place, but I can't seem to get back the DX (remainder) as I trace back from my recursion, help is appreciated!
FINAL EDIT: Solved, thanks everyone!
You apparently solved it while I was writing an answer. Good for you! So it doesn't go to waste, here is what I came up with. Probably useful to compare solutions...
Your recursion was fine, but the interaction with the screen wasn't.
eg. MOV DI, [BX+0A0h]
would have to be lea DI, [bx - 160]
ORG 256
mov ax, 0B800h
mov es, ax
xor cx, cx
mov bx, 0340h
mov ax, 746Fh
push ax
call numPrefix
mov ax, 4C00h
int 21h
; ---------------------------
numPrefix:
push bp
push dx
mov bp, sp
mov ax, [bp+6]
test ax, ax
jz baseCase
mov di, 10
xor dx, dx
div di
push ax
call numPrefix
sub bx, 160 ; 1 row up !!!
push bx
test cx, cx
jz equalZero
push ax
push cx
printLoop:
mov ax, [es:BX+160] ; copy from lower to higher !!!
mov [es:BX], ax
add bx, 2 ; 2 bytes per charactercell !!!
loop printLoop
pop cx
pop ax
equalZero:
add dx, 2E30h ; Convert to text plus set attribute !!!
mov [es:bx], dx
pop bx
inc cx
baseCase:
pop dx
pop bp
ret 2