‘Hello World!’ in ARM assembly
来源:互联网 发布:数据库实例不可用 编辑:程序博客网 时间:2024/04/28 10:42
‘Hello World!’ in ARM assembly
14. January 2012 22:29Over 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 theAndroid 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 givenhere. 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 detailhere. In contrast, the ARM ‘EABI’ calling convention uses a different method which is described vaguely inthese 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):
.datamsg: .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):
arm-linux-androideabi-as -o hello.o hello.Sarm-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:
adb push hello /data/local/tmp/helloadb shell /data/local/tmp/hello
It is also possible to run the binary locally on your device using the Android Terminal Emulator, as below:
Enjoy!
http://peterdn.com/post/e28098Hello-World!e28099-in-ARM-assembly.aspx
another version:
.syntax unified @ -------------------------------- .global main main: @ Stack the return address (lr) in addition to a dummy register (ip) to @ keep the stack 8-byte aligned. push {ip, lr} @ Load the argument and perform the call. This is like 'printf("...")' in C. ldr r0, =message bl printf @ Exit from 'main'. This is like 'return 0' in C. mov r0, #0 @ Return 0. @ Pop the dummy ip to reverse our alignment fix, and pop the original lr @ value directly into pc — the Program Counter — to return. pop {ip, pc} @ -------------------------------- @ Data for the printf calls. The GNU assembler's ".asciz" directive @ automatically adds a NULL character termination. message: .asciz "Hello, world.\n"The GNU assembler uses a different line-comment delimiter for each platform. On ARM, it is
@
. The GNU assembler also allows the use of C-style multi-line comments (such as "/* ... */
").http://community.arm.com/groups/processors/blog/2010/02/11/hello-world-in-assembly
- ‘Hello World!’ in ARM assembly
- ‘Hello World!’ in ARM assembly
- Linux Assembly "Hello World" Tutorial, CS 200
- Hello world in Java
- Hello World in ODE
- Hello Gtk+ in Linux Assembly Language
- Hello World(Java) in Eclipse
- Hello World(C++) in Eclipse
- puts "Hello world" in VC++
- Hello World in D Language
- 一 Hello World in ABAP
- Hello world in a container
- Eclipse Plug-in Hello world
- ARM assembly in Android Apps(1)
- linux arm programming in assembly language
- ARM开发板上的Hello World
- 一个Hello World的Arm汇编指令
- arm assembly
- Web.xml需要配置的代码
- 如何通过xcode编程使MAC机器和HID的USB单片机设备进行通讯
- kill命令
- 从协方差矩阵到PCA
- 冒泡排序
- ‘Hello World!’ in ARM assembly
- ldconfig
- DVS/DVR区别
- 音乐播放器
- WSAStartup与WSACleanup
- android解决三星手机拍照获取图片的问题
- EditText杂知识
- smartforms 我见
- SpringMVC+Maven的配置。