ARM/Thumb指令相关。

本文详细介绍了ARM处理器在ARM和Thumb状态下的指令切换,以及如何通过BX指令进行模式切换。重点讲解了在C/C++和汇编代码中支持代码交织的实现,包括-mthumb-interwork编译参数的作用。同时,讨论了-mcaller-super-interworking和-mcallee-super-interworking选项在处理旧代码交织问题上的应用。文章还探讨了dlltool的代码交织支持,并通过代码示例说明了代码交织的工作原理和影响代码效率的因素。
摘要由CSDN通过智能技术生成


我们都知道ARM处理器有两种工作状态:ARM状态和Thumb状态。处理器可以在两种状态下随意切换。

处于ARM状态时,执行32位字对齐的ARM指令。

处于Thumb状态时,执行16位对齐的Thumb指令。

ARM 和 Thumb 指令集的动态切换,是通过 BX 指令使用一个寄存器名作为参数来完成。 

程序控制权被转交给该寄存器中存储的地址 ( LSB 位被屏蔽 )。

如果 LSB=1, 则进入 Thumb 指令处理模式; 如果 LSB=0, 则进入 ARM 指令处理模式。

通俗点讲其实就是BX 跳转的地址最低位为1还是0来判断是进入Thumb指令处理模式还是进人ARM指令处理模式。

一、针对 C 和 C++ 文件代码交织的显式支持


缺省情况下,如果一个文件没有使用任何特殊的编译命令行参数,编译生成的代码将不支持代码交织。

如果一个程序完全通过目标文件和库文件以要么全部是 ARM 指令,要么全部是 Thumb 指令的方式编译链接,

将能生成一个可工作的可执行文件。

如果尝试去链接的目标文件和库文件中,既包括 ARM 指令, 也包括 Thumb 指令, 链接器将产生警告信息并且

生成的可执行文件不能正常工作。


为了产生支持代码交织( interworking ) 的代码,需要使用如下编译参数:

[cpp]  view plain   copy
  print ? 在CODE上查看代码片 派生到我的代码片
  1. -mthumb-interwork  

如果一个程序所需要的所有目标文件和库文件都使用了该编译参数, 即使该程序的不同部分分别使用了 

ARM 指令和 Thumb 指令,链接生成的可执行文件也可以正确工作。 且链接器不会给出警告信息。

但是,需要注意的是,使用了 -mthumb-interworking 参数后,生成的代码大小将略微增大,执行效率略微降低。

这就是为什么代码交织支持必须使能一个特定编译开关的原因。


二、针对 arm 汇编文件代码交织的显式支持

如果汇编文件将被包括进一个支持代码交织的程序中,必须遵循如下规则:

  • 任何外部可见函数必须使用  BX 指令返回
  • 普通的函数调用可以使用 BL 指令。链接器将自动插入代码以便进行 ARM 和 Thumb 指令切换
  • 如果函数指针调用来自 ARM 代码, 应该使用 BX 指令。

          然而,下述指令不能在 Thumb 模式工作,因为 MOV 指令没有正确设置 LR 寄存器的 LSB 位。

[cpp]  view plain   copy
  print ? 在CODE上查看代码片 派生到我的代码片
  1. .code 32  
  2. mov lr, pc  
  3. bx  rX  
            因此,应该使用 branch-and-link 指令来调用 _call_via_rX 函数。

            其中, rX 表示包含有该函数地址的寄存器名称。

[cpp]  view plain   copy
  print ? 在CODE上查看代码片 派生到我的代码片
  1. .code 16  
  2. bl  _call_via_rX  

  • 所有在 Thumb 模式运行的外部可见函数, 必须在函数入口前使用 .thumb_func 伪指令。

[cpp]  view plain   copy
  print ? 在CODE上查看代码片 派生到我的代码片
  1. .code 16  
  2. .global function  
  3. .thumb_func  
  4. unction:  
  5. ...start of function....  

  • 所有汇编文件必须使用 -mthumb-interwork 参数进行编译。
    (如果使用gcc 编译,如果该汇编文件被指定为第一个文件, gcc 将自动传入 -mthumb-interwork 参数)

三、支持古老的且无法区别 代码交织的代码

如果要链接相对古老的代码, 或者通过不支持代码交织的编译器生成的代码,或者通过新编译器产生

但是没有使用 -mthumb-interwork 参数生成的代码,有两种编译参数可以处理这种情况。

  • 编译开关: -mcaller-super-interworking

       该参数允许在 Thumb 模式的函数指针调用正常工作,而无须考虑该函数指针是否指向老的,无法区别代码交织的代码。

       使用该开关将产生执行较慢的代码。

       注意: 

       没有编译开关用于允许 ARM 模式的函数指针调用被特别处理。

       对于借助于函数指针的调用,如果从支持代码交织的 ARM 代码调用不支持代码交织的 ARM 代码,该调用能正常工作而

       无须编译器考虑有任何考虑。

       对于借助于函数指针的调用,如果从支持代码交织的 ARM 代码调用不支持代码交织的 Thumb 代码,该调用不能正常工作。

       (实际上对于某些特定情况,也能工作; 但是无法保证一定能工作) 这是因为只有新编译器可以产生 Thumb 代码,

        并且该编译器已经使用编译开关来产生支持代码交织的代码。

  • 编译开关: -mcallee-super-interworking

        该参数允许无法区别 ARM 和 Thumb 的代码调用 Thumb 函数,无论是直接调用或借助于函数指针的调用。

        使用此参数将产生略大且执行稍慢的代码。

        注意:

        没有编译开关可以用于允许无法区别代码交织的 ARM 或者 Thumb 代码调用 ARM 函数。
       对于从无法区别代码交织的 ARM 代码调用支持代码交织的 ARM 函数,没有必要进行任何特殊处理。
       对于从不支持代码交织的 Thumb 代码调 ARM 函数,将不能正常工作。

       这种情况没有其他选择,除非能够重新编译成支持代码交织的 Thumb 代码。

       作为编译参数 -mcallee-super-interworking (因为它影响同一个文件中所有的外部可见函数)   的替换选择,

       可以对单个函数指定一个属性或者 declspec 符号。通过此方式来表示该特定函数可以支持从无法区别代码交织的代码里被调用。

       示例如下:

[cpp]  view plain   copy
  print ? 在CODE上查看代码片 派生到我的代码片
  1.     int function __attribute__((interfacearm))  
  2.     {  
  3.         ... body of function ...  
  4.     }  
  5.   
  6. or  
  7.   
  8.     int function __declspec(interfacearm)  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值