How do I use the ARM assembler in XCode?

Just for educational purposes, I would like to add a function to an existing iPhone app, written in ARM assembly. I don’t need a tutorial on ARM assembly in general, because I already read too many of them. I just don’t know how to actually run the code!

What I would like to do is something like:

  • Cross-compiling ZeroMQ to ARM for use in a MonoTouch iPhone app configure settings
  • RGBA to ABGR: Inline arm neon asm for iOS/XCode
  • Mach-O symbol stubs (IOS)
  • Compiling Assembly (.S) file alongside iPhone project
  • return floats to objective-c from arm assembly function
  • duplicate symbols for architecture armv7
  • useless.h:

    void useless();
    

    useless.s:

    useless:
          bx lr
    

    If this also works on the simulator it would be fine… On the simulator, the .s file would not compile, so I should maybe do something like:

    useless.s:

    #if I_AM_ARM
    useless:
          bx lr
    #endif
    

    useless.c:

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

    I know the syntax I use is broken, but how do I write it correctly? (Breaking an app on the simulator just because I want to try some inline assembly is no option…)

    The second-best option would be to use inline assembly, but I would strongly prefer non-inline assembly.

    Thanks!

    Edit: I want to learn ARM assembly, so I would like to find a method to compile ARM assembly code, and to EXECUTE ARM assembly code.

    5 Solutions Collect From Internet About “How do I use the ARM assembler in XCode?”

    I finally found the answer myself. It’s actually not that hard. I only solved it for the 32-bit ARM version though.

    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
    

    Notes:

    The CLANG ARM Assembler syntax is a bit different from what you see in example all over the web. Comments start with // and /* multiline comments */ are also supported. It also understands the standard C preprocessor. The function has to be defined as a Thumb function, if you specify an arm function (.code 32) the program will just crash. The line .thumb_func _useless can be ommited and it works still. I have no Idea what it means. If you omit the .code 16 line, the program crashes.

    about the #ifdef. For ARMv7, __arm__ is defined. For ARMv8, i.e. the 64bit-variant on the iPhone 5S, __arm__ is not defined, but __arm64__ is defined instead. The above code does not work for the 64bit-ARM-version. Instead, the implementation from useless.c will be used. (I didn’t forget ARMv7s, I just don’t have a device with that arch in my hands currently, so I cannot test.)

    The simulator doesn’t use arm. you’ll have to write x86_64 assembly if you want it to run on the simulator. (probably).

    I just started working with iOS. The first thing I tried to do was add asm code to my project and ran into the same problem. The static data is handled slightly differently in 64-bit mode. I discovered how to do it by looking at the assembler output of the compiler. The same .S file will be compiled as both 32 and 64-bit in Xcode, so prepare it like this:

            .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
    

    The best way to learn is to take a look at actual working examples, see my blog post about ARM iOS timing. This example Xcode project shows how to mix ARM ASM and C impls of a function. There is also a very accurate timing module to run your code N times, because accurate timing is the hard part when it comes to optimizing the code.

    You can emulate ARM-Ubuntu with QEmu (there are some Windows ports of it, e.g. http://lassauge.free.fr/qemu/ ). If you are on Windows, you may need to emulate x86_64-Ubuntu in the middle. To create an ARM image you can follow the steps from this question: Black screen in QEmu for ARM-Ubuntu (how to get GUI?) (yes, unfortunately, you get no GUI with these steps, just a console to the ARM-Ubuntu machine, and you have to do the steps from Ubuntu). Then you can cross-compile your C++/C/Assembly programs from Windows/Ubuntu host to ARM-Ubuntu target.

    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/
    

    For cross-compilation you would need to download and roll out a toolchain, e.g. gcc-linaro-5.3-2016.02-i686-mingw32_arm-linux-gnueabihf.tar.xz (Windows/MinGW) from https://releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux-gnueabihf/ and replace “path-to-arm-linaro” in the above command with the path to the toolchain.