Macos 为什么这个x86代码会抛出一个segfault?
我试图在x86汇编中添加两个数字2和3。我不再主要使用寄存器,而是从堆栈中推送和弹出值(这是Forth编译器项目的一部分,这就是为什么)。然而,我的代码给了我一个分段错误。我已经在GDB中运行了它,但是回溯并没有给我任何有价值的信息。有人知道我的代码中发生此错误的确切原因吗?(我是这样编译的(在Mac上):Macos 为什么这个x86代码会抛出一个segfault?,macos,assembly,stack,x86-64,Macos,Assembly,Stack,X86 64,我试图在x86汇编中添加两个数字2和3。我不再主要使用寄存器,而是从堆栈中推送和弹出值(这是Forth编译器项目的一部分,这就是为什么)。然而,我的代码给了我一个分段错误。我已经在GDB中运行了它,但是回溯并没有给我任何有价值的信息。有人知道我的代码中发生此错误的确切原因吗?(我是这样编译的(在Mac上):gcc-g-mstackreallign-masm=intel-o test test.asm) push-rdi/ret相当于jmp-rdi。像正常人一样返回RAX中的值。e、 g.lea-
gcc-g-mstackreallign-masm=intel-o test test.asm
)
push-rdi
/ret
相当于jmp-rdi
。像正常人一样返回RAX中的值。e、 g.lea-rax,[rdi+rsi]
@Peter-Cordes正如我所说,我没有在rax中返回值的原因是,这段代码来自我正在构建的第四个编译器。在Forth中,结果将被弹出到堆栈中,而不是返回。考虑到这一点,我如何使我的代码工作——而不仅仅是遵循调用约定?显然这是行不通的。您不必在每一步都将第四个堆栈精确地映射到x86-64堆栈,是吗?e、 g.让调用者按下返回值寄存器。或者Forth函数可以在返回之前推送多个东西吗?在这种情况下,在按下返回值之前,您可能会将返回地址弹出到tmp寄存器中。@PeterCordes我会尝试一下,让您知道它是如何运行的。相关但不完全重复:-您可以对堆栈执行奇怪的操作,但是您必须确保调用者和被调用者在所有问题上达成一致,并跳到正确的位置。push rdi
/ret
相当于jmp rdi
。像正常人一样返回RAX中的值。e、 g.lea-rax,[rdi+rsi]
@Peter-Cordes正如我所说,我没有在rax中返回值的原因是,这段代码来自我正在构建的第四个编译器。在Forth中,结果将被弹出到堆栈中,而不是返回。考虑到这一点,我如何使我的代码工作——而不仅仅是遵循调用约定?显然这是行不通的。您不必在每一步都将第四个堆栈精确地映射到x86-64堆栈,是吗?e、 g.让调用者按下返回值寄存器。或者Forth函数可以在返回之前推送多个东西吗?在这种情况下,您可以在按下返回值之前将返回地址弹出到tmp寄存器中。@PeterCordes我会尝试一下,让您知道它是如何运行的。相关但不完全重复:-您可以对堆栈执行奇怪的操作,但您必须确保调用者和被调用者对所有内容都达成一致,并跳到正确的位置。
.global _main
.text
plus:
add rdi, rsi
push rdi # push accumulated rdi value onto stack
ret
minus:
sub rdi, rsi
push rdi
ret
_main:
push 2 # push 2 and 3 onto stack
push 3
pop rdi # as preparation for the function call, load rdi and rsi with 2 and 3
pop rsi
call plus
pop rax # put result into rax
mov rdi, rax # then, put the result into rdi
mov rax, 0x2000001 # exit system call
syscall