它是如何完成的?我需要采取哪些步骤以及需要考虑哪些陷阱和陷阱?
5 回答
多亏了Apple Devforums的一些内部帮助,我已经完成了这项工作,如果您是专门的 iPhone 开发人员,您应该注册。
首先是__asm__(),而不是普通的asm()。
其次,默认情况下,XCode 会生成一个针对 ARM Thumb 指令集编译内联汇编的编译目标,因此无法将usat识别为正确的指令。要解决此问题,请在目标上执行“获取信息”。向下滚动到“GCC 4.0 - 代码生成”部分并取消选中“Compile for Thumb”。然后,如果您将 Active SDK 设置为“设备”,则以下代码段将编译得很好
inline int asm_saturate_to_255 (int a) {
int y;
__asm__("usat %0, #8, %1\n\t" : "=r"(y) : "r"(a));
return y;
}
自然,现在它不能与 iPhone Simulator 一起使用。但是TargetConditionals.h已经定义了你可以使用#ifdef 来反对。即TARGET_OS_IPHONE和TARGET_IPHONE_SIMULATOR。
我写了很多 ARM Cortex-A8 汇编代码。iPhone 上的 CPU 是 ARM11 (afaik),因此核心指令集是相同的。
你到底在找什么?如果你愿意,我可以给你一些例子。
编辑:
我刚刚发现在 iPhone 上你必须使用 llvm-gcc 编译器。据我所知,它应该理解 GCC 的内联汇编语法。如果是这样,所有 ARM 内联汇编器教程也可以在 iPhone 上运行。
这是一个非常小的内联汇编函数(在 C 中)。你能告诉我它是否可以在 iphone 上编译和工作吗?如果它有效,我可以咆哮一下如何在 ARM 内联汇编器中做有用的事情,特别是对于 ARMv6 架构和 DSP 扩展。
inline int saturate_to_255 (int a)
{
int y;
asm ("usat %0, #8, %1\n\t" : "=r"(y) : "r"(a));
return y;
}
应该相当于:
inline int saturate_to_255 (int a)
{
if (a < 0) a =0;
if (a > 255) a = 255;
return a;
}
寄存器也可以在 inline asm 中显式使用
void foo(void) {
#if TARGET_CPU_ARM64
__asm ("sub sp, sp, #0x60");
__asm ("str x29, [sp, #0x50]");
#endif
}
Thumb 推荐用于不需要大量浮动操作的应用。Thumb 使代码大小更小,并导致更快的代码执行。
所以你应该只为 3D 游戏之类的应用程序关闭 Thumb...
背景
- 现在是 2021 年 -> 其他答案似乎太旧了?</li>
- 大多数 iOS 设备(iPhone 等)是 ARM 64 位:
arm64
iPhone 上的内联组装
asm 关键字
- GNU/GCC 编译器
- 标准 C(编译标志:
-ansi
/-std
):使用__asm__
- GNU 扩展:使用
asm
- 标准 C(编译标志:
- ARM 编译器:使用
__asm
汇编语法
AFAIK,有很多 asm 语法
- 汇编语法
AT&T syntax
~=GNU syntax
~=UNIX syntax
Intel syntax
ARM syntax
这里只关注最常用的GNU/GCC
语法
GNU/UNIX syntax
基本汇编
asm("assembly code");
__asm__("assembly code");
扩展汇编
asm asm-qualifiers ( AssemblerTemplate
: OutputOperands
[ : InputOperands
[ : Clobbers ] ])
我的示例代码
- 环境
- 开发者
- 苹果系统
- IDE:X代码
- 编译器:
clang
- 编译器:
- IDE:X代码
- 苹果系统
- 跑步
- iOS - iPhone
- 硬件拱门:
ARM64
- 硬件拱门:
- iOS - iPhone
- 开发者
使用扩展 Asm 为 ARM64 调用 svc 0x80 的内联 asm
- ObjC 代码中的内联汇编
// inline asm code inside iOS ObjC code
__attribute__((always_inline)) long svc_0x80_syscall(int syscall_number, const char * pathname, struct stat * stat_info) {
register const char * x0_pathname asm ("x0") = pathname; // first arg
register struct stat * x1_stat_info asm ("x1") = stat_info; // second arg
register int x16_syscall_number asm ("x16") = syscall_number; // special syscall number store to x16
register int x4_ret asm("x4") = -1; // store result
__asm__ volatile(
"svc #0x80\n"
"mov x4, x0\n"
: "=r"(x4_ret)
: "r"(x0_pathname), "r"(x1_stat_info), "r"(x16_syscall_number)
// : "x0", "x1", "x4", "x16"
);
return x4_ret;
}
- 调用内联汇编
// normal ObjC code
#import <sys/syscall.h>
...
int openResult = -1;
struct stat stat_info;
const char * filePathStr = [filePath UTF8String];
...
// call inline asm function
openResult = svc_0x80_syscall(SYS_stat64, filePathStr, &stat_info);