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.