memcpy function (interfacing C & nasm)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
ich_will

memcpy function (interfacing C & nasm)

Post by ich_will »

hi I wrote a memcpy function but doesn't work, but I think it have to work:

Code: Select all

[global _memcpy]; void *memcpy(void *dest, const void *src, unsigned int count);

;after three pushes
;ebp + 8  = dest
;ebp + 12 = src
;ebp + 16 = count

_memcpy:
   push ebp
   push esi
   push edi

   mov edi, [ebp+8]   ; edi = dest
   mov esi, [ebp+12]   ; esi = src
   mov ecx, [ebp+16]   ; ecx = count
   rep movsb   ; for(i = 0; i < ecx; i++){edi[i]=esi[i]}
   pop edi
   pop esi
   pop ebp
   mov eax, [ebp]      ; eax = return value = dest
   ret
it seems that the function does nothing
DennisCGc

Re:memcpy function (nasm)

Post by DennisCGc »

What about setting up DS and ES ?

Code: Select all

[global _memcpy]; void *memcpy(void *dest, const void *src, unsigned int count);

;after three pushes
;ebp + 8  = dest
;ebp + 12 = src
;ebp + 16 = count

_memcpy:
   push ebp
   push esi
   push edi
   push ds
   push es
   push ax
   mov ax, 16 ;source segment
   mov ds, ax ;source segment to DS (also source ;) )
   mov ax, 24 ;destination segment
   mov es, ax ;dest. segment to ES (also dest. ;) )
   mov edi, [ebp+8]   ; edi = dest
   mov esi, [ebp+12]   ; esi = src
   mov ecx, [ebp+16]   ; ecx = count
   rep movsb   ; for(i = 0; i < ecx; i++){edi[i]=esi[i]}
   pop edi
   pop esi
   pop ebp
   mov eax, [ebp]      ; eax = return value = dest
   ret
And what another problem could be is some invalid pushes and pops, which means wrong edi and esi.. but I don't know sure.
Adek336

Re:memcpy function (nasm)

Post by Adek336 »

try setting the direction flag. perhaps it copies memory downwards? i think the opcodes were cld and std
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:memcpy function (nasm)

Post by Pype.Clicker »

Code: Select all

    push ebp
    mov ebp, esp
should be a better start ;)
Schol-R-LEA

Re:memcpy function (nasm)

Post by Schol-R-LEA »

It's actually very simple: while you save the old EBP, you aren't setting it to the current ESP, so it's trying to use the stack frame from the calling function (EDIT: Looks like Pype beat me to the punch on this one; I spent too much time writing the test code, I guess). There's also a bug in the return value; not only is it using the wrong offset when setting the return value, it sets the return value after restoring the frame buffer, which means it would have the wrong value entirely. Try this:

Code: Select all

[global _kmemcpy]  ; void *kmemcpy(void *dest, const void *src, unsigned int count);

;after three pushes
;ebp + 8  = dest
;ebp + 12 = src
;ebp + 16 = count

_kmemcpy:
   push ebp

   ; set the frame pointer to the current stack pointer
   mov ebp, esp

   push esi
   push edi


   mov edi, [ebp + 8]       ; edi = dest

   ; since the return value is invariant, set it now
   mov eax, edi             ; eax = return value = dest

   mov esi, [ebp + 12]      ; esi = src
   mov ecx, [ebp + 16]      ; ecx = count
   rep movsb                ; for(i = 0; i < ecx; i++){edi[i]=esi[i]}

   pop edi
   pop esi
   pop ebp
   ret
The 'k' prefix is simply to avoid a conflict with the default memcpy() in the existing standard library while testing. I am assuming that you are using COFF, PE or a.out format, also, as the underscores are not needed in ELF. I've test the following code with this (or rather, with the GAS equivalent, in order to simplify some compiler issues), and it works correctly:

Code: Select all

#include <stdio.h>

void *kmemcpy(void *dest, const void *src, unsigned int count);
 
 main()
 {
  int i; 
   
  char alphabet[26] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                       'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                       'Q', 'R', 'S', 'T', 'U', 'W', 'X', 'Y', 'Z'};
                       
  char numerals[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
  
  char* p;
  
  p =  kmemcpy((void *)(alphabet + 7), (void *)numerals, 6);
  
  if(p == (alphabet + 7))
    {
      for (i = 0; i < 26; i++)
          putchar(alphabet[i]);
    }
  else
    {
      puts("Incorrect return value.");
    }
}
This prints "ABCDEFG012345NOPQRSTUVWXYZ". The actual AT&T code which I tested was:

Code: Select all

.globl _kmemcpy

/* void *kmemcpy(void *dest, const void *src, unsigned int count);

the GAS version of the kmemcpy() function */

/*
 after three pushes
 ebp + 8  = dest
 ebp + 12 = src
 ebp + 16 = count
*/

_kmemcpy:
   pushl %ebp

   /* set the frame pointer to the current stack pointer */
   movl %esp, %ebp

   pushl %esi
   pushl %edi

   movl 8(%ebp),  %eax         /* eax = return value = dest */???
   movl %eax,     %edi         /* edi = dest */
   movl 12(%ebp), %esi         /* esi = src */
   movl 16(%ebp), %ecx         /* ecx = count */
   rep
   movsb                   /* for(i = 0; i < ecx; i++){edi[i]=esi[i]} */

   popl %edi
   popl %esi
   popl %ebp
   
   ret
HTH. C&CW.
ich_will

Re:memcpy function (nasm)

Post by ich_will »

thanks, now it works.
Post Reply