我遇到分段错误 - 装配

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 conventionswrite系统调用需要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

修复这些后,程序对我有用。