“ int 0x80”在汇编代码中是什么意思?

有人能解释一下下面的汇编代码是做什么的吗?

 int 0x80
163518 次浏览

它把控制权传给了中断向量0x80

参见 http://en.wikipedia.org/wiki/Interrupt_vector

在 Linux 上,看一下 这个: 它被用来处理 system_call。当然,在另一个操作系统上,这可能意味着完全不同的东西。

Int 0x80是汇编语言 用于调用 在 x86上的 Linux 系统调用(即, 英特尔兼容的)处理器。

Http://www.linfo.org/int_0x80.html

它告诉 cpu 激活中断向量0x80,这在 Linux 操作系统上是系统调用中断,用于调用系统函数,如文件的 open(),等等。

如前所述,它会导致控制跳转到中断向量0x80。在实践中,这意味着(至少在 Linux 下)调用系统调用; 确切的系统调用和参数由寄存器的内容定义。例如,可以通过将% eax 设置为1后跟“ int 0x80”来调用 exit ()。

int表示中断,数字 0x80表示中断号。 中断将程序流传输给正在处理该中断的任何人,在这种情况下是中断 0x80。 在 Linux 中,0x80 interrupt handler 是内核,用于通过其他程序对内核进行系统调用。

通过检查寄存器 %eax(AT & T 语法,以及 Intel 语法中的 EAX)中的值,可以通知内核程序要进行哪个系统调用。每个系统调用对其他寄存器的使用有不同的要求。例如,%eax中的 1值表示 exit()的系统调用,而 %ebx中的值保存 exit()的状态代码的值。

请记住,0x80 = 80h = 128

You can see 给你 that INT is just one of the many instructions (actually the Assembly Language representation (or should I say 'mnemonic') of it) that exists in the x86 instruction set. You can also find more information about this instruction in Intel's own manual found 给你.

PDF 摘要:

INT n/INTO/INT 3ーー呼叫中断程序

The INT n instruction generates a call to the interrupt or exception 用目标操作数指定的处理程序 operand specifies a vector from 0 to 255, encoded as an 8-bit unsigned INTn 指令是 执行软件生成的对 interrupt handler 的调用。

正如你所看到的,0x80是你问题中的 目标操作数目标操作数。此时,CPU 知道它应该执行一些驻留在内核中的代码,但是什么代码呢?这是由 Linux 的中断向量决定的。

最有用的 DOS 软件中断之一是中断0x21。通过在寄存器中使用不同的参数(主要是 ah 和 al)调用它,您可以访问各种 IO 操作、字符串输出等等。

大多数 Unix 系统和衍生产品不使用软件中断,除了用于进行系统调用的中断0x80。这是通过输入一个 对应于内核函数的32位值进入处理器的 EAX 寄存器然后执行 INT0x80来完成的。

请看一下 interrupt handler 表中其他可用的值:

enter image description here

正如您所看到的,该表指向 CPU 以执行系统调用。您可以找到 Linux 系统调用表 给你

因此,通过将值0x1移动到 EAX 寄存器并在程序中调用 INT 0x80,您可以让进程执行 Kernel 中的代码,这将停止(退出)当前正在运行的进程(在 Linux 上,x86 Intel CPU 上)。

硬件中断不能和软件中断混淆,给你是这方面的一个很好的答案。

这个 也是很好的来源。

Minimal runnable Linux system call example

Linux 为 0x80设置了 interrupt handler,这样它就可以实现系统调用,这是用户界面程序与内核通信的一种方式。

.data
s:
.ascii "hello world\n"
len = . - s
.text
.global _start
_start:


movl $4, %eax   /* write system call number */
movl $1, %ebx   /* stdout */
movl $s, %ecx   /* the data to print */
movl $len, %edx /* length of the buffer */
int $0x80


movl $1, %eax   /* exit system call number */
movl $0, %ebx   /* exit status */
int $0x80

编译并运行:

as -o main.o main.S
ld -o main.out main.o
./main.out

结果: 程序打印到 stdout:

hello world

然后干净利落地离开。

您不能直接从用户端设置自己的中断处理程序,因为您只有 Ring 3和 Linux 阻止您这样做

在 Ubuntu 16.04上测试 GitHub。

更好的选择

int 0x80已经被更好的系统调用替代品所取代: 先是 sysenter,然后是 VDSO。

X86 _ 64有 a new syscall instruction

See also: “ int 0x80”和“ syscall”哪个更好?

最小16位示例

First learn how to create a minimal bootloader OS and run it on QEMU and real hardware as I've explained here: https://stackoverflow.com/a/32483545/895245

现在你可以在16位真实模式下运行:

    movw $handler0, 0x00
mov %cs, 0x02
movw $handler1, 0x04
mov %cs, 0x06
int $0
int $1
hlt
handler0:
/* Do 0. */
iret
handler1:
/* Do 1. */
iret

这样就可以了:

  • Do 0.
  • Do 1.
  • 停止执行

注意处理器如何查找地址 0处的第一个处理程序和地址 4处的第二个处理程序: 这是一个称为 IVT的处理程序表,每个条目有4个字节。

使用 IO 使处理程序可见的最小示例。

最小保护模式示例

Modern operating systems run in the so called protected mode.

在这种模式下,处理有更多的选项,所以它更复杂,但精神是相同的。

关键步骤是使用 LGDT 和 LIDT 指令,它们指向描述处理程序的内存中数据结构(中断描述符表)的地址。

最小的例子

“ int”指令导致中断。

What's an interrupt?

Simple Answer: An interrupt, put simply, is an event that interrupts the CPU, and tells it to run a specific task.

详细回答 :

CPU 有一个存储在内存中的中断服务例程(ISR)表。在实际(16位)模式下,这是存储为 IVT,或 中断 Vector Table。IVT 通常位于 0x0000:0x0000(物理地址 0x00000) ,它是指向 ISR 的一系列段偏移地址。操作系统可以用自己的 ISR 取代原有的 IVT 条目。

(注意: IVT 的大小固定为1024(0x400)字节。)

在受保护(32位)模式下,CPU 使用 IDT。IDT 是一个可变长度的结构,由 描述符(也称为门)组成,它告诉 CPU 有关中断处理程序的信息。这些描述符的结构比 IVT 的简单段偏移量条目要复杂得多,如下所示:

bytes 0, 1: Lower 16 bits of the ISR's address.
bytes 2, 3: A code segment selector (in the GDT/LDT)
byte 4: Zero.
byte 5: A type field consisting of several bitfields.
bit 0:  P (Present): 0 for unused interrupts, 1 for used interrupts.*
bits 1, 2: DPL (Descriptor Privilege Level): The privilege level the descriptor (bytes 2, 3) must have.
bit 3: S (Storage Segment): Is 0 for interrupt and trap gates. Otherwise, is one.
bits 4, 5, 6, 7: GateType:
0101: 32 bit task gate
0110: 16-bit interrupt gate
0111: 16-bit trap gate
1110: 32-bit interrupt gate
1111: 32-bit trap gate
 

* IDT 可能是可变大小的,但是它必须是连续的,也就是说,如果您声明您的 IDT 是从0x00到0x50,那么您必须拥有从0x00到0x50的每个中断。操作系统不一定要使用所有的中断,所以现在位允许 CPU 正确地处理操作系统不打算处理的中断。

When an interrupt occurs (either by an external trigger (e.g. a hardware device) in an IRQ, or by the int instruction from a program), the CPU pushes EFLAGS, then CS, and then EIP. (These are automatically restored by iret, the interrupt return instruction.) The OS usually stores more information about the state of the machine, handles the interrupt, restores the machine state, and continues on.

在许多 * NIX 操作系统(包括 Linux)中,系统调用是基于中断的。程序将参数放入寄存器(EAX、 EBX、 ECX、 EDX 等)中的系统调用呼叫中断0x80。内核已经将 IDT 设置为在0x80上包含一个 interrupt handler,当它接收到中断0x80时会调用这个函数。然后,内核读取参数并相应地调用内核函数。它可能在 EAX/EBX 存储退货。系统调用已经在很大程度上被 sysentersysexit(或 AMD 上的 syscallsysret)指令所取代,它们允许更快地进入环0。

这个中断在不同的操作系统中可能有不同的含义。一定要检查它的文档。

Int 只是一个中断 也就是说,处理器将暂停当前的执行。

0x80只是一个系统调用或内核调用。 即执行系统功能。

具体来说,0x80表示 rt _ sigtimedwait/init _ module/start _ sys,它因体系结构而异。

详情请参阅 Https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md