int 0x80是一个系统调用,在hexa中也是128。为什么内核使用int 0x80作为中断,当我声明int x时,他知道它只是一个名为x的整数,反之亦然?
您似乎对C语言和汇编语言之间的区别感到困惑。两者都是编程语言,(现在)都接受0xNNNN
表示法来用十六进制写数字,通常有一些方法可以在C程序中嵌入汇编语言的微小片段,但它们是不同的语言。关键字int
在C中的含义与在(x86)汇编语言中的含义完全不同。
对于C编译器来说,int
总是,而only意味着声明涉及整数的东西,并且不存在可以在int
后面立即添加数字文字的情况。int 0x80
(或int 128
,或int 23
,或诸如此类的任何东西)在C.中总是一个语法错误
对于x86汇编程序,int
始终且仅意味着为INTerrupt指令生成机器代码,该指令的有效操作数("imm8",即0–255范围内的数字)必须是下一行。int x;
是x86汇编语言中的语法错误,除非使用汇编程序的宏功能将x
定义为适当范围内的常量。
显而易见的后续问题:如果C编译器不将int
识别为INTerrupt指令,那么C程序(为x86编译)如何进行系统调用?这个问题有四个互补的答案:
-
大多数时候,在C程序中,您不会直接进行系统调用。相反,您可以调用C库中为您执行此操作的函数。在处理程序时,就C编译器所知,
open
(例如)与任何其他外部函数都没有什么不同。因此,它不需要来生成int
指令。它只是做call open
。 -
但C库只是别人为你写的更多的C,不是吗?然而,如果您分解
open
的实现,您确实会看到int
指令(或者可能是syscall
或sysenter
)。编写C库的人是怎么做到的他们用汇编语言编写函数,而不是用C。或者他们用这种技术在C程序中嵌入汇编语言片段,这让我们。。。 -
是如何工作的?这难道不意味着C编译器有时需要将
int
理解为汇编助记符吗?不一定。让我们来看看用于插入程序集的GCC语法——这可能是x86/32/Linux的open
的实现:int open(const char *path, int flags, mode_t mode) { int ret; asm ("int 0x80" : "=a" (ret) : "0" (SYS_open), "d" (path), "c" (flags), "D" (mode)); if (ret >= 0) return ret; return __set_errno(ret); }
你不需要理解其中的大部分:对于这个问题来说,重要的是,是的,它说的是
int 0x80
,但它在字符串文本中说的是。编译器将逐字逐句地将该字符串文本的内容复制到生成的汇编语言文件中,然后将该文件提供给汇编程序。它不需要知道它的意思。这是装配工的工作。 -
更普遍地说,在C语言中有很多单词意味着一件事,在汇编语言中有许多单词意味着完全不同的事。C编译器产生汇编语言,因此它必须";知道";这两个词的意思,对吧?确实如此,但这并没有混淆它们,因为它们总是在不同的上下文中使用"添加";作为C编译器知道如何使用的汇编助记符;添加";在C程序中;添加";指令在那个程序中被使用。