Home > Mobile >  I am getting segmentation fault - assembly
I am getting segmentation fault - assembly

Time:04-24

I'm trying assembly x86 but I got the zsh: segmentation fault ./test error. I am trying to make some basic library myself to use later on. It's divided into three files - string.asm for string manipulation, stdio.asm for standard io operations, and libtest.asm for library testing. I was planning to add more functions, but I wanted to test these first.

;;;;;;;;;;;;;;;;;
;;; stdio.asm ;;;
;;;;;;;;;;;;;;;;;
global print ; void print(string* text)
extern strlen ; int32 strlen(string* string)

section .data
stdin dd 0
stdout dd 1
stderr dd 2
newline db 0x0a, 0x00

section .text

print:
    push ebp
    mov ebp, esp
    push eax
    push ebx
    push ecx
    push edx
    
    ; get parameters
    mov ecx, dword [ebp 8]
    ; call strlen
    push ecx
    call strlen
    add esp, 4
    ; moving length
    mov ecx, eax
    ; moving syscall num and out desc
    mov eax, 4
    mov ebx, [stdout]
    ; syscall
    int 0x80
    
    pop edx
    pop ecx
    pop ebx
    pop eax
    mov esp, ebp
    pop ebp
    ret

;;;;;;;;;;;;;;;;;
;; string.asm ;;;
;;;;;;;;;;;;;;;;;
global strlen ; int32 strlen(string* str)

section .text
strlen:
    push ebp
    mov ebp, esp
    push ebx
    
    mov ebx, dword [ebp 8]
    
    mov eax, 0
    loop1:
        cmp [ebx eax], byte 0x00
        inc eax
        jne loop1
    dec eax
    
    pop ebx
    mov esp, ebp
    pop ebp
    ret

;;;;;;;;;;;;;;;;;
;; libtest.asm ;;
;;;;;;;;;;;;;;;;;
global _start

extern print

section .data
msg db 'Hello, world!', 0x0a, 0x00

section .text
_start:
    push msg
    call print
    add esp, 4
    
    mov eax, 1
    mov ebx, 0
    int 0x80

Execution:

$ nasm -f elf32 stdio.asm

$ nasm -f elf32 string.asm

$ nasm -f elf32 libtest.asm

$ ld -m elf_i386 -o test stdio.o string.o libtest.o

$ ./test

I don't know where the error could be, so I would appreciate any help from you guys.

Thanks!

CodePudding user response:

Two bugs:

    ; moving length
    mov ecx, eax
    ; moving syscall num and out desc
    mov eax, 4
    mov ebx, [stdout]
    ; syscall
    int 0x80

Referring to Linux system call conventions, the write system call needs the buffer pointer in ecx and the length in edx. You have the length in ecx and the buffer pointer is nowhere at all. Make it:

    mov edx, eax
    mov ecx, dword [ebp 8]
    mov eax, 4
    mov ebx, [stdout]
    int 0x80

Next, look at:

        cmp [ebx eax], byte 0x00
        inc eax
        jne loop1

The inc instruction sets the zero flag according to its output. So your jne doesn't branch on the result of the cmp, but rather on whether eax was incremented to zero (i.e. wrapped around). So your loop will iterate far too many times.

The jne needs to be immediately after the cmp, with no other flag-modifying instructions in between. There are several ways you could rewrite. One would be:

    mov eax, -1
loop1:
        inc eax
        cmp byte [ebx eax], 0x00
        jne loop1

Note this eliminates the need for the extra dec eax at the end.

After fixing these, the program works for me.

  • Related