3

I'm just trying to load the value of myarray[0] to eax:

        .text
        .data

        # define an array of 3 words
array_words:     .word 1, 2, 3

        .globl main

main:
        # assign array_words[0] to eax
        mov $0, %edi
        lea array_words(,%edi,4), %eax

But when I run this, I keep getting seg fault. Could someone please point out what I did wrong here?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
One Two Three
  • 22,327
  • 24
  • 73
  • 114
  • Is the `lea` the last instruction in your code? Means, is the above snippet all you have? – Andreas Fester Dec 18 '15 at 08:21
  • Editor's note: The original title was "segmentation fault when assigning value of an array to eax". I retitled to make this a better duplicate target (where the link title points out the problem) for other questions that have this simple mistake, which can be hard to spot if you aren't thinking about it. – Peter Cordes Sep 14 '20 at 18:36

2 Answers2

4

It seems the label main is in the .data section.

It leads to a segmentation fault on systems that doesn't allow to execute code in the .data section. (Most modern systems map .data with read + write but not exec permission.)

Program code should be in the .text section. (Read + exec)

Surprisingly, on GNU/Linux systems, hand-written asm often results in an executable .data unless you're careful to avoid that, so this is often not the real problem: See Why data and stack segments are executable? But putting code in .text where it belongs can make some debugging tools work better.


Also you need to ret from main or call exit (or make an _exit system call) so execution doesn't fall off the end of main into whatever bytes come next. See What happens if there is no exit system call in an assembly program?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • This solved my problem! Never would have thought such a thing could cause "seg fault"... in my mind, seg fault usually indicates I've got some un-initted variable somewhere – One Two Three Dec 18 '15 at 08:33
  • @OneTwoThree: data-section memory is mapped with read/write but not execute permission. Thus, the C runtime startup code causes a segfault when it runs a `call main` instruction. The extra permission bit for memory pages is a security feature ("NX"). – Peter Cordes Dec 20 '15 at 00:35
2

You need to properly terminate your program, e.g. on Linux x86_64 by calling the sys_exit system call:

...
main:
     # assign array_words[0] to eax
     mov $0, %edi
     lea array_words(,%edi,4), %eax

     mov $60, %rax       # System-call "sys_exit"
     mov $0, %rdi        # exit code 0
     syscall

Otherwise program execution continues with the memory contents following your last instruction, which are most likely in all cases invalid instructions (or even invalid memory locations).

Andreas Fester
  • 36,091
  • 7
  • 95
  • 123
  • Or since this is `main` (not `_start`), it's a function so you can simply `ret`. Also, in x86-64 you should use 64-bit address-size even if you want to truncate the result to 32-bit, like `mov $edi,0` ; `lea array_words(,%rdi,4), %rax` or `lea array_words(,%rdi,4), %eax`. – Peter Cordes Sep 14 '20 at 18:40