有人可以解释以下汇编代码的作用吗?
int 0x80
有人可以解释以下汇编代码的作用吗?
int 0x80
Answers:
它将控制权传递给中断向量0x80
看到 http://en.wikipedia.org/wiki/Interrupt_vector
在Linux上,看看这个:它是用来处理system_call
。当然,在另一个OS上,这可能意味着完全不同。
int 0x80
视为call
内核中函数的一种特殊类型(由选择eax
)。
请记住,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上)。
硬件中断不得与软件中断混淆。在这方面,这是一个很好的答案。
这也是很好的来源。
int 0x80
i386的Linux系统调用ABI极其类似DOS的int 0x21
ABI。将呼叫号码放入寄存器中(AH用于DOS,EAX用于Linux),并将其他参数放入其他寄存器中,然后运行软件中断指令。主要区别在于系统调用允许您执行的操作(直接在DOS中访问硬件,而不能在Linux中访问硬件),而不是如何调用它们。
/usr/include/x86_64-linux-gnu/asm/unistd_64.h
最低限度可运行的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
已经被用于进行系统调用的更好的替代方法所取代:首先是sysenter
VDSO。
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指令,它们指向描述处理程序的内存中数据结构(中断描述符表)的地址。
int 0x80是汇编语言指令,用于在x86(即Intel兼容)处理器上的Linux中调用系统调用。
“ 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中存储退货。系统调用在很大程度上被换成了sysenter
和sysexit
(或syscall
和sysret
上AMD)指令,允许更快的进入0环。
在不同的操作系统中,此中断可能具有不同的含义。确保检查其文档。
eax
用于系统调用号码。 asm.sourceforge.net/intro/hello.html
它告诉CPU激活中断向量0x80,在Linux OS上它是系统调用中断,用于调用诸如open()
文件等的系统功能。
int只是中断,也就是说,处理器将保留其当前执行。
0x80只是系统调用或内核调用。即将执行系统功能。
具体来说,0x80代表rt_sigtimedwait / init_module / restart_sys,它随体系结构而变化。
有关更多详细信息,请参阅 https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md