Converting decimal into String Problem

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

Previous topic - Next topic

Gustav


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

PinoyProgramador


PinoyProgramador

Wht is this code for? Where did sp come from?
cmp cx,sp
        je popdone




Gustav


sp ist the "stackpointer" register, which decrements on pushs ("push dx" decrements sp by 2) and increments on pops.

MichaelW

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]
eschew obfuscation

HosAh

i also checked the code. it's nice&simple :U

Gustav

> 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


PinoyProgramador

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

MichaelW

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.
eschew obfuscation

Gustav

>    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.




PinoyProgramador

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