汇编语言学习_2_正确的退出方式
第二节
正确的退出方式
背景知识
在 Lesson 1 中成功学习了如何执行系统调用之后,现在需要学习内核中最重要的系统调用之一 sys_exit
。
请注意我们的“Hello, world!”
之后的情况。程序运行我们遇到了Segmentation fault
(段错误)?好吧,计算机程序可以被认为是一长串指令,它们被加载到内存中并分成多个部分(或段)。这个通用内存池在所有程序之间共享,可用于存储变量、指令、其他程序或任何真正的东西。每个段都有一个地址,以便以后可以找到存储在该段中的信息。
要执行加载到内存中的程序,我们使用全局标签 _start
来告诉操作系统在内存中的什么位置可以找到并执行我们的程序。然后,按照程序逻辑顺序访问内存,程序逻辑决定要访问的下一个地址。内核跳转到内存中的那个地址并执行它。
告诉操作系统应该在哪里开始执行,在哪里停止,这一点很重要。在第一节中,我们没有告诉内核在哪里停止执行。因此,在我们调用 sys_write
之后,程序继续顺序执行内存中的下一个地址,这可能是任何地址。我们不知道内核试图执行什么,但最终其阻塞,终止进程并报错 “Segmentation fault
” 。在所有程序结束时调用 sys_exit
将意味着内核确切知道何时终止进程并将内存归还到通用池,从而避免错误。
写程序
sys_exit
有一个简单的函数定义。在 Linux 系统调用表中,它被分配为 OPCODE 1
,并通过 EBX
传递一个参数。
为了执行这个功能,我们需要做的是:
EBX
置为0
,表示没有错误EBX
置为1
,来调用sys_exit
- 使用
INT 80h
请求中断
然后我们再次编译、链接并运行它。
注意:只有在每节课中添加的新代码才会被注释。
; Hello World Program - asmtutor.com
; 文件名:helloworld.asm
; 编译:nasm -f elf helloworld.asm
; 链接(64位系统需要 elf_i386 选项):ld -m elf_i386 helloworld.o -o helloworld
; 运行:./helloworld
SECTION .data
msg db 'Hello World!', 0Ah
SECTION .text
global _start
_start:
mov edx, 13
mov ecx, msg
mov ebx, 1
mov eax, 4
int 80h
mov ebx, 0 ; 返回状态0来表示'No Errors'
mov eax, 1 ; 调用 SYS_EXIT
int 80h
~$ nasm -f elf helloworld.asm
~$ ld -m elf_i386 helloworld.o -o helloworld
~$ ./helloworld
Hello World!