Reputation: 13
I am currently learning how to intermix C code with assembly. In the .c file I have the following code:
extern int replace(char *c);
int main(){
static char * string2 = "aaab\n";
static char * string3;
string3 = (char *) replace(string2);
*string3 = 'A';
printf("%s",string3);
}
The assembly function replace has the following code:
section .data
string db "Test",10,0
section .text
global replace
replace:
enter 0,0
mov eax, string
leave
ret
This works very well and shows that the C program has access to the .asm file memory. However when I try to write to the pointer string2, say by adding the following code to the function replace,
mov edx, [ebp + 8]
mov byte [edx], 10
I obtain a segmentation fault. (From my understanding the latter is passing the address of the pointer to edx, thus edx = string2, and then assigning *string2 = 10 via *edx = 10). Could you please explain what I am doing wrong?
EDIT: I figured out that when I do a string3 = (char *) malloc(10); then I can indeed do in assembly
mov edx, [ebp + 8]
move byte [edx], 10
and obtain correct results. I would still be grateful for an explanation of why is this so. Is this due to the heap being publicly accessible? Is it perhaps because before char *string = "Hi" was pointing to a read-only part of the memory where strings are stored? I am learning this on my own so I would be grateful for clarifications.
Upvotes: 0
Views: 731
Reputation: 84521
Your problem in your C program is due to creating a string literal that cannot be modified with:
static char *string2 = "aaab\n";
You assign pointer string3
the address of string2
via your replace call:
string3 = (char *) replace(string2);
You then attempt to modify read-only memory (string2
) by changing the first character from a
to A
with:
*string3 = 'A';
Which results in the segfault. To fix the segfault, just change the string2
declaration to:
static char string2[] = "aaab\n";
So that it is simply a character array and not a string literal.
When you create a literal with char *label = "stuff";
you create a literal in read only memory. You can easily see this for yourself by dumping the assembly of the C program with gcc -S -masm=intel -o file.asm file.c
. If you look, you will see that "aaab\n"
is created in the .rodata
(read-only) data section:
.section .rodata
.string "aaab\n"
.data
.align 8
Upvotes: 2