.text .data 和 main 的分段错误(主要在 .data 部分)
Posted
技术标签:
【中文标题】.text .data 和 main 的分段错误(主要在 .data 部分)【英文标题】:segmentation fault with .text .data and main (main in .data section) 【发布时间】:2016-03-24 20:46:16 【问题描述】:我只是想将myarray[0]
的值加载到eax
:
.text
.data
# define an array of 3 words
array_words: .word 1, 2, 3
.globl main
main:
# assign array_words[0] to eax
mov $0, %edi
lea array_words(,%edi,4), %eax
但是当我运行它时,我不断收到段错误。 有人可以指出我在这里做错了什么吗?
【问题讨论】:
lea
是您代码中的最后一条指令吗?意思是,上面的sn-p是你所有的吗?
编者按:原标题为“将数组的值分配给eax时出现分段错误”。我重新命名以使其成为一个更好的重复目标(链接标题指出问题),以解决其他有这个简单错误的问题,如果你不考虑这个错误可能很难发现。
【参考方案1】:
标签main
似乎在.data
部分中。
这会导致不允许在.data
部分执行代码的系统出现分段错误。 (大多数现代系统映射 .data
具有读 + 写但没有 exec 权限。)
程序代码应该在.text
部分。 (读取+执行)
令人惊讶的是,在 GNU/Linux 系统上,手写 asm 通常会生成可执行文件 .data
,除非您小心避免这种情况,因此这通常不是真正的问题:请参阅 Why data and stack segments are executable? 但将代码放入 @ 987654329@所在的位置可以让一些调试工具更好的工作。
您还需要从 main 调用 ret
或调用 exit
(或进行 _exit
系统调用),这样执行就不会从 main
的末尾下降到接下来的任何字节。见What happens if there is no exit system call in an assembly program?
【讨论】:
这解决了我的问题!从来没有想过这样的事情会导致“段错误”......在我看来,段错误通常表明我在某处有一些未初始化的变量 @OneTwoThree:数据段内存映射有读/写但没有执行权限。因此,C 运行时启动代码在运行call main
指令时会导致段错误。内存页面的额外权限位是一项安全功能(“NX”)。【参考方案2】:
您需要正确终止程序,例如在 Linux x86_64 上通过调用 sys_exit
系统调用:
...
main:
# assign array_words[0] to eax
mov $0, %edi
lea array_words(,%edi,4), %eax
mov $60, %rax # System-call "sys_exit"
mov $0, %rdi # exit code 0
syscall
否则程序将继续执行最后一条指令之后的内存内容,这很可能在所有情况下都是无效指令(甚至是无效的内存位置)。
【讨论】:
或者因为这是main
(不是_start
),它是一个函数,所以你可以简单地ret
。此外,在 x86-64 中,即使要将结果截断为 32 位,也应该使用 64 位地址大小,例如 mov $edi,0
; lea array_words(,%rdi,4), %rax
或 lea array_words(,%rdi,4), %eax
.以上是关于.text .data 和 main 的分段错误(主要在 .data 部分)的主要内容,如果未能解决你的问题,请参考以下文章
我应该使用哪些 gdb 命令来缩小标签“main”中出现分段错误的位置?