小智 111

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

通过检查寄存器中的值%eax(气体语法和Intel语法中的EAX),内核会收到程序想要进行哪个系统调用的通知.每个系统调用对其他寄存器的使用有不同的要求.例如,值1in %eax表示系统调用exit(),而值in %ebx保存状态代码的值exit().

  • @mfaani 是的,内核是一个程序。 (2认同)

jld*_*ont 57

它将控制传递给中断向量0x80

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

在Linux上,看看这个:它曾被用来处理system_call.当然在另一个OS上,这可能意味着完全不同的东西.

  • 通过缩短长篇故事的指示意味着**DO IT**用于指导之前. (5认同)
  • @YudaPrawira:您应该将较早的指令视为在寄存器中设置 args,并将 `int 0x80` 视为对内核中函数的一种特殊 `call`(由 `eax` 选择)。 (5认同)
  • 你为什么说“被使用了?” 不再用了吗? (2认同)

Kor*_*gay 38

请记住,0x80 = 80h = 128

你可以在这里看到INT只是x86指令集中存在的许多指令之一(实际上是汇编语言表示(或者我应该说'助记符')).您还可以在此处的英特尔自己的手册中找到有关此说明的更多信息.

从PDF中总结:

INT n/INTO/INT 3 - 调用中断过程

INT n指令生成对使用目标操作数指定的中断或异常处理程序的调用.目标操作数指定0到255之间的向量,编码为8位无符号中间值.INT n指令是执行软件生成的中断处理程序调用的通用助记符.

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

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

大多数Unix系统和衍生产品不使用软件中断,中断0x80除外,用于进行系统调用.这是通过将对应于内核函数32位值输入处理器的EAX寄存器然后执行INT 0x80来实现的.

请看一下这里,其中显示了中断处理程序表中的其他可用值:

在此输入图像描述

如您所见,该表指向CPU执行系统调用.您可以在此处找到Linux系统调用表.

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

不得将硬件中断与软件中断混淆.在这方面,是一个非常好的答案.

也是很好的来源.

你可以在这里看到int 80h.

  • Linux系统调用表链接已损坏= \ (2认同)
  • *大多数 Unix 系统和衍生系统不使用软件中断(int 0x80 除外)* 似乎是一种奇怪的表达方式。‘int 0x80’ i386 Linux 系统调用 ABI 与 DOS ‘int 0x21’ ABI 极其相似。将调用号放入寄存器(DOS 中为 AH,Linux 中为 EAX),并将其他参数放入其他寄存器中,然后运行软件中断指令。主要区别在于系统调用允许您执行哪些操作(在 DOS 中直接访问硬件,而不是在 Linux 中),而不在于如何调用它们。 (2认同)

Tom*_*Tom 9

int 0x80是汇编语言指令,用于在x86(即Intel兼容)处理器上的Linux中调用系统调用.

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


Cir*_*四事件 8

最小的可运行Linux系统调用示例

Linux设置了中断处理程序,0x80以便它实现系统调用,这是用户程序与内核通信的一种方式.

.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
Run Code Online (Sandbox Code Playgroud)

编译并运行:

as -o main.o main.S
ld -o main.out main.o
./main.out
Run Code Online (Sandbox Code Playgroud)

结果:程序打印到stdout:

hello world
Run Code Online (Sandbox Code Playgroud)

干净利落地退出.

您不能直接从用户区设置自己的中断处理程序,因为您只有响铃3而Linux阻止您这样做.

GitHub上游.在Ubuntu 16.04上测试过.

更好的选择

int 0x80已经被更好的系统调用替代方案所取代:首先是sysenterVDSO.

x86_64有一条新syscall指令.

另请参阅:什么是更好的"int 0x80"或"系统调用"?

最小的16位示例

首先学习如何创建一个最小的引导加载程序操作系统并在QEMU和真实硬件上运行它,如我在此解释的那样: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
Run Code Online (Sandbox Code Playgroud)

这将按顺序执行:

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

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

做一些IO以使处理程序可见的最小示例.

最小保护模式示例

现代操作系统以所谓的保护模式运行.

处理在这种模式下有更多的选择,所以它更复杂,但精神是一样的.

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

最小的例子


Adr*_*ang 6

“int”指令引起中断。

什么是中断?

简单回答:简单来说,中断是一个中断 CPU 并告诉它运行特定任务的事件。

详细解答

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

(注意: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
 
Run Code Online (Sandbox Code Playgroud)

*IDT 的大小可以是可变的,但它必须是连续的,即,如果您将 IDT 声明为从 0x00 到 0x50,则必须拥有从 0x00 到 0x50 的每个中断。操作系统不一定使用所有中断,因此 Present 位允许 CPU 正确处理操作系统不打算处理的中断。

当中断发生时(无论是通过 IRQ 中的外部触发(例如硬件设备),还是通过int程序的指令),CPU 会推送 EFLAGS,然后推送 CS,最后推送 EIP。(这些由iret中断返回指令自动恢复。)操作系统通常存储有关机器状态的更多信息,处理中断,恢复机器状态,然后继续。

在许多 *NIX 操作系统(包括 Linux)中,系统调用是基于中断的。程序将系统调用的参数放入寄存器(EAX、EBX、ECX、EDX 等)中,并调用中断 0x80。内核已经将 IDT 设置为包含 0x80 上的中断处理程序,当收到中断 0x80 时将调用该中断处理程序。然后内核读取参数并相应地调用内核函数。它可以将返回存储在 EAX/EBX 中。系统调用很大程度上已被sysenterand sysexit(或AMD上的syscalland sysret)指令所取代,这样可以更快地进入ring 0。

该中断在不同的操作系统中可能具有不同的含义。请务必检查其文档。