linux x86_64程序集中的分段故障:系统调用问题[重复]

wixjitnu  于 2023-11-17  发布在  Linux
关注(0)|答案(1)|浏览(107)

此问题在此处已有答案

Segmentation fault when using DB (define byte) inside a function(1个答案)
3天前关闭。
我只是想在屏幕上打印“你好!”,但我遇到了一个SegmentationFault错误。我有两个程序,一个工作正常,另一个出错。
运行良好的代码:

global  _start
    section .text

_start:

    
    mov rdi,1           
    mov rsi,hello_world     
    mov rdx,13  
    mov rax,1           
    syscall

    ; exit(result)
    mov rax,60          
    mov rdi,0           
    syscall

hello_world:    db "Hello World!",10

字符串
给出SegmentationFault的代码:

global  _start
    section .text

_start:

    
    mov rdi,1           
    mov rsi,hello_world     
    mov rdx,13  
    mov rax,1           
    syscall

hello_world:    db "Hello World!",10

    ; exit(result)
    mov rax,60          
    mov rdi,0           
    syscall


第二个代码的输出应该是:Hello world!
但它给出:Segmentation Fault
有人能解释我为什么第一个代码工作正常,第二个给错误。

y1aodyip

y1aodyip1#

正如迈克尔在他的评论中所说,问题来自这个hello_world: db "Hello World!",10
要理解为什么会发生这种情况,你首先必须知道程序在内存中是如何表示的。Wikipedia的Object File页面可能是一个很好的开始,可以更详细地理解这一点。但在这个例子中,我们只对两种段类型感兴趣:数据段和代码段。

程序的代码段(或文本段)包含机器运行程序所必须执行的指令。通常此代码段在加载到主存时(当您执行程序时)变为只读。这主要是出于安全考虑,您可以阅读更多关于此here的信息。
程序的数据段包含初始化的静态变量,你程序中的字符串“Hello World!”就是一个很好的例子。

因此,要编写一个“具有良好实践”的程序集示例,您应该使用这两个不同的部分,一个Hello World示例可能是here
现在,当一个程序被执行时,我们的想法是CPU将加载程序计数器(PC)指向的操作,执行它,并递增PC以使其指向下一条指令。这是因为CPU知道指令的大小,因此可以正确地递增PC。在你的代码中,这一切都很顺利,CPU将正确地执行,直到它到达hello_world: db "Hello World!",10。在那里,接下来的10个字节被设置为“Hello World!“。所以当PC将递增时,它将指向这个字符串中的某个地方。也许一开始它会遇到字符串中的有效指令,但是在某些时候,它会遇到一个内存指令,该指令的地址指向一个没有分配给这个程序的内存区域。如果你想确切地知道正在使用什么指令和地址,Peter Cordes的评论给了你一个很好的开始。

相关问题