'Assembly i386 - segmentation fault

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 some first. When I ran it, I got zsh: segmentation fault ./test. I tried debugging it with gdb but the error appeared out of nowhere... Here is my code:

;;;;;;;;;;;;;;;
;; stdio.asm ;;
;;;;;;;;;;;;;;;
global print ; void print(string* text)
global println ; void println(string* text)
global printn ; void printn(char* text, int32 count)
global printnln ; void printnln(char* text, int32 count)

extern strlen ; int32 strlen(string* string)

; CONSTANTS
SYS_WRITE equ 4 ; x86 -> 1

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

section .text
printn:
    push ebp
    mov ebp, esp
    pusha
    
    ; get parameters
    mov edx, dword [ebp+8] ; length
    mov ecx, dword [ebp+12] ; text
    ; mov remainin
    mov eax, SYS_WRITE
    mov ebx, [stdout]
    ; call system
    int 0x80
    
    popa
    mov esp, ebp
    pop ebp
    ret
printnln:
    push ebp
    mov ebp, esp
    pusha
    
    ; push parameters
    push dword [ebp+12] ; text
    push dword [ebp+8] ; length
    ; call printn
    call printn
    ; clear stack; not needed
    add esp, 8
    ; push newline and call print
    push newline
    call print
    
    popa
    mov esp, ebp
    pop ebp
    ret
print:
    push ebp
    mov ebp, esp
    pusha
    
    ; push string to write
    push dword [ebp+8]
    ; get length to eax
    call strlen
    ; ebp+8 still on stack; pushing length
    push eax
    ; call printn
    call printn
    
    popa
    mov esp, ebp
    pop ebp
    ret
println:
    push ebp
    mov ebp, esp
    pusha
    
    ; call print
    push dword [ebp+8]
    call print
    add esp, 4
    ; print new line
    push newline
    call print
    add esp, 4
    
    popa
    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, -1
    loop1:
        inc eax
        cmp [ebx+eax], byte 0x00
        jne loop1
    
    pop ebx
    mov esp, ebp
    pop ebp
    ret

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

extern print

section .data
msg db 'Hello, mom!', 0x00
len equ $-msg

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!



Solution 1:[1]

So, it was because of that pusha and popa instruction. I didn't realize these were using also esp and ebp registers, so it messed up the stack. Using...

%macro pushr 0
    push eax
    push ebx
    push ecx
    push edx
    push esi
    push edi
%endmacro
%macro popr 0
    pop edi
    pop esi
    pop edx
    pop ecx
    pop ebx
    pop eax
%endmacro

...it's now working.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 UiOpL4504