本文介绍了使用来自_start的32位int 0x80 Linux系统调用来解释此x86 Hello World是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

section .text
    global _start       ;must be declared for using gcc
_start:                     ;tell linker entry point
    mov edx, len    ;message length
    mov ecx, msg    ;message to write
    mov ebx, 1      ;file descriptor (stdout)
    mov eax, 4      ;system call number (sys_write)
    int 0x80        ;call kernel
    mov eax, 1      ;system call number (sys_exit)
    int 0x80        ;call kernel

section .data

msg db  'Hello, world!',0xa ;our dear string
len equ $ - msg         ;length of our dear string

这是一个基本的32位x86 Linux汇编代码,用于打印"Hello,World!".在屏幕上(标准输出).使用

This is a basic 32-bit x86 Linux assembly code to print "Hello, World!" on the screen (standard output). Build + run it with

nasm -felf -g -Fdwarf hello.asm
gcc -g -m32 -nostdlib -static -o hello hello.o
./hello

(编者注:或 gdb ./hello 对其进行调试/单步执行.这就是为什么我们使用 nasm -g -Fdwarf gcc -g.或在GDB中使用 layout reg 进行不依赖调试符号的反汇编和注册视图,请参见https://stackoverflow.com/tags/x86/info )

(Editor's note: or gdb ./hello to debug / single-step it. That's why we used nasm -g -Fdwarf and gcc -g. Or use layout reg inside GDB for disassembly+register view that doesn't depend on debug symbols. See the bottom of https://stackoverflow.com/tags/x86/info)

现在,我想问一下这段代码在后台如何工作.就像所有这些说明都需要什么

Now I want to ask about how is this code working behind the scenes. Like what is the need for all these instructions

_start:                     ;tell linker entry point
        mov edx, len    ;message length
        mov ecx, msg    ;message to write
        mov ebx, 1      ;file descriptor (stdout)
        mov eax, 4      ;system call number (sys_write)
        int 0x80        ;call kernel
        mov eax, 1      ;system call number (sys_exit)
        int 0x80        ;call kernel

仅打印"Hello,World!"和声明

just to print "Hello, World!" and the statement

_start:

以上!是主要功能吗?

和声明

int 0x80

为什么要使用它?你们能给我深入介绍一下该程序的基本原理吗.

why is it used at all? Can you guys give me a deep explaination of the basic working of this program.

推荐答案

在机器代码中,没有任何功能.至少,处理器对功能一无所知.程序员可以根据自己的喜好来构造其代码. _start 是称为 symbol 的名称,它只是程序中某个位置的名称.符号用于表示您不知道其地址的位置.它们在链接过程中已解决.符号 _start 用作进入点(请参见此答案),这是操作系统跳转到启动程序的位置.除非您通过其他方式指定入口点,否则每个程序都必须包含 _start .程序使用的其他符号是 msg ,链接器将其解析为字符串 Hello,world!所在的地址和 len msg 的长度.

In machine code, there are no functions. At least, the processor knows nothing about functions. The programmer can structure his code as he likes. _start is something called a symbol which is just a name for a location in your program. Symbols are used to refer to locations whose address you don't know yet. They are resolved during linking. The symbol _start is used as the entry point (cf. this answer) which is where the operating system jumps to start your program. Unless you specify the entry point by some other way, every program must contain _start. The other symbols your program uses are msg, which is resolved by the linker to the address where the string Hello, world! resides and len which is the length of msg.

程序的其余部分执行以下操作:

The rest of the program does the following things:

  1. 设置系统调用 write(1,msg,len)的寄存器. write 具有系统调用号4,该系统调用号存储在 eax 中,以使操作系统知道您想要系统调用4.此系统调用将数据写入文件.提供的文件描述符号为1,代表标准输出.
  2. 使用 int $ 0x80 执行系统调用.该指令将中断您的程序,操作系统将接管该程序并执行其编号存储在 eax 中的功能.就像调用OS内核的函数调用一样.调用约定与其他函数不同,在寄存器中传递了args.
  3. 设置系统调用 _exit(?)的寄存器.它的系统呼叫号码是1,该号码进入 eax .可悲的是,该代码忘记为 _exit 设置参数,该参数应为0表示成功.取而代之的是使用之前 ebx 中的内容,似乎是1.
  4. 使用 int $ 0x80 执行系统调用.因为 _exit 结束了程序,所以它不返回.您的程序到此结束.
  1. Set up the registers for the system call write(1, msg, len). write has system call number 4 which is stored in eax to let the operating system know you want system call 4. This system call writes data to a file. The file descriptor number supplied is 1 which stands for standard output.
  2. Perform a system call using int $0x80. This instruction interrupts your program, the operating system picks this up and performs the function whose number is stored in eax. It's like a function call that calls into the OS kernel. The calling convention is different from other functions, with args passed in registers.
  3. Set up the registers for the system call _exit(?). Its system call number is 1 which goes into eax. Sadly, the code forgets to set the argument for _exit, which should be 0 to indicate success. Instead, whatever was in ebx before is used instead, which seems to be 1.
  4. Perform a system call using int $0x80. Because _exit ends the program, it does not return. Your program ends here.

指令 db 告诉汇编器将以下数据放入程序中当前所在的位置.这会将字符串 Hello,world!后面跟换行符放入程序中,因此我们可以告诉 write 系统调用编写该字符串.

The directive db tells the assembler to place the following data into the program where we currently are. This places the string Hello, world! followed by a newline into the program so we can tell the write system call to write that string.

len equ $-msg 告诉汇编程序,而不是 len $ (我们目前所在的位置)和 msg 之间的区别.定义了它,以便我们可以将要打印的文本传递给 write 多久.

The line len equ $ - msg tells the assembler than len is the difference between $ (where we currently are) and msg. This is defined so we can pass to write how long the text we want to print is.

程序中分号(; )之后的所有内容都是一个注释,被汇编程序忽略.

Everything after a semicolon (;) in the program is a comment ignored by the assembler.

这篇关于使用来自_start的32位int 0x80 Linux系统调用来解释此x86 Hello World是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 11:21