为什么“ push”会在此处引起段错误?

时间:2020-09-27 15:39:14

标签: assembly x86-64 nasm

我正在为几个月前写的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

0 个答案:

没有答案