Leo*_*rka 1 c c++ java assembly inline-assembly
我最近阅读了这篇名为Embedded Systems/Mixed C and Assembly Programming 的文档
它主要涉及 C 和 C++ 如何允许用户通过称为内联汇编的技术使用汇编代码,该技术看起来像这样:
#include<stdio.h>
void main() {
int a = 3, b = 3, c;
asm {
mov ax,a
mov bx,b
add ax,bx
mov c,ax
}
printf("%d", c);
}
Run Code Online (Sandbox Code Playgroud)
我想知道在其他高级语言(如 Java、Python 和其他语言)中是否可以进行类似的交互,或者是否只能使用 C 和 C++。
是的,D、Rust、Delphi 和许多其他提前编译的语言都有某种形式的内联汇编。
Java 没有,通常从可移植二进制文件(如 Java 的 .class 字节码或 C# 的 CIL)进行 JIT 编译的大多数其他语言也没有。 Java中的代码注入/汇编内联?.
像 Python 这样的高级语言甚至没有简单的数字对象表示,例如整数变量不仅仅是一个 32 位对象,它还具有类型信息,并且(特别是在 Python 中)对于大值可以是任意长度. 因此,即使一个Python实现也有内联汇编设施,这将是让你做任何事情的Python对象,这与NumPy阵列也许除外挑战的布局像C数组。
可以从大多数高级语言调用本机机器代码函数(例如从 C 编译的库或手写 asm)——这对于编写某些类型的应用程序通常很重要。例如,在 Java 中有 JNI(Java 本机接口)。甚至 node.js JavaScript 也可以调用原生函数。“编组” args 到一个有意义的形式传递给 C 函数可能会很昂贵,这取决于高级语言以及您是想让 C/asm 函数修改数组还是只返回一个值。
通常,它们不像您使用的那样是 MSVC 的低效形式(这会强制存储/重新加载输入和输出)。更好的设计,比如以 GNU C 内联 asm 为模型的 Rust 可以使用寄存器。例如,像 GNU C 一样,asm("lzcnt %1, %0" : "=r"(leading_zero_count) : "rm"(input));让编译器选择一个输出寄存器,并为输入选择寄存器或内存寻址模式。
(但更好的是使用类似_lzcnt_u32或__builtin_clz编译器知道的操作的内在函数,仅内联 asm 用于编译器没有内在函数的指令,或者如果您想以某种方式微优化循环 。https://gcc .gnu.org/wiki/DontUseInlineAsm )
有些(如 Delphi)通过类似于函数调用的“调用约定”进行输入,在寄存器中带有 args,不能完全自由地混合 asm 和高级代码。所以它更像是一个带有固定输入的 asm 块,以及一个特定寄存器中的一个输出(加上副作用),编译器可以像函数一样内联。
对于像你展示的那样工作的语法,要么
请注意,MSVC 对内联 asm 的特定实现非常脆弱和笨拙,以至于它不能在带有寄存器 args 的函数中安全工作,这意味着根本不支持 x86-64 或 ARM/AArch64,其中标准调用约定使用寄存器 args . 相反,它们基本上为每条指令提供了内在指令,包括像 那样的特权指令,invlpg从而可以在 Visual C++ 中编写内核(例如 Windows)。(其他编译器希望您将其asm()用于此类事情的地方)。Windows 几乎可以肯定有几个部分写在单独的 .asm 文件中,例如中断和系统调用入口点,也许还有一个上下文切换函数,它必须加载一个新的堆栈指针,但具有良好的内在支持,您不需要 asm,如果你相信你的编译器能自己制作出足够好的 asm。