for(i = 0; i < 10; i ++)
这样的for 语句可能再基础不过,可是理解不清楚还是容易犯错误。
现在我用ARM 汇编指令分析一下这样的语句到底是怎么执行的(当你看C代码不知道代码到底是怎么执行的时候,要么查C标准,要么看熟悉的ARM 汇编)。
测试用例:
/*
============================================================================
Name : while.c
Author : qiang
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i = 0;
for(i = 0; i < 10; ++i) {
printf("i = %d \n", i);
}
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
return EXIT_SUCCESS;
}
编译成ARM 可执行文件,
$ android_native_gcc -o while -g while.c
这里我设置了bash alias,
alias android_native_gcc='arm-linux-androideabi-gcc --sysroot=/home/qiang/wrwork/android/android-ndk-r9/platforms/android-18/arch-arm'
还有务必加上 -g 调试选项,不然之后反汇编的时候即使再怎么加上 -S 选项,C语言的代码也出不来的。
反汇编:
$ arm-linux-androideabi-objdump -d -S while > while.S
下面就可以研究一下 ARM 汇编了:
while: file format elf32-littlearm
Disassembly of section .plt:
0000824c <__libc_init@plt-0x14>:
824c: e52de004 .word 0xe52de004
8250: e59fe004 .word 0xe59fe004
8254: e08fe00e .word 0xe08fe00e
8258: e5bef008 .word 0xe5bef008
825c: 00001d88 .word 0x00001d88
00008260 <__libc_init@plt>:
8260: e28fc600 .word 0xe28fc600
8264: e28cca01 .word 0xe28cca01
8268: e5bcfd88 .word 0xe5bcfd88
0000826c <__cxa_atexit@plt>:
826c: e28fc600 .word 0xe28fc600
8270: e28cca01 .word 0xe28cca01
8274: e5bcfd80 .word 0xe5bcfd80
00008278 <printf@plt>:
8278: e28fc600 .word 0xe28fc600
827c: e28cca01 .word 0xe28cca01
8280: e5bcfd78 .word 0xe5bcfd78
00008284 <puts@plt>:
8284: e28fc600 .word 0xe28fc600
8288: e28cca01 .word 0xe28cca01
828c: e5bcfd70 .word 0xe5bcfd70
Disassembly of section .text:
00008290 <_start>:
8290: e59fc05c ldr ip, [pc, #92] ; 82f4 <_start+0x64>
8294: e92d4800 push {fp, lr}
8298: e59f3058 ldr r3, [pc, #88] ; 82f8 <_start+0x68>
829c: e28db004 add fp, sp, #4
82a0: e24dd010 sub sp, sp, #16
82a4: e08fc00c add ip, pc, ip
82a8: e79c3003 ldr r3, [ip, r3]
82ac: e50b3014 str r3, [fp, #-20]
82b0: e59f3044 ldr r3, [pc, #68] ; 82fc <_start+0x6c>
82b4: e28b0004 add r0, fp, #4
82b8: e79c3003 ldr r3, [ip, r3]
82bc: e50b3010 str r3, [fp, #-16]
82c0: e59f3038 ldr r3, [pc, #56] ; 8300 <_start+0x70>
82c4: e3a01000 mov r1, #0
82c8: e79c3003 ldr r3, [ip, r3]
82cc: e50b300c str r3, [fp, #-12]
82d0: e59f302c ldr r3, [pc, #44] ; 8304 <_start+0x74>
82d4: e79c3003 ldr r3, [ip, r3]
82d8: e50b3008 str r3, [fp, #-8]
82dc: e59f3024 ldr r3, [pc, #36] ; 8308 <_start+0x78>
82e0: e79c2003 ldr r2, [ip, r3]
82e4: e24b3014 sub r3, fp, #20
82e8: ebffffdc bl 8260 <__libc_init@plt>
82ec: e24bd004 sub sp, fp, #4
82f0: e8bd8800 pop {fp, pc}
82f4: 00001d38 .word 0x00001d38
82f8: ffffffec .word 0xffffffec
82fc: fffffff0 .word 0xfffffff0
8300: fffffff4 .word 0xfffffff4
8304: fffffff8 .word 0xfffffff8
8308: fffffffc .word 0xfffffffc
0000830c <atexit>:
830c: e59f2008 ldr r2, [pc, #8] ; 831c <atexit+0x10>
8310: e3a01000 mov r1, #0
8314: e08f2002 add r2, pc, r2
8318: eaffffd3 b 826c <__cxa_atexit@plt>
831c: 00001ce4 .word 0x00001ce4
00008320 <main>:
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
8320: e92d4800 push {fp, lr}
8324: e28db004 add fp, sp, #4
8328: e24dd008 sub sp, sp, #8
int i = 0;
832c: e3a03000 mov r3, #0
8330: e50b3008 str r3, [fp, #-8]
for(i = 0; i < 10; ++i) {
8334: e3a03000 mov r3, #0
8338: e50b3008 str r3, [fp, #-8]
833c: ea000007 b 8360 <main+0x40>
printf("i = %d \n", i);
8340: e59f3044 ldr r3, [pc, #68] ; 838c <main+0x6c>
8344: e08f3003 add r3, pc, r3
8348: e1a00003 mov r0, r3
834c: e51b1008 ldr r1, [fp, #-8]
8350: ebffffc8 bl 8278 <printf@plt>
#include <stdlib.h>
int main(void) {
int i = 0;
for(i = 0; i < 10; ++i) {
8354: e51b3008 ldr r3, [fp, #-8]
8358: e2833001 add r3, r3, #1
835c: e50b3008 str r3, [fp, #-8]
8360: e51b3008 ldr r3, [fp, #-8]
8364: e3530009 cmp r3, #9
8368: dafffff4 ble 8340 <main+0x20>
printf("i = %d \n", i);
}
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
836c: e59f301c ldr r3, [pc, #28] ; 8390 <main+0x70>
8370: e08f3003 add r3, pc, r3
8374: e1a00003 mov r0, r3
8378: ebffffc1 bl 8284 <puts@plt>
return EXIT_SUCCESS;
837c: e3a03000 mov r3, #0
}
8380: e1a00003 mov r0, r3
8384: e24bd004 sub sp, fp, #4
8388: e8bd8800 pop {fp, pc}
838c: 00000060 .word 0x00000060
8390: 00000040 .word 0x00000040
ARM 指令记不清的话翻看一下 ARM+System+Developers+Guide-Designing+and+Optimizing+System+Software.pdf
其中, [Rd] 表示的是以 Rd 寄存器中的值为地址的memory 中的内容。
That's all ! Enjoy ARM assembly, Enjoy C !!!