如何完成?我需要采取哪些步骤,需要考虑哪些陷阱和意外情况?
如何完成?我需要采取哪些步骤,需要考虑哪些陷阱和意外情况?
我已经成功实现了这个,感谢在Apple Devforums得到的内部帮助,如果你是一名专注于iPhone开发的开发人员,那么你应该注册。
首先,它是__asm__(),而不是普通的asm()。
其次,默认情况下,XCode生成的编译目标会针对ARM Thumb指令集进行内联汇编编译,因此usat不能被识别为正确的指令。要解决这个问题,请在目标上执行“获取信息”操作。滚动到“GCC 4.0 - 代码生成”部分,并取消选中“编译为Thumb”。然后,如果将活动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模拟器一起使用。但是TargetConditionals.h有一些定义可以用#ifdef进行匹配。即TARGET_OS_IPHONE和TARGET_IPHONE_SIMULATOR。
我写了相当多的ARM Cortex-A8汇编代码。iPhone上的CPU是ARM11(据我所知),因此核心指令集是相同的。
你具体需要什么?如果你想要,我可以给你一些例子。
编辑:
我刚刚发现,在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;
}
void foo(void) {
#if TARGET_CPU_ARM64
__asm ("sub sp, sp, #0x60");
__asm ("str x29, [sp, #0x50]");
#endif
}
推荐在不需要大量浮点运算的应用程序中使用Thumb。Thumb可以使代码大小更小,也可以使代码执行更快。
因此,您应该只在像3D游戏这样的应用程序中关闭Thumb...
arm64
-ansi
/ -std
):使用__asm__
asm
__asm
据我所知,有许多asm语法
AT&T语法
~= GNU语法
~= UNIX语法
Intel语法
ARM语法
这里只关注最常用的GNU/GCC
语法
GNU/UNIX语法
asm("assembly code");
__asm__("assembly code");
asm asm-qualifiers ( AssemblerTemplate
: OutputOperands
[ : InputOperands
[ : Clobbers ] ])
clang
ARM64
// 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);
__attribute__((naked))
函数中或者在全局范围内定义整个函数而不是使用单独的.S文件。它永远不应该在那种情况之外使用;始终使用扩展汇编,这样您就可以决定是否要在您的"dsb ish"
中使用"memory"
清除,而不是在某些编译器上隐含地使用,在其他编译器上则不是。请参见https://gcc.gnu.org/wiki/ConvertBasicAsmToExtended,了解为什么这很糟糕。 - Peter Cordes-1
,这里对于 svc 0x80 syscall
的 检查打开文件
是特殊的。我稍后会进行测试,然后更新代码以不在一般情况下使用 -1
。 - crifan!= 0
而不是 == -1
,特别是如果它们被编写为使用这个内联汇编包装器而不设置 errno
。 - Peter Cordesstat
系统调用是其中的一部分,而不是通过内联汇编执行open
系统调用。我不了解iOS具体情况,但在POSIX操作系统下,您无需先进行stat操作。如果您想知道文件大小,应该在文件描述符已经打开后使用fstat
。 - Peter Cordes