此问题在此处已有答案:
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
有人能解释我为什么第一个代码工作正常,第二个给错误。
1条答案
按热度按时间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的评论给了你一个很好的开始。