0

First of all I want to start off by saying that I've read this, this and this question. Yet none of the answers provided on these questions were sufficient/had detailed enough information in order to answer my question. Moreover, they are all 4 - 6 years old which makes them outdated. With that being said, I opened a new question here.

I am trying to make a simple program that displays 1 - 4 matrices in Linux 32-bit assembly with NASM syntax, I've made a procedure that should print the simple 1x1 matrix.

section .data
    msg1:       db 'output:', 10
    msg1len:    equ $-msg1

    endmsg:     db 10

    m1r1:       db '5'

    m2r1:       db '1', '4'
    m2r2:       db '2', '6'

    m3r1:       db '8', '3', '4'
    m3r2:       db '9', '2', '1'
    m3r3:       db '1', '5', '6'

    m4r1:       db '6', '3', '1', '7'
    m4r2:       db '1', '9', '8', '4'
    m4r3:       db '5', '0', '1', '2'
    m4r4:       db '2', '7', '1', '0'

section .bss
    output1:    resb 5
    output2:    resb 7*2
    output3:    resb 9*3
    output4:    resb 11*4


section .text
    global  _start

_start:
    mov eax, 1
    call printMatrix


_exit:
    mov eax, 0
    mov ebx, 1
    int 80h

;description:
;   displays a visual representation of
;   a matrix from size 1 through 4
;parameters:
;   eax - matrix size
printMatrix:
    push eax
    push ebx
    push ecx
    push edx
    push esi

    cmp eax, 1
    je .printMatrix1

    cmp eax, 2
    je .printMatrix2

    cmp eax, 3
    je .printMatrix3

    cmp eax, 4
    je .printMatrix4

.printMatrix1:
    mov eax, '[ '
    mov [output1], eax
    mov eax, m1r1
    mov [output1 + 2], eax
    mov eax, ' '
    mov [output1 + 3], eax
    mov eax, ']'
    mov [output1 + 4], eax

    mov eax, 4
    mov ebx, 1
    mov ecx, [output1]
    mov edx, 5
    jmp .exit

.printMatrix2:

    jmp .exit

.printMatrix3:

    jmp .exit

.printMatrix4:

    jmp .exit

.exit:
    pop esi
    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

printEndl:
    push eax
    push ebx
    push ecx
    push edx
    mov eax, 4
    mov ebx, 1
    mov ecx, endmsg
    mov edx, 1
    int 80h
    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

Yet when I compile via:

nasm -f elf32 matrix.asm

And link using:

ld -m elf_i386 -s -o matrix matrix.o

I get no errors/warnings whatsoever, but when I run the program using ./matrix I get segmentation fault (core dumped) error. Now I must note that this question provided a rather well definition for what is a segmentation fault and what it's usually caused by, it was a bit unclear though. What I seek is:

  1. A proper explanation/definition of a segmentation in terms of memory and assembly.
  2. What have caused the fault in this particular case (According to the first and second links, I suspect it has something to do with the jumps or calling procedures and the stack. However I've been sitting here for hours trying to figure out what caused it with no success).
  3. How to avoid such a fault and recommended future practices.
Community
  • 1
  • 1
Elian Kamal
  • 532
  • 7
  • 20
  • Use a debugger (`gdb`) to run your code and tell you where the segmentation fault. Segmentation fault (or segfault) is a general condition where you are accessing memory in a way that the hardware doesn't allow. you are likely using a pointer that is invalid. – Michael Petch May 08 '16 at 15:03
  • And I'm not sure why you use _LD_ with the `-s` option. that strips off all the symbols, so if you do use a debugger you make your life incredibly difficult. – Michael Petch May 08 '16 at 15:14
  • 1
    If you use a debugger you might realize your `int 80h` doesn't exit the program and falls through into the rest of your code a second time. The issue in your case is that the syscall number is suppose to be placed into _EAX_ before doing `int 80h` (in your case the syscall for sys_exit = 1), the return value for sys_exit is suppose to be in _EBX_. You have them backwards. A syscall table for 32-bit Linux is here: http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html – Michael Petch May 08 '16 at 15:20
  • Something you should be aware of is that when you do `mov [output1], eax` you are moving the **entire** 4 bytes that make up a 32-bit register and moving them to memory. `Output1` is allocated 5 bytes. Imagine what will happen when 4 bytes is written with `mov [output1 + 4], eax` - you will clobber the first few bytes of memory that `output2` was allocated. – Michael Petch May 08 '16 at 15:37
  • Thanks for the correction. Now the fault isn't there anymore, although the program still isn't printing out the output, I'll check it out in the debugger after I'll learn how to use it properly since I am new to Linux assembly. however from your comments I understand that not exiting the program caused the program to start reading again the codes and that was an illegal access to the code segment? – Elian Kamal May 08 '16 at 15:44
  • Effectively your `int 80h` did nothing because it was coded incorrectly. The code of your `printMatrix` function was executed a second time (after returning from `int 80h`) by falling through without actually doing a _CALL_. Because no _CALL_ was used to start executing `printMatrix` - when `printMatrix` hit the `ret` instruction to return, there was no return address on the stack and it attempted to return to the address of whatever garbage happened to be at the top of the stack (almost likely invalid memory address that could't be executed) which resulted in a `segfault` – Michael Petch May 08 '16 at 15:47
  • On x86 Linux executing code that the system hasn't marked as executable will result in a segfault. Reading from memory that you don't have permission to read will result in a segfault, and writing to memory you don't have write permission to will result in a segfault. These typically make up the bulk of all segfaults. It generally comes down to accessing memory in a way that is prohibited by the CPU. using a debugger is a good tool to see what exactly is going on. – Michael Petch May 08 '16 at 15:53

0 Answers0