在汇编代码中“int 0x80”是什么意思?
有人可以解释下面的汇编代码是做什么的?
int 0x80
它通过控制中断vector0x80
见http://en.wikipedia.org/wiki/Interrupt_vector
在Linux上,看看这个 :它被用来处理system_call
。 当然在另一个操作系统上这可能意味着完全不同的东西
int表示中断,数字0x80是中断号。 中断将程序stream传送给正在处理该中断的人,在这种情况下,中断为0x80。 在Linux中,0x80中断处理程序是内核,用于由其他程序对内核进行系统调用。
通过检查寄存器%eax(gas语法和Intel语法中的EAX)中的值,通知内核程序想要进行的系统调用。 每个系统调用对使用其他寄存器有不同的要求。 例如,%eax中的值1表示系统调用exit()
,而%ebx中的值保存exit()
的状态码值。
请记住,0x80 = 80h = 128
你可以在这里看到, INT只是存在于x86指令集中的许多指令(实际上是汇编语言表示(或者应该说是“助记符”))之一。 您也可以在这里find的英特尔自己的手册中find关于此指令的更多信息。
从PDF中总结:
INT n / INTO / INT 3 – 调用中断程序
INT n指令生成对目标操作数指定的中断或exception处理程序的调用。 目标操作数指定一个从0到255的向量,编码为8位无符号中间值。 INT n指令是执行软件生成的中断处理程序调用的通用助记符。
正如你所看到的, 0x80是你问题中的目标操作数 。 在这一点上,CPU知道它应该执行驻留在内核中的一些代码,但是代码是什么? 这是由Linux中的中断向量决定的。
最有用的DOS软件中断之一是中断0x21。 通过调用寄存器中的不同参数(主要是ah和al),可以访问各种IO操作,string输出等。
大多数Unix系统和衍生产品不使用软件中断,除了中断0x80,用于进行系统调用。 这是通过在处理器的EAX寄存器中input对应于内核函数的32位值 ,然后执行INT 0x80来实现的。
看看这个请在中断处理程序表中显示其他可用的值:
正如你所看到的,表格指出了CPU执行一个系统调用。 你可以在这里findLinux系统调用表。
因此,通过将值0x1移到EAX寄存器并在程序中调用INT 0x80,可以使进程执行内核中的代码,这将停止(退出)当前运行进程(在Linux,x86 Intel CPU上)。
硬件中断不能与软件中断混淆。 在这方面, 这是一个非常好的答案。
这也是很好的来源。
你可以在这里看到int 80h 。
int 0x80是用于在x86(即Intel兼容)处理器上的Linux中调用系统调用的汇编语言指令。
最小的16位示例
首先学习如何创build一个最小的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
:停止执行
注意处理器如何查找第一个地址为0
处理程序,第二个处理程序是4
:这是一个称为IVT的处理程序表,每个条目有4个字节。
最小的例子,做一些IO使处理程序可见。
最小保护模式
现代操作系统以所谓的保护模式运行。
在这种模式下处理有更多的select,所以更复杂,但精神是一样的。
关键的一步是使用LGDT和LIDT指令,它们指向描述处理程序的内存数据结构(中断描述符表)的地址。
最小的例子
Linux使用0x80
Linux为0x80
设置中断处理程序,以便实现系统调用,这是用户程序与内核进行通信的一种方式。
你不能直接从userland设置你自己的处理程序,因为你只有ring 3,Linux会阻止你这样做。
你好世界的例子:
.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
编译并运行:
gcc main.S as -o main.o main.s ld -o main.out -s main.o ./main.out
更好的select
int 0x80
已经被更好的select::第一个sysenter
,然后是VDSO。
x86_64有syscall
。
另请参阅:有什么更好的“INT 0x80”或“系统调用”?
如前所述,它会导致控制跳转到中断向量0x80。 实际上这意味着(至less在Linux下)是调用系统调用; 确切的系统调用和参数由寄存器的内容定义。 例如,可以通过将%eax设置为1,接着是“int 0x80”来调用exit()。
“int”指令引发中断。
当收到中断时,CPU暂停。 然后检查存储中断例程(接收到中断时调用的函数)的IDT(或中断发生器T able)。
在许多* NIX操作系统中,系统调用是基于中断的; 也就是说,parameter passing给寄存器(EAX,EBX,ECX,EDX等)之后,中断0x80被调用。 内核已经设置IDT在0x80包含一个中断处理程序,当它接收到int80h时被调用。 这处理参数并调用一个内核函数。
这个function在不同的操作系统中可能有不同的含义。 一定要检查其文档,或尝试解散该平台的程序
它告诉CPU激活中断向量0x80,它在Linux操作系统上是系统调用中断,用于调用系统函数,如文件open()
等等。