x86_64 汇编中的分段错误:系统调用问题[重复]

问题描述 投票:0回答:1

我只是想打印“Hello!”在屏幕上,但我遇到了 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

有人可以解释一下为什么第一个代码工作正常而第二个代码出错。

linux assembly segmentation-fault x86-64 nasm
1个回答
-1
投票

正如 Michael 在评论中所说,问题就来自于此

hello_world:    db "Hello World!",10

要理解为什么会发生这种情况,您首先必须知道程序在内存中是如何表示的。维基百科的对象文件页面可能是一个很好的开始,可以更详细地了解这一点。但简单来说,在这个例子中我们感兴趣的是 2 种段类型:数据段和代码段。

程序的代码段(或文本段)包含机器运行程序必须执行的指令。通常,当加载到主内存中时(当您执行程序时),此代码段将变为只读。这主要是出于安全原因,您可以在

here阅读更多相关信息。 程序的数据段

包含已初始化的静态变量。字符串“Hello World!”在你的程序中就是这样一个变量的一个很好的例子。

因此,要编写“具有良好实践”的汇编示例,您应该利用这两个不同的段,可以在此处

找到 Hello World 示例。

现在,当执行程序时,CPU将加载程序计数器(PC)指向的操作,执行它,并递增PC以使其指向下一条指令。这是可行的,因为 CPU 知道指令的大小,因此可以正确地递增 PC。在您的代码中,这一切都很顺利,CPU 将正确执行,直到到达 hello_world: db "Hello World!",10

。接下来的 10 个字节被设置为“Hello World!”。因此,当 PC 递增时,它将指向该字符串中的某个位置。由于指向的区域不是有效指令,因此会发出段错误。

© www.soinside.com 2019 - 2024. All rights reserved.