I want to write a function in x86 which will be called from C program.
The function should look like this:
char *remnth(char *s, int n);
I want it to remove every nth letter from string s and return that string. Here's my remnth.s file:
section.text
global remnth
remnth:
; prolog
push ebp
mov ebp, esp
; procedure
mov eax, [ebp+8]; Text in which I'm removing every nth letter
mov ebx, [ebp+12]; = n
mov ecx, [ebp+8] ; pointer to next letter (replacement)
lopext:
mov edi, [ebp+12] ; edi = n //setting counter
dec edi ; edi-- //we don't go form 'n' to '1' but from 'n-1' to '0'
lop1:
mov cl, [ecx] ; letter which will be a replacement
mov byte [eax], cl ; replace
test cl,cl ; was the replacement equal to 0?
je exit ; if yes that means the function is over
inc eax ; else increment pointer to letter which will be replaced
inc ecx ; increment pointer to letter which is a replacement
dec edi ; is it already nth number?
jne lop1 ; if not then repeat the loop
inc ecx ; else skip that letter by proceeding to the next one
jmp lopext ; we need to set counter (edi) once more
exit:
; epilog
pop ebp
ret
The problem is that when I'm calling this function from main()
in C I get Segmentation fault (core dumped)
From what I know this is highly related to pointers, in this case I'm returning *char
, and since I've seen some functions that returns int
and they worked just fine, I suspect that I forgot about something important with returning a *char
properly.
This is what my C file looks like:
#include <stdio.h>
extern char *remnth(char *s,int n);
int main()
{
char txt[] = "some example text\0";
printf("orginal = %s\n",txt);
printf("after = %s\n",remnth(txt,3));
return 0;
}
Any help will be appreciated.
You're using ecx
as a pointer, and cl
as a work register. Since cl
is the low 8 bits of ecx
, you're corrupting your pointer with the mov cl, [ecx]
instruction. You'll need to change one or the other. Typically, al
/ax
/eax
/rax
is used for a temporary work register, as some accesses to the accumulator use shorter instruction sequences. If you use al
as a work register, you'll want to avoid using eax
as a pointer and use a different register instead (remembering to preserve its contents if necessary).