我遇到分段错误 - 装配
I am getting segmentation fault - assembly
我正在尝试汇编 x86,但出现 zsh: segmentation fault ./test
错误。
我正在尝试自己制作一些基本库以供以后使用。它分为三个文件 - string.asm 用于字符串操作,stdio.asm 用于标准 io 操作,libtest.asm 用于库测试。我本来打算添加更多的功能,但我想先测试这些。
;;;;;;;;;;;;;;;;;
;;; 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
执行:
$ 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
我不知道错误在哪里,所以我很感激你们的帮助。
谢谢!
两个错误:
; moving length
mov ecx, eax
; moving syscall num and out desc
mov eax, 4
mov ebx, [stdout]
; syscall
int 0x80
参考Linux system call conventions,write
系统调用需要ecx
中的缓冲区指针和edx
中的长度。您的长度在 ecx
中,而缓冲区指针根本不存在。做到:
mov edx, eax
mov ecx, dword [ebp+8]
mov eax, 4
mov ebx, [stdout]
int 0x80
接下来看:
cmp [ebx+eax], byte 0x00
inc eax
jne loop1
inc
指令根据其输出设置零标志。因此,您的 jne
不会根据 cmp
的结果分支,而是根据 eax
是否递增到零(即环绕)。所以你的循环会迭代太多次。
jne
需要紧跟在 cmp
之后,中间没有其他 flag-modifying 指令。有几种方法可以重写。一个是:
mov eax, -1
loop1:
inc eax
cmp byte [ebx+eax], 0x00
jne loop1
请注意,这样就不需要在末尾添加额外的 dec eax
。
修复这些后,程序对我有用。
我正在尝试汇编 x86,但出现 zsh: segmentation fault ./test
错误。
我正在尝试自己制作一些基本库以供以后使用。它分为三个文件 - string.asm 用于字符串操作,stdio.asm 用于标准 io 操作,libtest.asm 用于库测试。我本来打算添加更多的功能,但我想先测试这些。
;;;;;;;;;;;;;;;;;
;;; 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
执行:
$ 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
我不知道错误在哪里,所以我很感激你们的帮助。
谢谢!
两个错误:
; moving length
mov ecx, eax
; moving syscall num and out desc
mov eax, 4
mov ebx, [stdout]
; syscall
int 0x80
参考Linux system call conventions,write
系统调用需要ecx
中的缓冲区指针和edx
中的长度。您的长度在 ecx
中,而缓冲区指针根本不存在。做到:
mov edx, eax
mov ecx, dword [ebp+8]
mov eax, 4
mov ebx, [stdout]
int 0x80
接下来看:
cmp [ebx+eax], byte 0x00
inc eax
jne loop1
inc
指令根据其输出设置零标志。因此,您的 jne
不会根据 cmp
的结果分支,而是根据 eax
是否递增到零(即环绕)。所以你的循环会迭代太多次。
jne
需要紧跟在 cmp
之后,中间没有其他 flag-modifying 指令。有几种方法可以重写。一个是:
mov eax, -1
loop1:
inc eax
cmp byte [ebx+eax], 0x00
jne loop1
请注意,这样就不需要在末尾添加额外的 dec eax
。
修复这些后,程序对我有用。