The MASM Forum

General => The Campus => Topic started by: dusty on February 01, 2013, 10:35:08 AM

Title: dwtoa x64
Post by: dusty on February 01, 2013, 10:35:08 AM
trying to convert this to x64, the code runs fine until I return to the c++ calling functiion. I get an unhandled exception error. I have a hunch it's a stacck/memory problem

;dwtoa is a MASM32 routine
; void dwto64(int dwValue, char* lpBuffer) C++ calling function
;                   rcx            rdx
; dwvalue 4 byte int, lpBuffer 8 byte ptr

.data

.code
align 16
dwtoa64 proc public
    push rax
    push rbx
    push rsi
    push rdi
   
    mov eax, ecx               ;dwValue
   ;cdq
    mov dword ptr[edi], edx            ;[lpBuffer]

    test eax,eax
    jnz sign

  zero:
    mov word ptr [edi],30h
    jmp dtaexit

  sign:
    jns pos
    mov byte ptr [edi],'-'
    neg eax
    add edi, 1

  pos:
    mov ecx, 3435973837
    mov esi, edi

loop1:
      mov ebx,eax
      mul ecx
      shr edx, 3
      mov eax,edx
      lea edx,[edx*4+edx]
      add edx,edx
      sub ebx,edx
      add bl,'0'
      mov [edi],bl
      add edi, 1
      cmp eax, 0
      jg loop1

    mov byte ptr [edi], 0       ; terminate the string

    ; We now have all the digits, but in reverse order.

loop2:
      sub edi, 1
      mov al, [esi]
      mov ah, [edi]
      mov [edi], al
      mov [esi], ah
      add esi, 1
      cmp edi, esi
      jg loop2
   
  dtaexit:

    pop rdi
    pop rsi
    pop rbx   
    pop rax   

    ret 

dwtoa64 endp
end
Title: Re: dwtoa x64
Post by: frktons on February 01, 2013, 10:52:32 AM
Better to post this thread in the x64 programming subforum.
Title: Re: dwtoa x64
Post by: dedndave on February 01, 2013, 10:57:58 AM
in 64-bit, addresses are 64 bits wide   :P
mov dword ptr[edi], edx            ;[lpBuffer]
mov rdi, rdx            ;[lpBuffer]

    mov word ptr [edi],30h
    mov word ptr [rdi],30h

and so on
Title: Re: dwtoa x64
Post by: dedndave on February 01, 2013, 11:06:50 AM
you might consider passing the string pointer in RCX
then - you can use that register to reference the characters without changing

Title: Re: dwtoa x64
Post by: qWord on February 01, 2013, 11:13:31 AM
mov dword ptr[edi], edxshould be
mov rdi, rdx

align 16
dwtoa64 proc
    push rax
    push rbx
    push rsi
    push rdi
   
    mov eax, ecx               ;dwValue
    mov rdi, rdx            ;[lpBuffer]

    test eax,eax
    jnz sign

  zero:
    mov word ptr [rdi],30h
    jmp dtaexit

  sign:
    jns pos
    mov byte ptr [rdi],'-'
    neg eax
    add rdi, 1

  pos:
    mov ecx, 3435973837
    mov rsi, rdi

loop1:
      mov ebx,eax
      mul ecx
      shr edx, 3
      mov eax,edx
      lea edx,[edx*4+edx]
      add edx,edx
      sub ebx,edx
      add bl,'0'
      mov [rdi],bl
      add rdi, 1
      cmp eax, 0
      jg loop1

    mov byte ptr [rdi], 0       ; terminate the string

    ; We now have all the digits, but in reverse order.

loop2:
      sub edi, 1
      mov al, [rsi]
      mov ah, [edi]
      mov [edi], al
      mov [rsi], ah
      add rsi, 1
      cmp rdi, rsi
      jg loop2
   
  dtaexit:

    pop rdi
    pop rsi
    pop rbx   
    pop rax   

    ret 

dwtoa64 endp
Title: Re: dwtoa x64
Post by: dusty on February 03, 2013, 04:40:33 AM
I got it to work

;dwtoa is a MASM32 routine
; void dwto64(int dwValue, char lpBuffer[]) C++ calling function
;                   rcx            rdx
; dwvalue 4 byte int, lpBuffer 8 byte ptr

.data

.code
align 16
dwtoa64 proc public
   
    push rbp
    mov rbp, rsp
   
    push rax
    push rbx
    push rsi
    push rdi
   
   
    mov eax, ecx     ; dwValue
    mov edi, edx     ;[lpBuffer]

    test eax,eax
    jnz sign

  zero:
    mov word ptr [edi],30h
    jmp dtaexit

  sign:
    jns pos
    mov byte ptr [edi],'-'
    neg eax
    add edi, 1

  pos:
    mov ecx, 3435973837
    mov esi, edi

loop1:
      mov ebx,eax
      mul ecx
      shr edx, 3
      mov eax,edx
      lea edx,[edx*4+edx]
      add edx,edx
      sub ebx,edx
      add bl,'0'
      mov [edi],bl
      add edi, 1
      cmp eax, 0
      jg loop1
   
    mov byte ptr [edi], 0       ; terminate the string

    ; We now have all the digits, but in reverse order.

loop2:
      sub edi, 1
      mov al, [esi]
      mov ah, [edi]
      mov [edi], al
      mov [esi], ah
      add esi, 1
      cmp edi, esi
      jg loop2

  dtaexit:
   
      pop rdi
      pop rsi
      pop rbx
      pop rax   
   
      mov rsp, rbp
      pop rbp

    ret 

dwtoa64 endp
end

Title: Re: dwtoa x64
Post by: jj2007 on February 03, 2013, 04:44:51 AM
The bold parts look a bit odd - are you sure you need them? Does it crash if you take them away?
Title: Re: dwtoa x64
Post by: dusty on February 03, 2013, 04:53:02 AM
jj2007;
Yes it will crash. I'm using vs2010, mix c++/masm. I had to do that to order to restore my base pointer, which was causing the crash. For some reason calling it from c++ with  void dwtoa64(int num, char* charnum) caused a problem as well, I have not solved that problem yet. It works fine if I call it from c++ void dwtoa64(int num, char charnum[]). but no big deal as I see it ?
Title: Re: dwtoa x64
Post by: japheth on February 03, 2013, 04:55:08 AM
Quote from: dusty on February 03, 2013, 04:40:33 AM
I got it to work

It works, as long as the program and its data is located in the first 4 GB of the address space. To ensure this to be ALWAYS the case you'll have to add linker option /LARGEADDRESSAWARE:NO - or, way better, adjust your routine so it will work with any address ( see qword's post ).
Title: Re: dwtoa x64
Post by: jj2007 on February 03, 2013, 05:47:27 AM
Quote from: dusty on February 03, 2013, 04:53:02 AM
jj2007;
Yes it will crash. I'm using vs2010, mix c++/masm. I had to do that to order to restore my base pointer, which was causing the crash.

Apologies if that is a stupid question: Why do you have to restore your base pointer? Where do you use it in the code above?

@japheth: Is that a backdoor entry to the x32 ABI (http://lwn.net/Articles/456731/)?
What I am wondering is whether /LARGEADDRESSAWARE:NO just limits the module entry point to low addresses; and if so, if a x32 app can still access large addresses by using reg64s.
Title: Re: dwtoa x64
Post by: dusty on February 03, 2013, 06:17:17 AM
If I don't restore my base point it hangs at ret, when I return to c++ calling function the return address is hosed?


private: System::Void test2_Click(System::Object^  sender, System::EventArgs^  e)
{
      dgv->Rows->Clear();
      dgv->RowCount = 50;
      int inum = 1234567890;
      char cnum[17];
      dwtoa64(inum, cnum);
      String ^snum = gcnew String(cnum);
      dgv->Rows[1]->Cells[0]->Value = snum;
}
Title: Re: dwtoa x64
Post by: jj2007 on February 03, 2013, 06:49:35 AM
Quote from: dusty on February 03, 2013, 06:17:17 AM
If I don't restore my base point it hangs at ret...

In the code you posted, rbp is not used at all, except for the bold part at top and bottom. They could be omitted, so that rbp gets never touched.
Title: Re: dwtoa x64
Post by: dusty on February 03, 2013, 07:11:47 AM
jj2007

Your'e right......I must have had somethng else in there causing the problem. I had made the  changes esi[rdi] and edi[rdi] but that didn't help, but it does now. I got rid the rbp as you suggested and it all works as it should.
thanks for the tips and your help  :P :P :greenclp: