首页 > 编程语言 >C和汇编混合编译

C和汇编混合编译

时间:2023-12-21 23:34:41浏览次数:47  
标签:汇编 int clang 混合 编译 add asm

有时候在写C语言项目的时候会需要用到汇编代码直接操作寄存器、栈之类更加底层的东西,所以在这里写一下C和汇编混合编程的几种方法(Windows和Linux需要分开讨论)

Windows

Visual Studio

Windows下常用的开发环境是Visual Studio,对于x86来说vs默认支持内联汇编,直接通过__asm关键词即可在函数体内嵌入汇编,例如

int add(int a, int b) {
    __asm {
        mov eax, a
        mov ebx, b
        add eax, ebx
    }
}

int main() {
    add(1, 2);
    return 0;
}

直接编译是没有错误的,而且x86还支持通过__declspec(naked)指定裸函数,正常的函数都是有函数序言和函数尾声的(即push ebp、pop ebp之类的),有时候我们并不需要这些东西,就可以声明裸函数,有我们自己来操控栈平衡

int __declspec(naked) add(int a, int b) {
    __asm {
        mov eax, a
        mov ebx, b
        add eax, ebx
        ret
    }
}

int main() {
    add(1, 2);
    return 0;
}

直接编译也没有任何问题

而且反编译来看确实没有乱七八糟的东西存在了。

但是从x64开始,VS就不再支持内联汇编了,而且也不支持naked关键字了。这里就可以切换项目的Platform Toolset为clang,clang默认支持x64内联汇编。Platform Toolset默认情况下是VS

点开来找到LLVM clang-cl

如果没有这个选项,可以打开vs安装工具,直接在单个组件里搜索LLVM,将两个组件都安装即可

然后直接切换为x64编译,是没有问题的

但是不支持裸函数。这里只能采取另一种方法,即额外创建一个asm,然后将asm文件链接到项目里。首先创建一个asm文件

extern mySub : PROC ; 引入C文件中的函数和全局变量
extern num : dw

.code
myAdd PROC
        call mySub
        mov ecx, dword ptr [num]
        add eax, ecx
        ret
myAdd ENDP
end

再创建一个C文件

extern int myAdd(int a, int b); // 引入汇编文件中的函数

int num = 0;

int mySub(int a, int b) {
    return a - b;
}

int main() {
    myAdd(1, 2);
    return 0;
}

可以看到两者之间互相引用是通过extern关键字来实现的。然后设置汇编文件的属性

再General中设置Item Type为自定义构建工具,点击应用后再去自定构建工具的General中设置如下两个东西

一个是命令行,一个是输出路径

ml64 $(InDir)%(fileName).obj /c %(fileName).asm
$(InDir)%(fileName).obj;$(Outputs)

注意这里Platform Toolset设置为默认的vs或者clang-cl都可以,直接编译可以看到没有报错

同时在反汇编中可以看到我们用汇编编写的函数

这种混合编程x86也适用,只不过需要将ml64改为ml

Clion

我个人更喜欢用Clion来编写C项目,这里Toolchains用的是VS的。x86内联汇编不说了,默认支持,主要来看x64的配置。如果要实现内联汇编,需要设置Toolchains为clang

这里clang-cl可以是vs的,也可以是另外安装的,然后添加CMake的选项让cmake用clang-cl编译

编译是没有问题的

如果要用混合编程,即创建一个asm文件链接到项目里,首先在CMakeLists.txt添加以下内容

主要是为了让cmake开启ASM_MASM支持,然后在Cmake设置选项,指定CMAKE_ASM_MASM_COMPILE为ml64

然后编译就没有任何问题

标签:汇编,int,clang,混合,编译,add,asm
From: https://www.cnblogs.com/musing/p/17920246.html

相关文章

  • Flutter 编译是pod intsall github 资源下载失败
    在fluterr编译报错然后显示github.xxxxx访问超时处理办法podinstall主要是读取profile文件platform:ios,'9.0'target'YourAppName'douse_frameworks!#这是安装依赖位置pod'SomeDependency'#添加其他依赖项...end想办法下载到github的文......
  • Android安卓打包app应用程序编译shrinkResources true报错解决方案
    Hello各位同学们好,我是咕噜铁蛋!在Android开发中,当我们需要打包应用程序时,经常会遇到一些问题。其中一个常见的问题是在使用shrinkResources设置为true时出现的编译错误。这个选项是在AndroidGradle插件的build.gradle文件中设置的,用于减少最终APK文件的大小。然而,如果设置不正确,可......
  • protobuf、protobuf-c、protobuf-c-rpc在Linux(Ubuntu18.04)编译安装及交叉编译arm\aar
    protobuf、protobuf-c、protobuf-c-rpc在Linux(Ubuntu18.04)编译安装及交叉编译arm\aarch64版本文章目录protobuf、protobuf-c、protobuf-c-rpc在Linux(Ubuntu18.04)编译安装及交叉编译arm\aarch64版本一、前言二、protobuf、rpc、protobuf-c、protobuf-c-rpc介绍1、protobuf2、protob......
  • 记录 | ubuntu源码编译安装/更新boost版本
    一、卸载当前的版本1、查看当前安装的boost版本dpkg-S/usr/include/boost/version.hpp通过上面的命令,你就可以发现boost的版本了,查看结果可能如下:libboost1.54-dev:/usr/include/boost/version.hpp2、删除当前安装的boostsudoapt-getautoremovelibboost1.54-dev这样就可以删......
  • 记录 | ubuntu源码编译安装faiss
    ubuntu源码编译安装faiss#安装依赖aptupdateaptinstallbuild-essentiallibopenblas-devliblapack-devlibopencv-dev#clonegitclonehttps://github.com/facebookresearch/faiss.gitcdfaiss./configuremake-j32makeinstall使用示例:#include<faiss/IndexF......
  • 记录 | ubuntu源码编译ccls
    ubuntu源码编译ccls#clone代码gitclone--depth=1--recursivehttps://github.com/MaskRay/ccls#安装libclang-15sudoapt-getinstallclanglibclang-15-dev#编译cmake-H.-BRelease-DCMAKE_BUILD_TYPE=Release\-DCMAKE_PREFIX_PATH=/usr/lib/llvm-15\......
  • ubuntu 18.04.6 编译Preloader提示 没有规则可制作目标 /host_tools/altera/preloader
     生成spl_bsp后,在spl_bsp路径下输入make 提示:没有规则可制作目标/host_tools/altera/preloader/uboot-socfpga.tar.gz 原来要先运行 ./embeddedcommandshell.sh,并在该终端窗口下输入make   ......
  • 使用汇编和反汇编引擎写一个x86任意地址hook
    最简单的Hook刚开始学的时候,用的hook都是最基础的5字节hook,也不会使用hook框架,hook流程如下:构建一个jmp指令跳转到你的函数(函数需定义为裸函数)保存被hook地址的至少5字节机器码,然后写入构建的jmp指令接着在你的代码里做你想要的操作以内联汇编的形式执行被hook地址5字节机......
  • clump与ball的混合情况
    ;fname:make_specimen.p2dat;;Generateadensegranularassemblywithinabox;;=============================================================================;Loadutility|FISH|functionsforlaterusesetechooff callStrainUtilities.p2fis ca......
  • QT 加载构建控件的时候 是灰色的,并且不能编译
    先上图 我安装完程序之后,返现上面红框中是灰色的,并且前面还带一个黄色感叹号并且下面C++的地方还是空的,应该是系统没有c++编译器 为系统安装g++编译器sudoapt-getinstallg++不能编译需要安装套件,用命令行安装sudoapt-getinstallbuild-essential......