Running Hello World in Assembly Language on Android

Principle of Ximen Chui Xue

This article explains how to write a GNU ARM assembly program and run it on an Android phone.

Running Hello World in Assembly Language on Android

(1) Why Learn ARM Assembly?

If learning is only done when needed, then nothing needs to be learned in advance. The situation of “learning when needed” often exists and makes sense; your time and energy should not be spent on knowledge and skills that are not currently useful (will they be useful in the future? Let’s deal with problems that have already appeared or are about to appear; if there are no problems, then just enjoy yourself). Similarly, learning ARM assembly is best done because you need this knowledge and skill for what you are “doing”, such as translating someone else’s assembly code, making some reverse modifications to assembly code, or understanding the assembly code when a program crashes, etc. As for showing off, that is also a reason (showing off may also give you a certain perspective).

(2) How to Write a Hello World?

Just write it with your familiar editor and save it as a .s file. As for the syntax of GNU ARM ASM, refer to the manual and examples.

For example, to say hello:

  .data  
  msg:  .asciz  "hello, gnu asm\n"  
  len = . - msg  .text  
  .global main                                                                                                                        
  main:  
  push    {r0,r1,r2,lr}
  ldr     r1, =msg         @ address  
  mov     r0, #1          @ stdout  
  ldr     r2, =len         @ length  
  mov     %r7, $4     /* write is syscall #4 */
  swi     $0          /* invoke syscall */
  pop     {r0,r1,r2,pc}

And for summation:

    .data
    msg: .asciz "sum=%d\n"

    .text 
    sum:    push {lr}    mov r2, r0
    mov r3, r1
    add r0, r2, r3
    pop {pc}    
    
    .global main
    main:   
    push {r0, r1, r2, lr}    mov r0, #100
    mov r1, #120
    bl sum 
    mov r1, r0
    ldr r0, =msg
    bl printf    pop {r0, r1, r2, pc}

(3) How to Compile an Assembly Program?

Since the final goal is to run on an Android device, the executable format must be ELF, so it needs to be compiled into ELF format.

On Mac, you need to use a cross-compilation tool (a tool that compiles programs for another platform), which can be: arm-linux-androideabi-gcc (for example, in the directory: toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/), but when compiling (for example, directly gcc -o test test.c), you may encounter issues with header files (like stdio.h) not being recognized, due to not specifying the directory of the header files.

Solution: Use the compilation toolchain.

A compilation toolchain is an environment suitable for a certain scenario (such as generating executable files for a certain platform), including the header files needed during compilation.

To create this compilation environment, you need to use the make-standalone-toolchain.sh script in the NDK.

The final compilation script is as follows:

#!/bin/bash

# toolchain

TOOLCHAIN=~/asmtoolchain

SYSROOT=$TOOLCHAIN/sysroot/

ANDROID_NDK_ROOT=/Users/sky/Documents/android-ndk-r10d

NDK_PATH=$ANDROID_NDK_ROOT

MIN_PLATFORM=android-8

TOOLCHAIN_VER=arm-linux-androideabi-4.8

OUT_NAME=helloasm

OBJS=helloasm.s

if [ ! -d $SYSROOT ]; then

$NDK_PATH/build/tools/make-standalone-toolchain.sh –platform=$MIN_PLATFORM –install-dir=$TOOLCHAIN –toolchain=$TOOLCHAIN_VER

fi

PATH=$TOOLCHAIN/bin:$PATH

CC=arm-linux-androideabi-gcc

#LD=arm-linux-androideabi-ld

#AR=arm-linux-androideabi-ar

$CC –sysroot=$SYSROOT -o $OUT_NAME $OBJS

The executable file compiled above is in ELF format (you can check with file helloasm).

(4) Running the Executable File

Copy the executable file (for example, helloasm) to the /data directory of the Android phone to run it (first adb push to /sdcard/, then adb shell to the phone and copy to /data, then chmod 777 helloasm, after which it can be run).

(5) Disassembling the Final Executable File

Disassemble the compiled executable file and see how different it is from the source file.

For example, after disassembling the above summation executable program using Hopper, you can see code like this (part):

sum:
    @ args = 0, pretend = 0, frame = 8
    @ frame_needed = 1, uses_anonymous_args = 0
    @ link register save eliminated.
    str fp, [sp, #-4]!
    add fp, sp, #0
    sub sp, sp, #12
    mov r3, #10
    str r3, [fp, #-8]
    mov r3, #3
    str r3, [fp, #-12]
    ldr r2, [fp, #-8]
    ldr r3, [fp, #-12]
    add r3, r2, r3
    mov r0, r3
    sub sp, fp, #0
    @ sp needed
    ldr fp, [sp], #4
    bx  lr    
    .size   sum, .-sum    
    .section    .rodata
    .align  2
 .LC0:
    .ascii  "%d\012\000"
    .text
    .align  2
    .global main    .type   main, %functionmain:
    @ args = 0, pretend = 0, frame = 16
    @ frame_needed = 1, uses_anonymous_args = 0
    stmfd   sp!, {fp, lr}    add fp, sp, #4
    sub sp, sp, #16
    str r0, [fp, #-16]
    str r1, [fp, #-20]
    bl  sum(PLT)
    str r0, [fp, #-8]
    ldr r3, .L5.LPIC0:
    add r3, pc, r3
    mov r0, r3
    ldr r1, [fp, #-8]
    bl  printf(PLT)    mov r3, #0
    mov r0, r3
    sub sp, fp, #4
    @ sp needed
    ldmfd   sp!, {fp, pc}

Isn’t it similar?

Newbie: But what is the use of this?

Ximen Chui Xue: Writing a few small programs is just to familiarize oneself with some basic concepts of ASM, but for practical application, it still relies on information gathering and analysis.

Reply “1” in the public account to join the programmer group chat

Must-read 100 programming books for front-end developers

Download 300 classic programming books

Download 83 A-round and angel round financing plans

Download 1000G free programming teaching videos, all classics

Download 100 sets of WeChat mini-program source code

Essential for programmers!! Complete set of WeChat mini-program development tutorials

Follow the public account, ask the editor to send red envelopes

Running Hello World in Assembly Language on Android

Leave a Comment