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.