Jump to content

My dword to string function

- - - - -

  • Please log in to reply
12 replies to this topic

#1
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
I tried making a function that converts a double-word into a string. For some numbers, this function works, however, for other numbers I don't exactly know what it does.

Anyone know what's wrong?

Attached Files



#2
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
What numbers doesn't it work for? Do you notice a pattern? I suggest you write the function in standard C first and then convert that to assembly language. I see that you tried that, but it's in a somewhat weird syntax and your variable names aren't that helpful.
sudo rm -rf /

#3
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
I think a C++ (I don't quite know how different C and C++ are) version, with more helpful variable names, would look something like:

int e= 9; 

int d2string(int theInteger, char *theString){ 
    char a; 
    if (e == -1){ 
        *theString= 0; 
        e= 9; 
    } else { 
        a= (theInteger / exp10(e)); 
        while (a >= 10) e -= 10; 
        while (a < 0) e += 10; 
        *theString= (a + 48); 
        e--; 
        d2string(theInteger, (theString + 1)); 
    } 
    return 0; 
} 
int exp10(int theExponent){ 
    int i= 1; 
    int a; 
    for (a= 0; a < theExponent; a++){ 
        i *= 10; 
    } 
    return i; 
} 


I didn't really get this code to work on my C++ compiler, but that's kind of the idea.

The variable 'e' is supposed to be used to tell where, in the integer, the function is at. It is supposed to divide the integer by 10 to the 'e' power, add 48 to it (ASCII 48 is the character "0"), and store it as a character at the character, pointed to by the 'theString' variable. Then it is supposed to decrement 'e' and recurse, passing the same 'theInteger' to itself, with the pointer to the output string character + 1 (the next character to be written to, in the string) at the 'theString' parameter. When 'e' finally equals -1, the function is supposed to set 'e' back to 9 (for future d2string() calls) and return.

I tried using the asm function (the one I posted earlier) with 100, 150, 149, 300, 200 as inputs and 100 got converted to "100", 150 got converted to "154", 149 got converted to "143", 300 got converted to "304", and 200 got converted to "204."

I don't really notice anything wrong in the code, so I don't know what's wrong.

Edited by dargueta, 14 December 2010 - 06:46 PM.
Added code tags


#4
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
If your C/C++ code doesn't work, how do you expect the assembly code to work? I tested this code and it works:
#include <stdint.h>

void dword2str(uint32_t num, char *buf)
{
    const char *digits = "0123456789";
    uint32_t i, divisor;
    
    if( num == 0 )
    {
        buf[0] = '0';
        buf[1] = '\0';
        return;
    }

    divisor = 1000000000;    /* 10 decimal digits for DWORD, so init to 10^9 */
    while( num / divisor == 0 )
        divisor /= 10;

    for( i = 0; divisor > 0; ++i )
    {
        buf[i] = digits[num / divisor];
        num = num % divisor;
        divisor /= 10;
    }
    
    buf[i] = '\0';
}
Try converting that into assembly language and see if you still have problems.
sudo rm -rf /

#5
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
What does "num % divisor" (the "%", in particular) mean?

#6
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
% is the modulus, the remainder of num / divisor. For example:

10 / 3 = 3
10 % 3 = 1
sudo rm -rf /

#7
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
I made another function. I think this one works.



;;  void d2a ( int theInteger, char * theString ){ 

;;  	d2aProc ( theInteger, theString ); 

;;  	reverse_string ( theString ); 

;;  } 

;;  void d2aProc ( int theInteger, char *theString ){ 

;;  	char a; 

;;  	int i= theInteger; 

;;  	if (theInteger == 0){ 

;;  		*(theString + 0)= 48; 

;;             *(theString + 1)= 0; 

;;  		return; 

;;  	} 

;;  	while (i >= 10) i -= 10; 

;;  	a= i; 

;;  	*theString= a + 48; 

;;  	d2aProc ( ( theInteger / 10 ), ( theString + 1 ) ); 

;;  } 


d2a proc 

	enter 0, 0 

	pusha 

	theInteger                 equ  ebp + 8 

	theString                  equ  ebp + 12 

	

	push dword ptr [theString] 

	push dword ptr [theInteger] 

	call d2aProc 

	

	push dword ptr [theString] 

	call reverse_string 

	

	mov eax, dword ptr [theString] 

	mov ebx, eax 

	mov ah, 48 

	call skip_to_non_char 

	mov eax, dword ptr [theString] 

	call StringCopy 

	

	popa 

	leave 

	ret 8 

d2a endp 


d2aProc proc 

	enter 8, 0 

	theInteger                     equ  ebp + 8 

	theString                      equ  ebp + 12 

	a                              equ  ebp - 4 

	i                              equ  ebp - 8 

	

	mov eax, dword ptr [theInteger] 

	mov dword ptr [i], eax 

	

	;mov eax, dword ptr [theInteger]      ;; eax is already equal to [theInteger] 

	cmp eax, 0 

	jnz d2aProcOver1 

		mov eax, dword ptr [theString] 

		mov ebx, eax 

		mov byte ptr [ebx+0], 48 

		mov byte ptr [ebx+1], 0 

		

		leave 

		ret 8 

	d2aProcOver1: 

	

	lp1: 

		cmp dword ptr [i], 10 

		jl lp1s 

		

		sub dword ptr [i], 10 

		

		jmp lp1 

	lp1s: 

	

	mov eax, dword ptr [i] 

	mov byte ptr [a], al 

	

	mov eax, dword ptr [theString] 

	mov ebx, eax 

	mov al, byte ptr [a] 

	add al, 48 

	mov byte ptr [ebx], al 

	

	;mov eax, dword ptr [theString] 

	mov eax, ebx            ;; since ebx == [theString]  (at this point) 

	inc eax 

	push eax 

		push dword ptr 10 

		push dword ptr [theInteger] 

		call divide4 

	push eax 

	call d2aProc 

	

	leave 

	ret 8 

d2aProc endp 


Thanks for the help.

#8
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
I think this function (the function that you gave me in C/C++) works too. I tried converting it to assembly and here's how it is:
.386 

.model flat, stdcall 

option casemap:none 

option prologue:none 

option epilogue:none 

include \string.inc 

dword2str proto 

.data 

.data? 

.code 


dword2str proc 

	enter 12, 0 

	num                   equ  ebp + 8 

	buf                   equ  ebp + 12 

	digits                equ  ebp - 12 

	divisor               equ  ebp - 8 

	i                     equ  ebp - 4 

	

	mov dword ptr [digits], string("0123456789") 

	

	mov eax, dword ptr [num] 

	cmp eax, 0 

	jnz dword2str_over1 

		mov eax, dword ptr [buf] 

		mov ebx, eax 

		mov byte ptr [ebx+0], 48 

		mov byte ptr [ebx+1], 0 

		leave 

		ret 8 

	dword2str_over1: 

	

	mov dword ptr [divisor], 1000000000 

	

	lp1: 

		push dword ptr [divisor] 

		push dword ptr [num] 

		call divide4 

		cmp eax, 0 

		jnz lp1s 

		

		push dword ptr 10 

		push dword ptr [divisor] 

		call divide4 

		mov dword ptr [divisor], eax 

		

		jmp lp1 

	lp1s: 

	

	mov dword ptr [i], 0 

	lp2: 

		mov eax, dword ptr [divisor] 

		cmp eax, 0 

		jng lp2s 

		

		push dword ptr [divisor] 

		push dword ptr [num] 

		call divide4 

		add eax, dword ptr [digits] 

		mov edx, eax 

		

		mov eax, dword ptr [buf] 

		add eax, dword ptr [i] 

		mov ebx, eax 

		

		mov al, [edx] 

		mov [ebx], al 

		

		;; num= num % divisor 

		push dword ptr [divisor] 

		push dword ptr [num] 

		call divide4 

		mov dword ptr [num], ecx 

		

		push dword ptr 10 

		push dword ptr [divisor] 

		call divide4 

		mov dword ptr [divisor], eax 

		

		inc dword ptr [i] 

		jmp lp2 

	lp2s: 

	

	mov eax, dword ptr [buf] 

	add eax, dword ptr [i] 

	mov ebx, eax 

	mov byte ptr [ebx], 0 

	

	leave 

	ret 8 

dword2str endp 


include div4.asm 


end 

And here's what "div4.asm" has:
divide4 proc 

	enter 4, 0 

	a                     equ  ebp + 8 

	b                     equ  ebp + 12 

	i01                   equ  ebp - 4 

	push ecx 

	push edx 

	

	;; int i= 0; 

	;; while ((b * i) <= a){ 

	;;   i++; 

	;; } 

	

	mov dword ptr [i01], 0 

	lp003: 

		mov eax, dword ptr [b] 

		mov ecx, dword ptr [i01] 

		imul eax, ecx 

		cmp eax, dword ptr [a] 

		jg lp003s 

		

		inc dword ptr [i01] 

		

		jmp lp003 

	lp003s: 

	

	dec dword ptr [i01] 

	

	mov eax, dword ptr [b] 

	imul eax, dword ptr [i01] 

	neg eax 

	add eax, dword ptr [a] 

	

	pop edx 

	pop ecx 

	

	mov ecx, eax 

	

	mov eax, dword ptr [i01] 

	

	;; eax= a / b; ecx= a % b; 

	

	leave 

	ret 8 

divide4 endp 


#9
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
That's a little over-complicating things. Here's what I came up with; I don't have time to comment it too well right now, but if you have questions just ask. I map some variables to registers:

ECX: divisor
EBX: 10
EDI: buf
EAX: num (most of the time)


global dword2str


section .text

dword2str:

    push    ebp

    mov     ebp, esp

    push    ebx

    push    edi


    mov     eax, [ebp + 8]

    mov     edi, [ebp + 12]


    or      eax, eax

    jnz     .nonzero

    mov     BYTE [edi], '0'

    mov     BYTE [edi + 1], 0

    jmp     .done


    .nonzero:

    mov     ecx, 1000000000

    mov     ebx, 10


    .div_loop:

        xor     edx, edx

        div     ecx

        or      eax, eax

        jnz     .buf_loop

        xor     edx, edx

        mov     eax, ecx

        div     ebx

        mov     ecx, eax

        mov     eax, [ebp + 8]

        jmp     .div_loop


    .buf_loop:

        xor     edx, edx

        mov     eax, [ebp + 8]

        div     ecx

        mov     [ebp + 8], edx          ; num = num % divisor

        mov     dl, [digits + eax]      ; buf[i] = digits[num / divisor]

        mov     [edi], dl


        ; divisor /= 10

        xor     edx, edx

        mov     eax, ecx

        div     ebx

        mov     ecx, eax


        ; ++i

        inc     edi

        or      ecx, ecx

        jnz     .buf_loop


    .add_null:

    mov     BYTE [edi], 0


    .done:

    pop     edi

    pop     ebx

    pop     ebp

    ret


section .data

    digits: db "0123456789", 0x00


sudo rm -rf /

#10
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
I tried this:
global dword2str, _dword2str 


section .text


_dword2str: 

	jmp dword2str 

;; .....  


dword2str:

	%define divisor                    ecx 

	%define buf                        edi 

	%define num                        eax 

    push    ebp

    mov     ebp, esp

    push    ebx

    push    edi


    mov     num, [ebp + 8] 

    mov     buf, [ebp + 12] 


    or      num, num 

    jnz     .nonzero

    mov     BYTE [buf], 48 

    mov     BYTE [buf + 1], 0

    jmp     .done


    .nonzero:

    mov     divisor, 1000000000

    mov     ebx, 10


    .div_loop:

        xor     edx, edx

        div     divisor

        or      num, num

        jnz     .buf_loop

        xor     edx, edx

        mov     eax, divisor 

        div     ebx

        mov     divisor, eax

        mov     num, [ebp + 8]

        jmp     .div_loop


    .buf_loop:

        xor     edx, edx

        mov     num, [ebp + 8]

        div     divisor

        mov     [ebp + 8], edx          ; num = num % divisor

        mov     dl, [digits + eax]      ; buf[i] = digits[num / divisor]

        mov     [buf], dl


        ; divisor /= 10

        xor     edx, edx

        mov     eax, divisor 

        div     ebx

        mov     divisor, eax 


        ; ++i

        inc     buf

        or      divisor, divisor 

        jnz     .buf_loop


    .add_null:

    mov     BYTE [buf], 0


    .done:

    pop     edi

    pop     ebx

    pop     ebp

    ret


section .data

    digits: db "0123456789", 0x00

And it seems to work, also.

#11
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Wait...what'd you change?
sudo rm -rf /

#12
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
Just changed things like 'mov eax, [ebp+8]' to 'mov num, [ebp+8]', with the '%define num eax' at the beginning of the function.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users