汇编语言学习_2_正确的退出方式

第二节

正确的退出方式

翻译自:https://asmtutor.com/

背景知识

在 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!
posted @ 2023-02-27 21:24  charain_li  阅读(215)  评论(0编辑  收藏  举报