• 服务器正文20:跨平台(win和linux)用cmake给程序增加汇编代码


    • 备注(文件格式要求)
    需要注意所有文件的编码格式一定要是utf-8或者utf-8 with BOM
    
    • 1

    一、cmake在linux下增加.S汇编文件到程序调用

    1)背景介绍

    在Linux下常用的C/C++编译器为GCC。近些年,随着LLVM项目的发展,Clang也占有了一席之地。但它们在Linux平台下,背后默认的汇编器依然是GAS。GAS使用语法格式为AT&T,与我们平常学习的Intel格式截然不同。它们的差别这里就不赘述了,网络上很多这方面的资料。那我们能不能在Linux平台也使用我们熟悉的Intel语法格式的汇编呢?答案是肯定的。

    2)cmakelists.txt

    if(MSVC)
    	XXXX
    else()
    	enable_language(ASM)
    	list (APPEND  SRC_FILES
    		"${BASE_DIR}/src/asm/jump_x86_64_linux.S"
    		"${BASE_DIR}/src/asm/make_x86_64_linux.S"
    	)
    endif()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    二、cmake在win下增加.asm汇编文件到程序调用

    1)代码

    • asm汇编代码
    extern printf ;声明printf,将调用C语言的printf函数
    
    section .rodata
        msg  db "这是汇编中的输出",0xa,0
    
    section .text
    global 汇编函数
    汇编函数:
        push 	rbp
        mov 	rbp, rsp
        lea 	rdi, [rel msg]
        call printf wrt ..plt ;也可以使用 call 	[rel printf wrt ..got]
        mov 	eax, 0
        leave
        ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • main.cpp代码
      在这里插入图片描述

    2)cmakelists.txt(一部分)

    if(MSVC)
    	list (APPEND  SRC_FILES
    		"${BASE_DIR}/src/asm/jump_x86_64_win.asm"
    		"${BASE_DIR}/src/asm/make_x86_64_win.asm"
    	)
    	SET(MASMFound FALSE)
    	enable_language(ASM_MASM)
    	//SET(CMAKE_ASM_NASM_FLAGS "-g") # 让NASM生成调试信息
    	if(CMAKE_ASM_MASM_COMPILER_WORKS)
    		SET(MASMFound TRUE)
    	else()
    		# This could happen if the CMakeCache.txt was deleted; 
    		#try finding the ASM_MASM compiler again
    		include(CMakeDetermineASM_MASMCompiler)
        	include(CMakeTestASM_MASMCompiler)
        	if(NOT CMAKE_ASM_MASM_COMPILER_WORKS)
    			message(FATAL_ERROR "enable  ASM_MASM failed")
    		endif()
    	endif(CMAKE_ASM_MASM_COMPILER_WORKS)
    endif()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3)masm需要注意的点(.plt)

    lea  rdi, [rel msg]
    call printf wrt ..plt 
    
    
    • 1
    • 2
    • 3

    因为GCC编译器默认会使用PIE(Position-Independent-Executable)模式(即位置无关的模式,这里就不深入探讨了,感兴趣的朋友可以网上查资料深入了解),所以64位的汇编也必须要使用PIE模式。如果我们直接按下面的方式来写:

    lea  rdi, [msg]
    
    • 1

    就会出现链接错误:

    [build] /usr/bin/ld: CMakeFiles/demo.dir/test.asm.o: relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIE
    [build] /usr/bin/ld: failed to set dynamic section sizes: bad value
    [build] collect2: error: ld returned 1 exit status
    
    • 1
    • 2
    • 3

    或者调用的方式写成:

    call printf
    
    • 1

    也会出现链接错误:

    [build] /usr/bin/ld: CMakeFiles/demo.dir/test.asm.o: warning: relocation against `printf@@GLIBC_2.2.5' in read-only section `.text'
    [build] /usr/bin/ld: CMakeFiles/demo.dir/test.asm.o: relocation R_X86_64_PC32 against symbol `printf@@GLIBC_2.2.5' can not be used when making a PIE object; recompile with -fPIE
    [build] /usr/bin/ld: final link failed: bad value
    [build] collect2: error: ld returned 1 exit status
    
    • 1
    • 2
    • 3
    • 4

    当然,也可以让GCC不使用PIE模式,在CMakeLists.txt中添加一句:

    SET(CMAKE_CXX_FLAGS "-no-pie")
    
    • 1

    这样就可以把前面两句写成:

    lea  rdi, [msg]
    call printf
    
    • 1
    • 2

    但是不建议这样做

    4)cmake判断编译成32位还是64位(CMAKE_CL_64是64位)

    在这里插入图片描述

    三、其他备注(boost汇编看到的一些其他东西)

    因为最近需要用汇编实现协程的切换,考虑到boost是全平台的实现,所以用了boost的汇编代码,下面是一些备注

    1、elf
    目标文件再不同的系统或平台上具有不同的命名格式,在Unix和X86-64 Linux上称为ELF(Executable and Linkable Format, ELF)。
    ELF文件详解

    2、MASM的环境搭建(没用到)
    传送门

    3、clang
    clang是C,C ++和Objective-C编译器,包括预处理,解析,优化,代码生成,汇编和链接。通过模式设置(参考阶段选择选项),Clang将在完成链接之前停止
    介绍传送门

    4、macho
    MachO文件是一种文件格式,是iOS或者OSX系统的可执行文件的格式
    介绍传送门

  • 相关阅读:
    Git的入门详细教程
    Blender 学习笔记(一)
    UG NX二次开发-博客文章速览
    ARM架构
    lv3 嵌入式开发-5 linux shell命令(进程管理、用户管理)
    【Docker】Docker安全性与安全实践(五)
    keycloak~为keycloak-services项目添加第三方模块(首创)
    测试开发——进阶篇2
    车联网远程监控管理提升车辆调度效率,实现高效运营
    【工艺库】SMIC数字后端工艺库
  • 原文地址:https://blog.csdn.net/weixin_43679037/article/details/126025754