Converting decimal into String Problem

Started by PinoyProgramador, November 18, 2005, 12:06:12 PM

Previous topic - Next topic

PinoyProgramador

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


sinsi

        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
Light travels faster than sound, that's why some people seem bright until you hear them.

PinoyProgramador


PinoyProgramador

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

PinoyProgramador

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

MichaelW

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.

eschew obfuscation

PinoyProgramador

MikieW

The sounds very simple i cant beliv i never thought of that. Thnk you very much.  :bg

PinoyProgramador

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

Gustav


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


PinoyProgramador


Gustav


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.

PinoyProgramador

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?

MichaelW

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.

eschew obfuscation

Gustav


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


PinoyProgramador

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?