可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
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.
回答1:
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.)
回答2:
The simulator doesn't use arm. you'll have to write x86_64 assembly if you want it to run on the simulator. (probably).
回答3:
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.
回答4:
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.
回答5:
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