我们都熟悉计算机和PC内的程序和处理流程,这么手机的流程呢?一些app开发的人可能熟悉了,然而其他人可能对此知之颇多,本文中虫虫代理你们借助一个简单的安卓实例来探求安卓中应用的处理流程。出于研究目的我们没有使用联通开发的常用的AndroidStudio和Java语言,而是使用了底层的汇编语言。
Hello,Android!
问题始于,某个开发群,有人的随口一个问题:智能手机怎样工作的?上面有哪些?
我们借助一个安卓设备GalaxyS6Edge,该机基于ARM构架(大多数智能手机都是基于ARMCPU这和常见的基于X86平台PC或则服务器不一样)。我们就以他为例,实现一个汇编版本的"Hello,World"简单程序,并让它在该设备商跑上去。
.text
.globl_start
_start:
mov%r0,$1//filedescriptornumber1(stdout)
ldr%r1,=message
mov%r2,$message_len
mov%r7,$4//syscall4(write)
swi$0
mov%r0,$0//exitstatus0(ok)
mov%r7,$1//syscall1(exit)
swi$0
.data
message:
.ascii"Hello,WorldChongchongn"
message_len=.–message
假如你之前未曾见过汇编代码,这么这个程序可不好理解,但不要担忧,跟随我们一起进行就好了。
程序解释
程序分为两部份:.text部份:包含机器代码指令。
.data部份:从第15行开始,包含变量,字符串和其他数据。.text部份一般是只读的,而.data部份支持写入。
在第2行中android 安装linux软件,我们定义了一个名为_start的全局函数。这是该工程的注入点。操作系统将从这一点开始运行代码。该函数的实际定义在第4行。函数有两个功能:第5-9行将消息复印到屏幕,第11-13行中止程序。实际上11-13行可以省略掉,这时侯程序将字符串复印"Hello,WorldChongChong"并退出,但退出时侯可能会崩溃企图执行一些随机无效的指令,它正好是显存中的下一个。
复印消息(r0,r1,r2寄存器和swi)
通过调用系统调用来复印到屏幕。系统调用是操作系统提供的功能。本程序中我们调用了write()系统调用,通过将值4形参给名为r7(第8行)的CPU寄存器中来指示,之后执行"swi$0"指令(第9行),该指令直接调用在Android内部运行的Linux内核。
系统调用的参数通过其他寄存器传递:r0表示我们要复印的文件描述符的编号。我们给他形参为1(第5行),这个我们都熟悉鸟哥的linux私房菜,标号为1的文件描述符实际上就是stdout,标准输出,这样就功能在屏幕上复印。
r1表示我们要载入的数据的显存地址,因而我们给它形参为"Hello,WorldChongChong"字符串的地址(第6行)。r2告诉Android我们要写入多少字节。我们将其设置为message_len(第7行)的值,该值在第18行使用特殊的句型估算:点符号表示当前的显存地址,因而".-message"表示当前显存地址除以message的地址。这就估算了message的厚度。其实,第5-9行中的代码相当于以下c代码:
#definemessage"Hello,WorldChongChongn"
write(1,message,sizeof(message));
结束程序(r0,r7)
结束程序要简单得多,我们只须要将退出代码形参给r0(第11行),之后我们将值1(即exit()系统调用的值)形参给r7(第12行),而且再度调用内核(第13行)。
假如有兴趣,你可以参考在安卓源代码中相关的Android系统调用列表及其编号。你也可以在哪里找到write()和exit()函数的实现,它们调用相应的系统调用,如同我们一样。
编译源码
为了编译汇编程序,你须要AndroidNDK,即NativeDevelopmentKit,它包含一组用于ARM平台的编译器和重构工具。你可以直接从官方网站下载,也可以通过AndroidStudio安装:
转入"SDK工具"并选中"NDK",之后单击"确定"。另请注意AndroidSDK位置
获得NDK后,你须要搜索一个名为arm-linux-androideabi-as的文件,它是ARM平台的汇编程序。假如你是通过AndroidStudio下载的,请在AndroidSDK位置内查找。在我的机器上,它坐落:
ndk-bundletoolchainsarm-linux-androideabi-4.9prebuiltwindows-x86_64bin
依照不同的NDK版本和操作系统该路径会略有变化,依照实际环境选择。该文件外置了ARM汇编程序。
将源代码保存为hello.s的文件。之后运行以下命令将编译为机器代码:
arm-linux-androideabi-as-ohello.ohello.s
以上命令会创建一个名为hello.o的可执行文件。
之后再通过调用链接器将其转换为可在你的设备上运行的ELF二补码文件:
arm-linux-androideabi-ld-ohellohello.o
你如今有一个名为hello的文件,其中包含你的程序,可以运行。
运行程序
安卓应用程序一般以APK格式分发。这是一种特殊的ZIP文件,安卓希望以特定的形式建立android 安装linux软件,而且应当包含Java类(你可以使用本机C/C++或则其他语言编撰具体的应用代码,但入口点始终必须是是Java)。
为了便捷运行我们的应用程序,我们使用adb将其复制到她的Android设备的临时文件夹,之后使用adbshell运行应用程序并查看输出:
adbpushhello/data/local/tmp/hello
adbshellchmod+x/data/local/tmp/hello
最后,运行应用程序:
adbshell/data/local/tmp/hello
HelloWorldChongchon
总结
为安卓设备编撰汇编代码是熟悉ARM体系结构的好方式,帮我们了解每天使用的APP是怎样运行linux vi,及其底层的工作原理,我以前在先前的文章和回答中回答过汇编作为一个必需要技能,我们何必需要精通而且每位人都须要学习一点,这样有助于我们了解计算机体系结果和底层的运行原理。