“int 0x80”在汇编代码中的含义是什么?

时间:2009-11-30 02:17:58

标签: assembly x86

有人可以解释以下汇编代码的作用吗?

 int 0x80  

9 个答案:

答案 0 :(得分:105)

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

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

答案 1 :(得分:53)

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

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

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

答案 2 :(得分:35)

请记住,0x80 = 80h = 128

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

总结PDF:

  

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

     

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

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

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

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

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

enter image description here

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

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

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

This也是很好的来源。

您可以在行动here中看到 int 80h

答案 3 :(得分:9)

  

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

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

答案 4 :(得分:7)

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

然后干净利落地退出。

您无法直接从用户区设置自己的中断处理程序,因为您只有ring 3 and Linux prevents you from doing so

GitHub upstream。在Ubuntu 16.04上测试过。

更好的替代方案

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

x86_64有a new syscall instruction

另请参阅:What is better "int 0x80" or "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个字节。

Minimal example that does some IO让处理程序可见。

最低保护模式示例

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

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

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

Minimal example

答案 5 :(得分:3)

“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中存储一个回报。系统调用已基本上由sysentersysexit(或AMD上的syscallsysret)指令取代,这样可以更快地进入第0环。

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

答案 6 :(得分:2)

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

答案 7 :(得分:1)

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

答案 8 :(得分:1)

int只是中断 即处理器将保留其当前执行。

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

具体来说,0x80代表rt_sigtimedwait / init_module / restart_sys,它随体系结构的不同而不同。

有关更多详细信息,请参阅 https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md