【发布时间】:2010-09-19 06:37:39
【问题描述】:
它是如何完成的?我需要采取哪些步骤以及需要考虑哪些陷阱和陷阱?
【问题讨论】:
-
问得好,我很想看看回复。
标签: iphone assembly inline-assembly
它是如何完成的?我需要采取哪些步骤以及需要考虑哪些陷阱和陷阱?
【问题讨论】:
标签: iphone assembly inline-assembly
我写了很多 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;
}
【讨论】:
感谢Apple Devforums 的一些内部帮助,我已经完成了这项工作,如果您是专门的 iPhone 开发人员,您应该注册。
首先,它是 __asm__(),而不是普通的 asm()。
其次,默认情况下,XCode 会生成一个针对 ARM Thumb 指令集编译内联汇编的编译目标,因此 usat 未被识别为正确的指令。要解决此问题,请在目标上执行“获取信息”。向下滚动到“GCC 4.0 - 代码生成”部分并取消选中“Compile for Thumb”。如果将 Active SDK 设置为“设备”,那么下面的 sn-p 将编译得很好
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。
【讨论】:
Thumb 推荐用于不需要大量浮动操作的应用。 Thumb 使代码更小,代码执行速度也更快。
所以你应该只为 3D 游戏之类的应用程序关闭 Thumb...
【讨论】:
寄存器也可以在 inline asm 中显式使用
void foo(void) {
#if TARGET_CPU_ARM64
__asm ("sub sp, sp, #0x60");
__asm ("str x29, [sp, #0x50]");
#endif
}
【讨论】:
arm64
-ansi/-std):使用__asm__
asm
__asm
AFAIK,有很多 asm 语法
AT&T syntax ~= GNU syntax ~= UNIX syntax
Intel syntaxARM syntax这里只关注最常用的GNU/GCC语法
GNU/UNIX syntaxasm("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 文件)。绝不应在该上下文之外使用它;始终使用扩展 asm,这样您就可以决定是否要使用 "dsb ish" 使用 "memory" clobber,而不是将其隐含在某些编译器上而不是其他编译器上。请参阅gcc.gnu.org/wiki/ConvertBasicAsmToExtended 了解其可怕的原因。
$label(%edx,%ebx,$4) 引用符号 $label,而不是 label;也许您将它与 AT&T 语法混为一谈以获取直接操作数?但这是在 Basic Asm 部分,所以它应该被删除。)在 Extended Asm部分,您仍在使用 AT&T 语法来处理 x86 / x86-64,尽管至少它看起来没有错误。但由于 AT&T 的源/目标顺序与 AArch64 程序集相反,这可能会造成混淆。
svc 0x80 的 AArch64 示例忘记在您编写的硬寄存器上声明 clobbers。请注意,您的函数甚至是 always_inline,因此即使在 -O0 处,这也会导致损坏,而不仅仅是启用优化。 (不是这样就可以了;即使noinline 也不能证明它是合理的,因为编译器可以选择 x0 作为输入,因此您在阅读之前覆盖它。)。
mov 开头和/或结尾,你通常做错了(或效率低下):相反,告诉编译器你想要你的值在哪个寄存器中。例如使用register const char *path __asm__("x0") = pathname 进行"r" 约束选择x0。请参阅stackoverflow.com/tags/inline-assembly/info 中的链接。这具有另一个优点,即编译器知道这些值之后仍在 regs 中。你可能应该使用"r"(SYS_stat64) 约束作为电话号码,如果 iPhone 有,则使用来自<sys/syscall.h> 的常量(GNU 和 BSD 可以)。