正确的程序退出
在第1课中成功地学习了如何执行系统调用之后,我们现在需要了解内核中最重要的系统调用之一,sys_exit。
注意在我们的“Hello, world!”'程序运行,我们有一个分割错误?好吧,计算机程序可以被认为是一长串指令,被载入内存并被分成若干段(或若干段)。这个通用的内存池在所有程序之间共享,可以用来存储变量、指令、其他程序或其他任何东西。每个段都有一个地址,以便以后可以找到存储在该段中的信息。
要执行加载在内存中的程序,我们使用全局标号_start:来告诉操作系统可以在内存中找到并执行程序的位置。然后按照程序逻辑顺序访问内存,程序逻辑确定了下一个要访问的地址。内核跳转到内存中的那个地址并执行它。
告诉操作系统应该在哪里开始执行,在哪里停止执行,这一点很重要。在第1课中,我们没有告诉内核在哪里停止执行。因此,在我们调用sys_write之后,程序继续在内存中依次执行下一个地址,这个地址可以是任何地址。我们不知道内核试图执行什么,但它导致阻塞和终止进程,而不是给我们留下'分割错误'的错误消息。在所有程序的末尾调用sys_exit将意味着内核确切地知道何时终止进程并将内存返回给常规池,从而避免出现错误。
写我们的程序
Sys_exit有一个简单的函数定义。在Linux系统调用表中,它被分配为OPCODE 1,并通过EBX传递一个参数。
为了执行这个函数,我们需要做的就是:
使用0加载EBX将0传递给函数,表示“零错误”。
用1加载EAX来调用sys_exit。
然后在libc上使用INT 80h请求一个中断。
然后编译、链接并再次运行它。
注意:只有在每个课程中添加的新代码才会被注释。