前言
首先什么是内联汇编?
内联汇编是在C,C++代码内部嵌入一部分汇编代码, 这部分代码会被编译器跳过直接拼接.
为什么要用内联汇编?
这种情况一般是由于我们对于当前的编译器的能力感到不满意, 所以需要代替编译器来优化一些代码片段. 当然我们可以完全进行汇编实现, 直接把函数写成一个.asm汇编文件(这个文件可以用yasm, nasm, masm进行编译为object文件参与代码链接). 内联汇编相比较而言不用实现整个函数, 比如函数的入栈和出栈的操作, 栈指针也不需要你去计算然后移动, 只需要用寄存器实现高效率的计算.
内联汇编需要特殊的编译器或者命令吗?
内联汇编属于正常C++编译器的特性, 不需要额外的编译命令. 但是MSVC目前只支持32位的内联汇编, 64位汇编据官方说法是没必要. 如果使用Clang进行编译的话就没有问题, 都支持.
微软原话:Inline assembly is not supported on the ARM and x64 processors. 具体官方链接在这里:https://docs.microsoft.com/zh-cn/cpp/assembler/inline/inline-assembler?view=msvc-160
正文
一. 32位汇编
a. 首先创建一个win32的空项目, 这一步省略, 可以参考我前面的文章.
b. 一个简单的内联汇编代码如下:
#include <stdio.h>
int main()
{
int test = 1;
__asm
{
mov eax, test //把test的值写入eax寄存器
dec eax //寄存器数值减一
mov test, eax //把eax的值写回test变量中
}
printf("test:%d\n", test); //test 为0
return 1;
}
c. 整体看起来是这样的:
可以看到写32位的内联汇编只需要修改代码, 不需要更改VS的任何配置就可以.
补充一个内联汇编的技巧:
操作数组和_asm行代码:
__asm后面可以直接跟一行汇编代码. 另外汇编代码支持[]的索引操作符.
但是, 这里有个容易犯错的地方:
这个易错点就是[]里面的index是字节offset, 不是元素的index. 从上图中可以看到mov arr[1], 2; 这个代码实际上把2写到了arr的第0个元素arr[0]的第二个字节