内核如何知道"int 0x80"和"int x"之间的区别

-1 system-calls linux-kernel

int 0x80是一个系统调用,它在hexa中也是128.为什么内核使用int 0x80作为中断,当我声明int x时,他知道它只是一个名为x的整数,反之亦然?

zwo*_*wol 7

您似乎对C语言和汇编语言之间的区别感到困惑.两者都是编程语言,(现在)都接受0xNNNN以十六进制编写数字的符号,并且通常有一些方法可以在C程序中嵌入汇编语言的小片段,但它们是不同的语言.关键字int在C中意味着与(x86)汇编语言完全不同.

对于C编译器,int 始终并且表示声明涉及整数的内容,并且不存在可以立即跟随int数字文字的情况.int 0x80(或者int 128,或者int 23,或者其他任何类型的东西)总是C中的语法错误.

要在x86汇编,int 一直唯一的手段,产生的中断指令的机器代码,和一个数字文字必须立即执行. int x;在x86汇编语言中始终是语法错误.

明显的后续问题:如果C编译器不能识别int为INTerrupt指令,那么C程序(为x86编译)如何进行系统调用?这个问题有四个补充答案:

  1. 大多数情况下,在C程序中,您不直接进行系统调用.相反,您可以调用C库中为您执行此操作的函数.处理程序时,就C编译器而言,open(例如)与任何其他外部函数没有什么不同.所以它不需要生成int指令.它就是这样call open.

  2. 但是C库只是其他人为你写的C,不是吗?然而,如果您反汇编的实现open,您确实会看到一条int指令(或者可能syscall或者sysenter相反).编写C库的人是怎么做到的? 他们用汇编语言编写了这个函数,而不是用C. 或者他们使用这种技术在C程序中嵌入汇编语言的片段,这使我们...

  3. 什么用?难道这不是意味着C编译器需要了解int作为一个组件有时记忆?不必要.让我们看一下插入程序集的GCC语法 - 这可能是openx86/32/Linux的一个实现:

    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);
     }
    
    Run Code Online (Sandbox Code Playgroud)

    你不需要理解其中的大部分内容:对于这个问题而言,重要的是,是的,它说int 0x80,但它在字符串文字中表示.编译器会将该字符串文字的内容(逐字)复制到生成的汇编语言文件中,然后将其提供给汇编器.它不需要知道它意味着什么.这是汇编程序的工作.

  4. 更一般地说,有许多单词在C中表示一件事,在汇编语言中表示完全不同的东西.AC编译器生成汇编语言,因此它必须"知道"这两个词的含义,对吧?它确实如此,但它并不会混淆它们,因为它们总是在不同的环境中使用."add"是C编译器知道如何使用的汇编助记符,并不意味着在C程序中命名变量"add"存在任何问题,即使在该程序中使用了"add"指令也是如此.