我正在为几个月前写的LISP解释器编写编译器。我当前的方法是生成程序集(nasm),然后使用nasm和gcc进行编译+链接。我在MacOS上。
我目前正在调试一个相当奇怪的段错误。有问题的代码段非常干净(出于调试目的,我缩进以跟踪堆栈):
; Above this point, we do some math and stick the final result into `rax`
; hand written
push rbp
mov rbp, rsp
lea rsi, [0x101]
lea rdi, [rel dbg]
call _printf
mov rsp, rbp
pop rbp
; end hand written
push rax ; push result onto stack
; hand written
push rbp
mov rbp, rsp
lea rsi, [0x102]
lea rdi, [rel dbg]
call _printf
mov rsp, rbp
pop rbp
; end hand written
这行特殊代码在操作之后发生,我们需要保存其结果以供以后调用(因此我们将其放在栈上)。但是我从中得到的输出是:
101
zsh: segmentation fault ./bin
这意味着我以某种方式在这两个printf调用之间进行隔离,其中只有一条指令。我将附加整个源代码(生成并很难阅读,对不起),但是我不会迷惑rsp
,而且我肯定不会用完堆栈空间。
有什么想法吗?
(LISP源代码,在我的怪异方言中-我知道这段代码已损坏,应该永远循环,但甚至还没有达到目的)
(let (REC self n tot) (self self (- n 1) (* n tot)))
(let (fib n) (REC REC n 1))
(fib 5)
我的编译步骤:
nasm my_prog.asm -o my_prog.o -f macho64
gcc my_prog.o -o bin
./bin
(整个源文件)
global _main
extern _printf
extern _fflush
section .text
__init:
ret
_REC:
; START CALL for [rel __local0]
push qword [rel __local0]
push qword [rel __local1]
push qword [rel __local2]
push rbp
mov rbp, rsp
; COMPUTE ARGS for [rel __local0]
mov [rel __local0], rdi
mov [rel __local1], rsi
mov [rel __local2], rdx
; START INLINE for sub
push rcx
; SETUP ARGS for sub (inline)
; MOV ARGS for sub (inline)
mov rax, [rel __local1]
mov rcx, 1
; START BODY for sub (inline)
sub rax, rcx
; RESTORE STATE after sub (inline)
pop rcx
; END INLINE for sub
; hand written
push rbp
mov rbp, rsp
lea rsi, [0x101]
lea rdi, [rel dbg]
call _printf
mov rsp, rbp
pop rbp
; end hand written
push rax ; push result onto stack
; hand written
push rbp
mov rbp, rsp
lea rsi, [0x102]
lea rdi, [rel dbg]
call _printf
mov rsp, rbp
pop rbp
; end hand written
; START INLINE for mul
; SETUP ARGS for mul (inline)
; MOV ARGS for mul (inline)
mov rax, [rel __local1]
mov rcx, [rel __local2]
; hand written
push rbp
mov rbp, rsp
lea rsi, [0x10]
lea rdi, [rel dbg]
call _printf
mov rsp, rbp
pop rbp
; end hand written
; START BODY for mul (inline)
mul rcx
; RESTORE STATE after mul (inline)
; hand written
push rbp
mov rbp, rsp
lea rsi, [rax + 10]
lea rdi, [rel fmt]
call _printf
mov rsp, rbp
pop rbp
; end hand written
; END INLINE for mul
; hand written
push rbp
mov rbp, rsp
mov rsi, rax
lea rdi, [rel fmt]
call _printf
mov rsp, rbp
pop rbp
; end hand written
push rax ; push result onto stack
; POSITION ARGS for [rel __local0]
mov rdi, [rel __local0]
pop r10 ; pop result
mov rsi, r10
pop r10 ; pop result
mov rdx, r10
call [rel __local0] ; make the actual call
mov rsp, rbp
pop rbp
pop qword [rel __local2]
pop qword [rel __local1]
pop qword [rel __local0]
; END CALL for [rel __local0]
ret
_fib:
; START CALL for REC
push qword [rel __local0]
push rbp
mov rbp, rsp
; COMPUTE ARGS for REC
mov [rel __local0], rdi
; POSITION ARGS for REC
lea rdi, [rel _REC]
mov rsi, [rel __local0]
mov rdx, 1
call _REC ; make the actual call
.__cleanup:
mov rsp, rbp
pop rbp
pop qword [rel __local0]
; END CALL for REC
ret
_main:
; call init
push rbp
mov rbp, rsp
call __init
mov rsp, rbp
pop rbp
; START CALL for printf
push rbp
mov rbp, rsp
; COMPUTE ARGS for printf
; START CALL for fib
push rbp
mov rbp, rsp
; COMPUTE ARGS for fib
; POSITION ARGS for fib
mov rdi, 5
call _fib ; make the actual call
mov rsp, rbp
pop rbp
; END CALL for fib
push rax ; push result onto stack
; POSITION ARGS for printf
lea rdi, [rel fmt]
pop r10 ; pop result
mov rsi, r10
call _printf ; make the actual call
mov rsp, rbp
pop rbp
; END CALL for printf
jmp _exit
_exit:
; say bye
push rbp
mov rbp, rsp
mov rdi, 0
call _fflush ; flush stdout
mov rsp, rbp
pop rbp
mov rax, 0x2000006 ; close
mov rdi, 1 ; stdout
syscall
; exit
mov rax, 0x2000001 ; exit
mov rdi, 0
syscall
section .bss
section .data
__local0: dq 0
__local1: dq 0
__local2: dq 0
__local3: dq 0
__local4: dq 0
__local5: dq 0
fmt: db "%d", 10, 0
dbg: db "%x", 10, 0
__exit_msg: db "Exiting now...", 10
.len equ $ - __exit_msg