我该如何在XCode中使用ARM汇编器?

6

出于教育目的,我想在现有的 iPhone 应用程序中添加一个 ARM 汇编函数。我不需要一般 ARM 汇编的教程,因为我已经读了太多了。我只是不知道如何实际运行代码!

我想做的事情类似于:

useless.h:

void useless();

useless.s:

useless:
      bx lr

如果在模拟器上也能工作那就太好了... 在模拟器上,.s文件无法编译,所以我应该做一些像这样的事情: useless.s:
#if I_AM_ARM
useless:
      bx lr
#endif

useless.c:

#if !I_AM_ARM
void useless()
{
}
#endif

我知道我使用的语法是错误的,但是应该如何编写正确的语法呢?(不能仅仅因为想尝试一些内联汇编而在模拟器上破坏应用程序...)

第二个选择是使用内联汇编,但我强烈希望使用非内联汇编。

谢谢!

编辑:我想学习ARM汇编语言,所以我想找到一种编译ARM汇编代码和执行ARM汇编代码的方法。


声明 void useless(); 是正确的。据我所知,模拟器编译成本地代码而不是模拟ARM,因此汇编在那里不起作用。 - Notlikethat
如果使用了优化编译器,void useless() {} 很可能会被编译成 bx lr - tangrs
@Notlikethat:你是对的。 - Michael
@tangrs:你也是对的。 - Michael
但是,嘿伙计们...我想执行ARM汇编代码,因为我想学习ARM汇编。不应该太难,对吧?如果我没有编译器来构建我的代码,也没有平台来运行代码,我就无法学习ARM汇编。 - Michael
可以在下面的答案提到的我的博客文章中找到一个具有Github链接的实际工作示例。 - MoDJ
5个回答

4

我最终自己找到了答案。其实并不难,尽管我只针对32位ARM版本进行了解决。

useless.h:

void useless();

useless.s:

#ifdef __arm__


    .syntax        unified
    .globl         _useless
    .align         2
    .code          16
    .thumb_func    _useless

_useless:
    //.cfi_startproc
    bx    lr
    //.cfi_endproc

// CFI means Call Frame Information
// Optionally. Use for better debug-ability.


#endif

useless.c:

#ifndef __arm__

void useless()
{
}

#endif

注意:

CLANG ARM汇编语法与在网上看到的示例略有不同。注释以//开头,也支持/* 多行注释 */。它还理解标准C预处理器。函数必须定义为Thumb函数,如果指定了ARM函数(.code 32),程序将崩溃。行.thumb_func _useless可以省略,它仍然有效。我不知道它的含义。如果省略.code 16行,程序也会崩溃。

关于#ifdef。对于ARMv7,定义了__arm__。对于ARMv8,即iPhone 5S上的64位变体,未定义__arm__,但定义了__arm64__。以上代码不适用于64位ARM版本。而是使用useless.c中的实现。(我没有忘记ARMv7s,只是我手头没有那种架构的设备,无法测试。)


在Xcode 6中,使用.thumb_func将函数标记为thumb代码对其正常工作是必要的。 - BitBank

3
模拟器不使用arm架构。如果您想在模拟器上运行它,您需要编写x86_64汇编代码。(可能)。

1
我知道。我想为iPhone编写ARM汇编,并为模拟器编写一个纯C版本。我只想编译和执行任何ARM代码。 - Michael
1
来吧,伙计们。真的没有人在iPhone上使用过ARM汇编吗? - Michael
你是否在寻找一个表示arm64的预编译器标志?如果是,你可以使用__LP64__。 - Bryce Buchanan

1
你可以使用QEmu(其中包括一些Windows版本,例如http://lassauge.free.fr/qemu/)来模拟ARM-Ubuntu。如果你在Windows上,可能需要在中间模拟x86_64-Ubuntu。要创建一个ARM映像,您可以按照这个问题的步骤:Black screen in QEmu for ARM-Ubuntu (how to get GUI?)(是的,不幸的是,这些步骤没有GUI,只有一个控制台到ARM-Ubuntu机器,并且您必须从Ubuntu执行步骤)。然后,您可以将C ++ / C / Assembly程序从Windows / Ubuntu主机交叉编译到ARM-Ubuntu目标。
clang++.exe -Wall test1.cpp -o test1exe -std=c++14 -Ipath-to-arm-linaro/arm-linux-gnueabihf/include/c++/5.3.1 -Ipath-to-arm-linaro/arm-linux-gnueabihf/include/c++/5.3.1/arm-linux-gnueabihf -ffunction-sections -fdata-sections --sysroot=path-to-arm-linaro/arm-linux-gnueabihf/libc --target=arm-unknown-linux-gnueabihf -Bpath-to-arm-linaro/arm-linux-gnueabihf/bin/

要进行交叉编译,您需要下载并安装工具链,例如从https://releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux-gnueabihf/中获取的gcc-linaro-5.3-2016.02-i686-mingw32_arm-linux-gnueabihf.tar.xz(Windows/MinGW),然后将上述命令中的"path-to-arm-linaro"替换为工具链的路径。请保留HTML标签。

1

学习的最佳方式是查看实际的工作示例,可以参考我的博客文章ARM iOS timing。这个示例Xcode项目展示了如何混合使用函数的ARM ASM和C实现。此外还有一个非常准确的计时模块可以运行您的代码N次,因为准确的计时是优化代码时最困难的部分。


0

我刚刚开始学习 iOS 编程。第一件事就是尝试将汇编代码添加到我的项目中,但遇到了同样的问题。在 64 位模式下,静态数据的处理方式略有不同。通过查看编译器的汇编输出,我找到了解决方法。同一个 .S 文件在 Xcode 中会被编译成 32 位和 64 位两个版本,因此请按如下方式准备它:

        .globl         _myfunction
        .align         2

        my_constant_data:
              .byte 0,1,2,3,4,5,6,7

    #ifdef __arm__
        .thumb_func    _myfunction 
        .syntax        unified
        .code          16

    //
    // call from C as my myfunction()
    //
    _myfunction:
       ldr r0,=my_constant_data

    < write your thumb-2 code here >
       bx lr

    #else // or you can use #ifdef __arm64__
    //
    // Call from C as myfunction()
    //
    _myfunction:
       adrp x0, my_constant_data@PAGE
       add x0,x0, my_constant_data@PAGEOFF

    < write your Armv8 code here >
       ret

    #endif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接