我只是想打印出"你好!"在屏幕上,但我遇到了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

谁能给我解释一下为什么第一个代码工作正常,而第二个代码出错.

推荐答案

正如迈克尔在他的 comments 中所说,问题来自这hello_world: db "Hello World!",10人.

要理解为什么会发生这种情况,您首先必须知道程序在内存中是如何表示的.维基百科的Object File页可能是更详细地理解这一点的一个良好开端.但为简短起见,在本例中,我们对两种段类型感兴趣:数据段和代码段.

程序的The code segment(或文本段)包含机器为运行程序而必须执行的指令.通常,当加载到主内存中时(当您执行程序时),此代码段变为只读.这主要是出于安全原因,你可以阅读更多关于这here.

一个程序的The data segment%包含初始化的静态变量.字符串"Hello World!"在您的程序中就是这样一个变量的很好的例子.

因此,要编写一个"具有良好实践"的组装示例,您应该利用这两个不同的段,Hello World示例可能会找到here个.

现在,当程序执行时, idea 是CPU将加载程序计数器(PC)所指向的操作,执行它,并递增PC以使其指向下一条指令.这是因为CPU知道指令的大小,因此可以正确地递增PC.在您的代码中,这一切都很顺利,CPU将正确执行,直到达到hello_world: db "Hello World!",10.在这里,接下来的10个字节被设置为"Hello World!".因此,当PC将递增时,它将指向此字符串中的某个位置.也许一开始它会遇到字符串中的有效指令,但在某个时刻,它会遇到地址指向未分配给此程序的内存区的内存指令.try 取消对此地址的引用时,将发出段错误.如果您想确切地知道正在使用什么指令和地址,Peter Cordes的 comments 将为您提供一个很好的开始.

Linux相关问答推荐

如何限制SLURM中并行执行的程序数量

Flutter 构建错误:';DART:JS_interop';在此平台上不可用

如何判断程序是在终端上运行还是在后台运行?

如何更改文件的上次访问/修改/更改日期?

如何从 2 个文件中获取内容并使用 shell 脚本将该内容附加到新文件中

查找在特定日期从特定机器登录的所有用户

在 Linux 中 Select 多个同名的可执行文件

CHMOD 755 与 750 权限集之间的差异

如何找出哪个进程正在消耗等待 CPU(即 I/O 阻塞)

在 bash 中检测公共 IP 地址的方法

C.UTF-8 和 en_US.UTF-8 语言环境有什么区别?

Linux命令删除.git文件夹以外的所有文件?

如何准确复制文件夹

NGINX:connect() 到 unix:/var/run/php7.0-fpm.sock 失败(2:没有这样的文件或目录)

Linux上C中的标准输出线程安全?

Linux 上真的没有异步块 I/O 吗?

将所有文件扩展名转换为小写

构建窗口管理器

学习内核编程

未找到版本CXXABI_1.3.8(...要求)