Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 为什么下面的x86_64程序集会给我一个分段错误?_Assembly_X86 64_X86 - Fatal编程技术网

Assembly 为什么下面的x86_64程序集会给我一个分段错误?

Assembly 为什么下面的x86_64程序集会给我一个分段错误?,assembly,x86-64,x86,Assembly,X86 64,X86,到目前为止,我一直在学习编写一些x86_64程序集。我读到可以减去RSP来向下扩展堆栈并分配空间,因此我编写了以下代码: push %rbp movq %rsp, %rbp subq $16, %rsp movq $200, -8(%rsp) movq $300, -16(%rsp) popq %rbp retq 据我所知,这将生成一个函数,在该函数中,它在堆栈帧上设置一个值,然后在堆栈上分配16个字节,并将值分别设置为-8和-16到200和300。 然而,当我用gcc运行这个程序时,我得到了

到目前为止,我一直在学习编写一些x86_64程序集。我读到可以减去RSP来向下扩展堆栈并分配空间,因此我编写了以下代码:

push %rbp
movq %rsp, %rbp
subq $16, %rsp
movq $200, -8(%rsp)
movq $300, -16(%rsp)
popq %rbp
retq
据我所知,这将生成一个函数,在该函数中,它在堆栈帧上设置一个值,然后在堆栈上分配16个字节,并将值分别设置为-8和-16到200和300。
然而,当我用gcc运行这个程序时,我得到了一个分段错误。虽然如果我删除程序的
子部分
,它仍能正常工作。我想我误解了什么,那么这里到底发生了什么?

正如Jester所说,问题是当你
pop%rbp
/
ret
时,堆栈指针指向其他地方,所以你没有得到旧的
%rbp
和返回地址。(由于另一个潜在的错误,您从不向弹出的位置写信,因此我无法确切地告诉您将
ret
发送到哪个无效地址。)

如果您制作了一个堆栈帧(
mov%rsp,%rbp
),那么使用相对于
%rbp
的偏移量是正常的。有趣的事实:
movq$200,-8(%rbp)
比同等的
movq$200,8(%rsp)
花费更多。(遗憾的是,使用
%rsp
作为基址寄存器总是需要SIB字节来编码有效地址。)

使用
%rbp
还意味着引用任何给定堆栈地址的表达式即使在推/弹出内容时也不会更改(在32位代码中,堆栈参数ABI很常见,但在64位代码中很少见。64位gcc在32位之前切换为-fomit帧指针)


您的
movq$200,-8(%rsp)
使用您保留的16B之外的空间。这就是我前面提到的“其他潜在bug”

在当前的
%rsp
下使用最多128B实际上并不是SysV ABI中的一个错误:异步事件(信号处理程序等)避免阻塞,因此不调用任何其他函数的小函数可以避免花费指令修改
%rsp
以保留空间。x86-64有15个通用寄存器(不计算堆栈指针),因此中小型函数通常不需要使用堆栈,而只需要保存/恢复调用保留的寄存器。或用于本地阵列

Windows ABI不使用红色区域,因此
%rsp
下面的内存可能会被踩到,即使您自己不使用
调用


有关调用约定/ABI的链接,请参见tag wiki。

正如Jester所说,问题是当您
pop%rbp
/
ret
时,堆栈指针指向其他地方,因此无法获取旧的
%rbp
和返回地址。(由于另一个潜在的错误,您从不向弹出的位置写信,因此我无法确切地告诉您将
ret
发送到哪个无效地址。)

如果您制作了一个堆栈帧(
mov%rsp,%rbp
),那么使用相对于
%rbp
的偏移量是正常的。有趣的事实:
movq$200,-8(%rbp)
比同等的
movq$200,8(%rsp)
花费更多。(遗憾的是,使用
%rsp
作为基址寄存器总是需要SIB字节来编码有效地址。)

使用
%rbp
还意味着引用任何给定堆栈地址的表达式即使在推/弹出内容时也不会更改(在32位代码中,堆栈参数ABI很常见,但在64位代码中很少见。64位gcc在32位之前切换为-fomit帧指针)


您的
movq$200,-8(%rsp)
使用您保留的16B之外的空间。这就是我前面提到的“其他潜在bug”

在当前的
%rsp
下使用最多128B实际上并不是SysV ABI中的一个错误:异步事件(信号处理程序等)避免阻塞,因此不调用任何其他函数的小函数可以避免花费指令修改
%rsp
以保留空间。x86-64有15个通用寄存器(不计算堆栈指针),因此中小型函数通常不需要使用堆栈,而只需要保存/恢复调用保留的寄存器。或用于本地阵列

Windows ABI不使用红色区域,因此
%rsp
下面的内存可能会被踩到,即使您自己不使用
调用


有关调用约定/ABI的链接,请参见标记wiki。

您需要释放分配的空间。通过将
rbp
移回
rsp
或撤消
sub
@Jester,我可以在rsp上做与减法和加16相反的操作吗?是的,如果不使用帧指针,这是通常的方法。当你有一个帧指针时,它通常会移回
rsp
。哇!这里不是指
(%rBp)
吗?如果要将这些值写入刚刚分配的堆栈部分,您是指
-8(%rBp)
-16(%rBp)
。您需要释放分配的空间。通过将
rbp
移回
rsp
或撤消
sub
@Jester,我可以在rsp上做与减法和加16相反的操作吗?是的,如果不使用帧指针,这是通常的方法。当你有一个帧指针时,它通常会移回
rsp
。哇!这里您不是指
(%rBp)
吗?如果您打算将这些值写入刚刚分配的堆栈部分,您是指
-8(%rBp)
-16(%rBp)