Hey guys im having a trouble with converting decimal to string. Im out of ideas again. Maybe coz im a total newb in assembly. Im out of registers to use maybe becoz i really dont know wht they are for. Heres the code i came up with.
org 100h
mov ax, 000Dh ;Integer to convert to string ( ax == 11 )
mov dx, buff ; Should be the string where the converted decimal will be stored
call intToString ; Convert 11 to String '11' and put it in DX which is pointing to buff variable
call printString ; Pring value of DX
call getch
mov ax, 4C00h
int 21h
buff db 8 dup( 24h )
;===================================:
;PRINTSTRING(). Print String :
;===================================:
printString:
mov ax, 0900h
int 21h
ret
;===============================
;intToString() Convert Integer :
;===============================
intToString:
xor si, si
mov cx, ax
push ax
stiLoop:
mov bl, 0Ah
div bl
add al, '0'
inc si
mov dx, buff
mov [dx+si], ax ; not working
;This is the algorithm for this function
;1. asval = value % 10
;2. char = asval + '0'
;3. value /= 10
;===================================:
;GETCH(). Wait for key press :
;===================================:
getch:
mov ax, 0700h
int 21h
ret
mov dx, buff
mov [dx+si], ax ; not working
in dos (16-bit) you can't use dx
you must use bx...so
mov bx, buff
mov [bx+si], ax
also i think you are only getting al with one div, not ax
Ok tnks. Ill try do it with BX.
I got it working but. The output is reversed. What would be the best way to do so that the outputing will be in the other way around?
for decimal 100 the out put is 001
org 100h
Main:
;Integer to convert to string
mov ax, 100d
mov dx, buff
call intToString
call printString
;call getch
mov ax, 4C00h
int 21h
buff db 8 dup( 24h )
;===================================:
;PRINTSTRING(). Print String :
;===================================:
printString:
mov ax, 0900h
int 21h
ret
;================================
;intToString() Convert Integer :
;in DIV, :
;ah = remainder , al = qoutient :
;================================
intToString:
xor si, si
stiLoop:
mov bl, 10d
div bl
add ah, '0'
mov bx, dx
mov byte [bx+si], ah ; This should output at the supposed to be output len and not at index 0 so itll be in the right order for outputting
inc si
mov ah, 00h
cmp ax, 01h
jl itsEnd
jmp stiLoop
itsEnd:
ret
;Function Algo
;1. asval = value % 10
;2. char = asval + '0'
;3. value /= 10
;===================================:
;GETCH(). Wait for key press :
;===================================:
getch:
mov ax, 0700h
int 21h
ret
I tried reversing the output. But the program just exits whenever i run it. Any1 know whts wrong with the revrsing part of my code?
org 100h
Main:
;Integer to convert to string
mov ax, 100d
mov dx, buff
call intToString
call printString
call getch
mov ax, 4C00h
int 21h
buff db 8 dup( 24h )
;===================================:
;PRINTSTRING(). Print String :
;===================================:
printString:
mov ax, 0900h
int 21h
ret
;================================
;intToString() Convert Integer :
;in DIV, :
;ah = remainder , al = qoutient :
;================================
intToString:
xor si, si
stiLoop:
mov bl, 10d
div bl
add ah, '0'
mov bx, dx
mov byte [bx+si], ah
inc si
mov ah, 00h
cmp ax, 01h
jl reversing
jmp stiLoop
;The problem starts here !!
reversing:
push 00h
mov ax, si
mov bl, 02h
div bl
mov cl, al
mov ch, 00h
reverse:
mov ah, byte [bx+si]
dec si
pop bx
push si
mov si, bx
mov al, byte [bx+si]
mov byte [bx+si], ah
inc si
pop bx
push si
mov si, bx
mov byte [bx+si], al
cmp si, cx
je endits
jmp reverse
endits:
ret
;Function Algo
;1. asval = value % 10
;2. char = asval + '0'
;3. value /= 10
;===================================:
;GETCH(). Wait for key press :
;===================================:
getch:
mov ax, 0700h
int 21h
ret
One common method of reversing the digits would be to push all of them onto the stack and then pop all of them off of the stack. Because of the way the stack operates, the digits would come off in reverse order. The conversion routine could push the digits as they are generated, and then in a separate loop pop them off of the stack and place them in the buffer.
MikieW
The sounds very simple i cant beliv i never thought of that. Thnk you very much. :bg
Not as simple as i thought. Took me more than an hour. Well im a noob. For those who may have the same problem in the future here is the solution.
org 100h
Main:
;Integer to convert to string
mov ax, 213d ;213 is the value im trying to print
mov dx, buff
call intToString
call printString
call getch
mov ax, 4C00h
int 21h
buff db 5 dup( 24h )
;===================================:
;PRINTSTRING(). Print String :
;===================================:
printString:
mov ax, 0900h
int 21h
ret
;================================
;intToString() Convert Integer :
;in DIV, :
;ah = remainder , al = qoutient :
;================================
intToString:
xor si, si
stiLoop:
mov bl, 10d
div bl
add ah, '0'
mov bx, dx
mov byte [bx+si], ah
inc si
mov ah, 00h
cmp ax, 01h
jl reversing
jmp stiLoop
reversing:
mov cx, si
xor si, si
pushLoop:
push word [bx+si]
inc si
inc si
cmp si, cx
jge popLoopStart
jmp pushLoop
popLoopStart:
xor si, si
popLoop:
pop ax
cmp ah, 24h
jne insertHigh
insertLow:
mov byte [bx+si], al
inc si
cmp si, cx
jge endits
jmp popLoop
insertHigh:
mov byte [bx+si], ah
inc si
jmp insertLow
endits:
ret
;Function Algo
;1. asval = value % 10
;2. char = asval + '0'
;3. value /= 10
;===================================:
;GETCH(). Wait for key press :
;===================================:
getch:
mov ax, 0700h
int 21h
ret
using the stack to revert the digits could be coded more simple:
intToString:
mov cx,sp
stiLoop:
mov bl, 10d
div bl
add ah, '0'
push ax
mov ah, 00h
cmp ax, 01h
jl reversing
jmp stiLoop
reversing:
mov bx,dx
popLoop:
cmp cx,sp
je popdone
pop ax
mov byte [bx], ah
inc bx
jmp popLoop
popdone:
ret
Thnks thats simple indeed. :U
You should be aware that your code will only work if ax is < 0A00h (decimal 2560), else you will get a divide error. Consider to use 16 bit registers for the division.
Yeah i have that problem how do i solve that anyway? I see that al or ah the one that holds the Qoutient can only hold up to 256. How do i get by solve that. Or maybe there is a carry of the result where do i get it?
For a 16-bit source (divisor) the implied destination (dividend) will be the 32-bit value in DX:AX. If the initial value in DX is greater than 9, then the result (quotient) will overflow AX (e.g 0A0000 / 0Ah = 10000h). You can prevent this by clearing DX before the DIV instruction is executed.
that's how the code should look like for 16bit (not tested!)
intToString:
mov si, dx
mov cx,sp
stiLoop:
xor dx,dx
mov bx, 10d
div bx
add dl, '0'
push dx
cmp ax, 01h
jl reversing
jmp stiLoop
reversing:
mov dx,si
popLoop:
cmp cx,sp
je popdone
pop ax
mov byte [si], al
inc si
jmp popLoop
popdone:
ret
It worked !! That was simple.
What was happenning in my code why it isnt working? Wht has BX and not BL got to do with this code working? I see that thats the only part you seem to modify asid from the others you removed?
using BL as divisor the division op is AX / BL = AL, remainder AH
using BX, it is DX:AX / BX = AX, remainder in DX
both the result and remainder must fit in AL/AX and AH/DX or an exception occurs
Ok got it thnks :) :bg
Wht is this code for? Where did sp come from?
cmp cx,sp
je popdone
sp ist the "stackpointer" register, which decrements on pushs ("push dx" decrements sp by 2) and increments on pops.
The instructions:
mov cx, sp
...
cmp cx, sp
je popdone
Are an efficient method of ensuring that the number of pops matches the number of pushes (one that had never occurred to me, thanks Gustav). In 16-bit code each push will decrement SP by two, and each pop will increment SP by two. The attachment contains a trace of the code running in DEBUG. It shows what each execution of each instruction does to the registers.
[attachment deleted by admin]
i also checked the code. it's nice&simple :U
> i also checked the code. it's nice&simple
to win a price in a "nice and simple code" competition I would have suggested this variant:
intToString:
mov si, dx
mov cx, offset storedigit
mov bx, 10
stiLoop:
xor dx, dx
div bx
add dl, '0'
push dx
push cx
and ax, ax
jnz stiLoop
mov dx, si
ret
storedigit:
pop ax
mov byte ptr[si], al
inc si
ret
however, for a noobie it's possibly "too simple" to understand what's going on here :green
Someone explain whats going on here?
intToString:
mov si, dx ; strore value of SI to DX ?
mov cx, offset storedigit ; set value of CX to address of storeDigit ?
mov bx, 10 ; set value of BX to 10
stiLoop:
xor dx, dx ; set DX to 0
div bx ; divide here
add dl, '0'
push dx
push cx
and ax, ax ; what about here?
jnz stiLoop
mov dx, si
ret
storedigit: ; What is this part for i dont see it executing ?
pop ax
mov byte ptr[si], al
inc si
ret
To understand how it works you must understand how the stack and the call and ret instructions work. For 16-bit code, a push instruction copies its operand to the address specified by ss:[sp] and then subtracts 2 from sp, and a pop instruction copies the value at the address specified by ss:[sp] to its operand and then adds 2 to sp, so sp always "points" to the most recently pushed value. A call instruction (a near call) effectively pushes the address of the next instruction (following the call instruction) onto the stack and jumps to the destination address. A ret instruction (a near return) effectively pops the most recently pushed value from the stack and uses it for the return destination. Assuming you were converting a two-digit number, the contents of the stack after the jnz stiLoop instuction would be:
return address back to code that called intToString
digit value
address of storedigit label
digit value
address of storedigit label
So the first ret instruction would "return" to the storedigit label. The pop ax instruction would then get the digit value off the stack, and the ret instruction would return to the storedigit label. The pop ax instruction would then get the next digit value off the stack, and since the return address back to code that called intToString would then be the most recently pushed value, the final ret instruction would return to the caller.
The and ax,ax followed by the jnz stiLoop are just another method of looping until ax is zero.
> mov si, dx ; strore value of SI to DX ?
that's because the 16 bit devision destroys DX, and since you are using DX for the string pointer which mustn't be changed its value is saved in SI and restored later.
Just use DEBUG to see what's happening. If someone told you that DEBUG shouldn't be used nowadays ignore it, it is just the right tool for your little program. Use the 'T' (=trace) command to single step through the code.
So thats what the trace.zip was for. I didnt even bother to read everything in it coz they look like junks. Thnks for both replies :)
And thnks for the debug tut. :U