小智 111
int表示中断,数字0x80是中断号.中断将程序流传送给处理该中断的任何人,0x80在这种情况下是中断.在Linux中,0x80中断处理程序是内核,用于通过其他程序对内核进行系统调用.
通过检查寄存器中的值%eax(气体语法和Intel语法中的EAX),内核会收到程序想要进行哪个系统调用的通知.每个系统调用对其他寄存器的使用有不同的要求.例如,值1in %eax表示系统调用exit(),而值in %ebx保存状态代码的值exit().
jld*_*ont 57
它将控制传递给中断向量0x80
请参见http://en.wikipedia.org/wiki/Interrupt_vector
在Linux上,看看这个:它曾被用来处理system_call.当然在另一个OS上,这可能意味着完全不同的东西.
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系统调用示例
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
编译并运行:
as -o main.o main.S
ld -o main.out main.o
./main.out
结果:程序打印到stdout:
hello world
干净利落地退出.
您不能直接从用户区设置自己的中断处理程序,因为您只有响铃3而Linux阻止您这样做.
GitHub上游.在Ubuntu 16.04上测试过.
更好的选择
int 0x80已经被更好的系统调用替代方案所取代:首先是sysenterVDSO.
x86_64有一条新syscall指令.
最小的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
这将按顺序执行:
Do 0.Do 1.hlt:停止执行注意处理器如何在地址处查找第一个处理程序,0第二个处理程序在4:它是一个名为IVT的处理程序表,每个条目有4个字节.
最小保护模式示例
现代操作系统以所谓的保护模式运行.
处理在这种模式下有更多的选择,所以它更复杂,但精神是一样的.
关键步骤是使用LGDT和LIDT指令,这些指令指向描述处理程序的内存数据结构(中断描述符表)的地址.
“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
 
*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。
该中断在不同的操作系统中可能具有不同的含义。请务必检查其文档。
| 归档时间: | 
 | 
| 查看次数: | 104990 次 | 
| 最近记录: |