‘Hello World!’ in ARM assembly

http://peterdn.com/post/e28098Hello-World!e28099-in-ARM-assembly.aspx


‘Hello World!’ in ARM assembly

by peterdn 14. 一月 2012 22:29

Over the last few weeks, in an effort to port a small C library to the platform, I’ve been doing a fair bit of tinkering around with the Android NDK.  The NDK is primarily intended to allow Android developers to write performance-critical portions of their apps in native C or C++, which interface with the Android Java API through JNI.  As the C library in question required porting some x86 SIMD assembly, I figured it would be helpful for me to get to know the bare bones of the ARM architecture.  As a means to this end, we can use the NDK’s cross-compiler as a standalone tool to write a simple ‘Hello World!’ console “app” in ARM assembly.  As Android is effectively Linux under the hood, we can apply our x86 Linux assembly programming skills to the ARM platform.

First things first: ‘Hello World!’ in x86 assembly

Briefly, the method involves invoking system calls by talking directly to the underlying Linux kernel.  An example of how to do this in x86 assembly is given here.  As ARM uses a different ABI to x86 (registers are named different things, for a start), this code needs a tiny bit of modification.

Firstly, notice that system calls are identified numerically – in the x86 example, #1 refers to exit() and #4 refers to write().  To invoke a system call, we put its identifier in the EAX register, pass (up to 6) arguments in EBX, ECX, EDX, ESI, EDI, EBP, respectively, and interrupt 0x80 is generated.  This is described in further detail here.  In contrast, the ARM ‘EABI’ calling convention uses a different method which is described vaguely in these patch notes.  We can glean that, on ARM, the system call identifier is put in register R7, arguments are passed in R0-R6 (respecting “EABI arrangement” where appropriate, i.e. 64-bit arguments), and the kernel is called with the ‘SWI 0’ instruction. 

Secondly, as they are not guaranteed to be the same on each platform, we must look up the system call identifiers for exit() and write().  For this we refer to the Linux kernel source – $LINUX_SOURCE_ROOT/arch/arm/include/asm/unistd.h, specifically.  As it turns out, these two system calls do have the same identifiers on both x86 and ARM platforms.

To ARM

So our assembly code, in GAS syntax, looks very much like (see inline comments for details):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.data
 
msg:
    .ascii      "Hello, ARM!\n"
len = . - msg
 
 
.text
 
.globl _start
_start:
    /* syscall write(int fd, const void *buf, size_t count) */
    mov     %r0, $1     /* fd -> stdout */
    ldr     %r1, =msg   /* buf -> msg */
    ldr     %r2, =len   /* count -> len(msg) */
    mov     %r7, $4     /* write is syscall #4 */
    swi     $0          /* invoke syscall */
    
    /* syscall exit(int status) */
    mov     %r0, $0     /* status -> 0 */
    mov     %r7, $1     /* exit is syscall #1 */
    swi     $0          /* invoke syscall */

Assembling

Save the above as hello.S and run it through the GNU cross-assembler provided with the NDK.  I will assume that you have the prebuilt NDK toolchain directory in your PATH (in my case here, /Users/peterdn/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin):

?
1
2
arm-linux-androideabi-as -o hello.o hello.S
arm-linux-androideabi-ld -s -o hello hello.o

Deploying to Android

For many, the easiest way to test the above binary is by deploying it to an Android device with an ARM processor.  This also means we can take advantage of the insanely useful ‘adb’ tool.  If you happen to be running bog-standard Linux on an ARM device, the binary should still run, providing your kernel supports the newer EABI (I believe 2.6.15 and above).

To deploy and test on Android, simply run:

?
1
2
adb push hello /data/local/tmp/hello
adb shell /data/local/tmp/hello

It is also possible to run the binary locally on your device using the Android Terminal Emulator, as below:

Android Terminal Emulator screenshot

Enjoy!

Currently rated 4.0 by 3 people

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(581) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值