简体   繁体   中英

Accessing C pointers from assembly

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM