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


Answers:


69

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

看到 http://en.wikipedia.org/wiki/Interrupt_vector

在Linux上,看看这个:它是用来处理system_call。当然,在另一个OS上,这可能意味着完全不同。


5
通过缩短长的故事,这就是指令意味着DO IT的指令以前。
Yuda Prawira 2011年

2
@YudaPrawira:您应该将先前的说明视为在寄存器中设置args,以及将其int 0x80视为call内核中函数的一种特殊类型(由选择eax)。
彼得·科德斯

为什么说“曾经使用过”?不再使用了吗?
西甲

127

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

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


47

请记住,0x80= 80h=128

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

从PDF总结:

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

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

如您所见,0x80目标操作数。此时,CPU知道它应该执行内核中的某些代码,但是什么代码呢?这取决于Linux中的中断向量。

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

除了用于进行系统调用的中断0x80之外,大多数Unix系统及其派生工具都不使用软件中断。这是通过将与内核功能相对应32位值输入到处理器的EAX寄存器中,然后执行INT 0x80来实现的。

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

在此处输入图片说明

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

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

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

也是很好的来源。


4
Linux系统调用表链接已损坏= \
Miguel Angelo

1
大多数Unix系统和派生类都不使用软件中断(int 0x80除外)似乎是一种怪异的放置方式。在int 0x80i386的Linux系统调用ABI极其类似DOS的int 0x21ABI。将呼叫号码放入寄存器中(AH用于DOS,EAX用于Linux),并将其他参数放入其他寄存器中,然后运行软件中断指令。主要区别在于系统调用允许您执行的操作(直接在DOS中访问硬件,而不能在Linux中访问硬件),而不是如何调用它们。
彼得·科德斯

这是一个完整的syscall表链接。syscalls.kernelgrok.com只需将其展开以在顶部显示所有调用即可。
ollien

使用64位linux时,您可以在/usr/include/x86_64-linux-gnu/asm/unistd_64.h
ton

11

最低限度可运行的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

并干净地退出。

您不能直接从userland设置自己的中断处理程序,因为您只有环3,而Linux禁止这样做

GitHub上游。在Ubuntu 16.04上测试。

更好的选择

int 0x80已经被用于进行系统调用的更好的替代方法所取代:首先是sysenterVDSO。

x86_64有一条新syscall指令

另请参见:更好的“ int 0x80”或“ syscall”是什么?

最小的16位示例

首先,请学习如何创建最小的Bootloader操作系统,并在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:停止执行

请注意处理器如何在address查找第一个处理程序0,并在以下位置查找第二个处理程序4:这是一个称为IVT的处理程序表,每个条目都有4个字节。

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

最小保护模式示例

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

在此模式下,处理具有更多选项,因此更为复杂,但实质是相同的。

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

最小的例子



4

“ int”指令导致中断。

什么是打扰?

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

详细答案

CPU在内存中存储了一张中断服务程序(ISR)表。在真实的(16位)的模式下,该被存储为IVT,或nterrupt V厄克托Ť能。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。操作系统并不一定要全部使用它们,因此Present位允许CPU正确处理操作系统不打算处理的中断。

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

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

在不同的操作系统中,此中断可能具有不同的含义。确保检查其文档。


有趣的事实:FreeBSD的i386系统调用ABI在用户空间堆栈上传递了args。仅eax用于系统调用号码。 asm.sourceforge.net/intro/hello.html
彼得·科德斯

2

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


1

它告诉CPU激活中断向量0x80,在Linux OS上它是系统调用中断,用于调用诸如open()文件等的系统功能。


9
严格来说,它不告诉内核...它告诉CPU,它在IDT中查找处理程序,最后是指向某些内核代码的指针。
asveikau

真正。我想更好的措词是告诉CPU激活向量,并且向量(作为内核的一部分)调用函数。
琥珀色

最终完成该操作,然后依次完成该操作,然后执行此操作,然后混淆。:/琥珀色的答案是可以理解的。就是这样
阿夫扎尔·艾哈迈德·泽山

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.