-
在iOS中如何使用汇编语言
本文将系统地介绍如何利用XCode在iOS设备上使用汇编语言。
一、创建汇编源文件:
在你的XCode项目中存放源文件的目录下鼠标(或触控板)右键,选择New File。然后在左侧的iOS那栏里选择Other,在右边你会看到Assembly File,选中它,然后命名,以.s作为后缀。
二、编写汇编代码:
然后可以尝试以下代码:
/* * arm7.asm * Test * * Created by Zenny Chen on 4/24/10. * Copyright 2010 GreenGames Studio. All rights reserved. */ .text .align 4 .globl _my_arm_test .globl _my_thumb_test .arm _my_arm_test: vdup.32 q0, r0 qadd8 r0, r1, r2 add r0, r0, LSL #2 bx lr .thumb .thumb_func _my_thumb_test _my_thumb_test: movw r1, #1001 rev16 r0, r1 bx lr
这里要注意的是Apple所采用的ARM汇编器遵循GNU Assembler规范。其中,我们可以看到,汇编文件里的注释可以采用C语言标准的注释方式,也可以用C++标准的//注释方式。
.text表示代码正文部分。
.align根据不同的汇编器会有不同的行为,像这里的.align4可能表示4字节对齐,也可能表示16字节对齐。
GAS规范中表示,可以用.global或.globl来标注全局函数。在Apple的Assembler中仅支持.globl。函数名前要加下划线。
.arm表示后面的函数中的指令都是arm指令。而.thumb表示后面函数中的指令都是thumb或thumb-2指令。其中,如果一个函数是用thumb写的,那么必须用.thumb_func修饰,否则连接器在连接符号时会有问题。
上述代码中,_my_arm_test分别使用了一条NEON指令,一条ARMv6指令和两条ARMv5TE指令。而_my_thumb_test中则分别使用了一条ARMv7 Thumb-2指令、一条ARMv6指令和一条ARMv5TE指令。
另外,Apple LLVM汇编器中的条件预处理与C语言用的也几乎一样。可以使用#if、#else、#endif、#ifdef、#ifndef、#elif等等。另外,在架构标识上也统一使用了标准的架构标识符,比如:__i386__表示x86处理器架构;__x86_64__表示64位的x86处理器;__arm__表示ARM架构的处理器;__arm64__表示64位ARM架构处理器。下面给出一个示例代码:
.text .align 2 .globl _MyASMTest #if defined(__i386__) || defined(__x86_64__) _MyASMTest: xor %eax, %eax ret #elif defined(__arm__) _MyASMTest: eor r1, r0, r0 bx lr #elif defined(__arm64__) _MyASMTest: eor x1, x0, x0 ret #endif
如果要查看当前架构下的所有子架构所预定义的宏,那么可以使用以下控制台命令:
clang -arch arm64 -E -dM - < /dev/null
这将输出当前所有arm64架构下预定义的宏。
三、在C/C++或Objective C/C++中调用汇编函数
如何在你的C/C++源文件中调用汇编写的函数呢?其实这跟调用普通的C函数一样。
1
2
3
4
5
6
7
8
9
|
extern int my_arm_test( int a, int b, int c); extern int my_thumb_test( int a, int b); void my_test( void ) { printf ( "ARM value: %d\n" , my_arm_test(10, 20, 30)); printf ( "Thumb value: %d\n" , my_thumb_test(10, 20)); } |
我们可以看到,这里函数名前的下划线没有了。这里不需要,而且也不能加下划线。
由于当前Apple的ARM汇编器尚未完全支持Thumb-2指令集,像.w后缀就全都没有支持。但Apple LLVM3.0和LLVM-GCC支持。因此我们可以采用在C/C++中以内联汇编的方式来写。详细请参考——在LLVM的C语言编译器中内联纯汇编函数的注意事项。而Xcode4.5之后,Thumb-2已经支持得非常良好了。现在Xcode自带的汇编器还不支持Thumb-EE,不过它已经成为过时的指令集了,我们也无需深入研究,呵呵。
Apple LLVM 5.1开始,对ARMv7、VFPv4以及ARM64都已经完整支持了。下面再进一步介绍iOS中ARMv7以及ARM64下的ABI:
ARMv7中,对于通用寄存器,自己写的过程中需要保护R4、R5、R6、R7、R8、R9、R10、R11以及R14寄存器;NEON寄存器需要保存Q4、Q5、Q6、Q7寄存器。
ARM64模式下,通用寄存器X18、X30不能被使用。而需要被自己写的过程所保护的是:X19、X20、X21、X22、X23、X24、X25、X26、X27、X28、X29寄存器;而SIMD寄存器需要保护的是V8、V9、V10、V11、V12、V13、V14、V15。
出 处:https://www.cnblogs.com/zenny-chen/archive/2011/10/31/2229731.html