有人能解释一下下面的汇编代码的作用吗?

 int 0x80  
有帮助吗?

解决方案

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

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

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

其他提示

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

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

请记住,0x80 = 80h = 128

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

总结PDF:

  

INT n / INTO / INT 3&#8212;调用中断程序

     

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

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

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

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

请看看中断处理程序表中其他可用值的显示位置:

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

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

硬件中断不得与软件中断混淆。 这里非常这方面的答案很好。

这个也是很好的来源。

你可以在行动中看到 int 80h 此处

  

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

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

最小可运行 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

结果:程序打印到标准输出:

hello world

并干净地退出。

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

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

更好的选择

int 0x80 已被更好的系统调用替代方案所取代:第一的 sysenter, ,然后是VDSO。

x86_64 有 一个新的 syscall 操作说明.

也可以看看: “int 0x80”或“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 个字节。

执行一些 IO 的最小示例 使处理程序可见。

最小保护模式示例

现代操作系统在所谓的保护模式下运行。

该模式下的操控有更多的选择,因此也更复杂,但精神是一样的。

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

最小的例子

“int”指令导致中断。

什么是中断?

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

详细解答

CPU有一个存储在内存中的中断服务程序(或ISR)表。在Real(16位)模式下,它存储为 IVT ,或 I nterrupt V ector T 能够。 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正确处理操作系统无意处理的中断。

当发生中断时(通过IRQ中的外部触发器(例如硬件设备)或程序中的 int 指令),CPU按下EFLAGS,然后按CS,然后按EIP。 (这些由 iret ,中断返回指令自动恢复。)OS通常存储有关机器状态的更多信息,处理中断,恢复机器状态,并继续。

在许多* NIX操作系统(包括Linux)中,系统调用都是基于中断的。程序将参数放入寄存器(EAX,EBX,ECX,EDX等)中的系统调用,并调用中断0x80。内核已经将IDT设置为在0x80上包含一个中断处理程序,当它接收到中断0x80时会被调用。然后内核读取参数并相应地调用内核函数。它可以在EAX / EBX中存储一个回报。系统调用已基本上被 sysenter sysexit (或AMD上的 syscall sysret )指令所取代,允许更快地进入环0。

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top