arm反汇编.
- 格式:doc
- 大小:315.00 KB
- 文档页数:13
arm汇编与逆向工程蓝狐卷基础知识下载提示:该文档是本店铺精心编制而成的,希望大家下载后,能够帮助大家解决实际问题。
文档下载后可定制修改,请根据实际需要进行调整和使用,谢谢!本店铺为大家提供各种类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by this editor. I hope that after you download it, it can help you solve practical problems. The document can be customized and modified after downloading, please adjust and use it according to actual needs, thank you! In addition, this shop provides you with various types of practical materials, such as educational essays, diary appreciation, sentence excerpts, ancient poems, classic articles, topic composition, work summary, word parsing, copy excerpts, other materials and so on, want to know different data formats and writing methods, please pay attention!当然,请看下面的文章示例:ARM汇编与逆向工程基础知识。
ARM平台下的反汇编目的作为代码插桩过程的前提,首先需要对于所提供的二进制代码进行必要的分析,了解ELF文件的结构以及ARM平台的指令编码,将二进制01码翻译成为用户可读的汇编代码。
通过对于汇编代码的分析,用户可以得到程序应用中各个函数起始地址以及程序各个模块的流程调用等重要信息,为代码插桩提供详细的数据。
经过插桩的代码最后通过再一次汇编的过程输出到目标文件。
因此,正确、快速地进行平台下的反汇编工作显得十分关键。
ARM平台介绍[1-2]ARM(Advanced RISC Machines)是微处理器行业的一家知名企业,设计了大量高性能、廉价、耗能低的RISC(精简指令集计算机)处理器、相关技术及软件。
技术具有性能高、成本低和能耗低等特点。
经历过早期自己设计和制造芯片的不景气之后,公司自己开始不制造芯片,只将芯片的设计方案授权(licensing)给其他公司,由它们来生产,形成了较为独特的盈利模式。
RISC结构优先选取使用频率最高的简单指令,避免复杂指令;将指令长度固定,指令格式和寻地方式种类减少;以控制逻辑为主,不用或少用微码控制等。
ARM处理器在秉承RISC体系优点的基础上,进行了针对嵌入式系统的功能扩展,使得指令更加灵活,处理器性能在嵌入式平台上更加突出。
ARM微处理器的核心结构如下图所示:Figure 1.ARM处理器核心结构示意图[2]数据指令通过数据总线进入到处理器核心,然后在指令被执行之前经由指令解码器翻译。
和所有精简指令集处理器一样,ARM采用了load-store架构,load指令将数据从内存拷贝到寄存器,store指令将数据从寄存器转储到内存,所有的数据处理在寄存器中完成。
ARM处理器是32位的处理器,所有的指令默认将寄存器视为32位的值,因此Sign extend会在数据写入寄存器之前将所有8位或者12位的数值转换为32位的数值。
ARM指令通常有两个源寄存器: Rn, Rm 以及一个目标寄存器,操作数都是从寄存器通过内部总线读取得到。
为什么要反汇编?反汇编文件的生成和解读为什么要反(汇编)反汇编顾名思义就是汇编的逆过程,将二进制文件反汇编成汇编代码。
(arm)-(linux)-objdump是交叉编译工具链里的一个工具,专门用来反汇编的,将二进制代码反汇编成汇编代码来查看。
为什么要反汇编1.逆向破解。
将可执行程序反汇编得到汇编代码,再根据汇编代码推理出整个程序的逻辑。
这个不是一般人能做的,能看懂大量汇编语言写的程序都很困难了,更别说反推别人的代码逻辑。
2.调试程序时可以帮助我们理解并(检测)生成的可执行程序是否正常,尤其是在理解链接脚本和链接地址等概念时。
3.(C语言)的源代码编译链接生成的可执行文件再反汇编,可以帮助我们理解C语言和汇编语言的对应关系,有助于深入理解C 语言。
反汇编文件的生成和解读反汇编文件的生成:上面是一个简单的Makefile,功能是把源文件.S和.c先编译成.o 文件,再把.o文件链接成.elf的可执行文件。
arm-linux-objdump -D (led).elf > led_elf.dis是将led.elf反汇编成ed_elf.dis。
源文件:star.s是一个汇编文件star.s是一个学习S5PV210开发板时点亮LED的汇编程序,由开始、点亮、延时和死循环组成,在这里并不关注具体实现的功能,重点是和反汇编生成的文件进行对照。
得到的反汇编文件:led_elf.dis解析:1.第一行:led.elf: file f(or)mat elf32-littlearm。
表明此汇编程序是由led.elf生成,程序是32的小端模式。
2.00000000 :前面的00000000是标号的地址,是标号,对应start.s的_start标号。
其实标号就相当于C语言中的函数名,在C语言中也可以用函数名代表函数的首地址,在这里可以得到印证。
反汇编的标号就是由汇编文件得来的,这样可以方便我们找到反汇编文件和汇编文件对应的部分。
单片机反汇编单片机反汇编是指将单片机的机器码翻译成汇编代码的过程。
在程序调试或逆向工程中,反汇编技术是必不可少的。
本文将介绍单片机反汇编的基本原理和实际应用。
一、反汇编原理单片机的机器码是由指令和数据组成的二进制代码。
指令是CPU执行的基本操作,例如数据传输、算术运算、逻辑运算等。
不同的单片机芯片有不同的指令集,但它们都遵循一定的规则,例如指令的长度和格式。
在反汇编过程中,我们需要根据这些规则将机器码解析成汇编指令。
二、反汇编工具反汇编工具有很多种,例如IDA Pro、OllyDbg、Ghidra等。
这些工具可以自动将机器码翻译成汇编指令,并提供调试和逆向分析的功能。
不同的工具有不同的特点和优缺点,选择适合自己的工具是非常重要的。
三、反汇编实例以下是一个简单的反汇编实例,以AT89S52单片机为例。
假设我们要反汇编一个简单的LED闪烁程序。
78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0 78 F0 90 F0MOV P1,#0xFFL1: ACALL DELAYCPL P1.0SJMP L1解析:第一条指令MOV P1,#0xFF是将0xFF赋值给P1寄存器,即将P1所有引脚都输出高电平,点亮LED灯。
反编译初识⼀. 反编译(反汇编)简介 1.1. 为什么要反编译(汇编 assembly 反汇编 dissembly) 1.1.1. 反编译原因如下: a. 逆向破解程序,作为⼀个有逼格,素养的我肯定不会这么⼲的。
哈哈 b. 调试程序时,反汇编代码可以帮助我们理解程序(我们学习时使⽤objdump主要⽬的是这个),尤其是在理解链接脚本、链接地址等概念时 c. 把C语⾔源代码编译链接⽣成的可执⾏程序反汇编后得到对应的汇编代码,可以帮助我们理解C语⾔和汇编语⾔之间的对应关系。
⾮常有助于深⼊理解C语⾔。
1.2. 反编译命令 1.2.1. arm-linux-objdump -D led.elf > led_elf.dis 命令 a. objdump是gcc⼯具链中的反汇编⼯具,作⽤是由编译链接好的elf格式的可执⾏程序反过来得到汇编源代码 b. -D表⽰反汇编 1.2.1. 获得反编译⽂件过程 a. 此过程是基于上篇⽂章《》,前期准备参考此⽂章 b. 反编译后⽣成led_elf.disroot@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.4.13-LED# lsled.S Makefile mkv210_image.c write2sd 说明.txtroot@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.4.13-LED# makearm-linux-gcc -o led.o led.S -carm-linux-ld -Ttext 0x0 -o led.elf led.oarm-linux-objcopy -O binary led.elf led.binarm-linux-objdump -D led.elf > led_elf.disgcc mkv210_image.c -o mkx210./mkx210 led.bin 210.binroot@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.4.13-LED# ls210.bin led.elf led.o Makefile mkx210 说明.txtled.bin led_elf.dis led.S mkv210_image.c write2sdroot@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.4.13-LED#View Code 1.3. 反编译⽂件led_elf.dis分析 1.3.1. 我们选取⼀段分析 00000000 <_start>:0: e59f1060 ldr r1, [pc, #96] ; 68 <delay_loop+0x10> a. 00000000 <_start>: 表⽰标号地址、标号名字 b. 0: e59f1060表⽰指令地址、指令机器码 c. ldr r1, [pc, #96]表⽰指令机器码反汇编到的指令,由于有流⽔线的存在,此时PC值是当初指令地址+9; d. 68 <delay_loop+0x10>表⽰注释;0x68 = 96+8led.elf: file format elf32-littlearmDisassembly of section .text:00000000 <_start>:0: e59f1060 ldr r1, [pc, #96] ; 68 <delay_loop+0x10>4: e59f0060 ldr r0, [pc, #96] ; 6c <delay_loop+0x14>8: e5810000 str r0, [r1]0000000c <while>:c: e59f105c ldr r1, [pc, #92] ; 70 <delay_loop+0x18>10: e3e00008 mvn r0, #814: e5810000 str r0, [r1]18: eb00000c bl 50 <delay>1c: e59f104c ldr r1, [pc, #76] ; 70 <delay_loop+0x18> 20: e3e00010 mvn r0, #1624: e5810000 str r0, [r1]28: eb000008 bl 50 <delay>2c: e59f103c ldr r1, [pc, #60] ; 70 <delay_loop+0x18> 30: e3e00020 mvn r0, #3234: e5810000 str r0, [r1]38: eb000004 bl 50 <delay>3c: e59f102c ldr r1, [pc, #44] ; 70 <delay_loop+0x18> 40: e3e00010 mvn r0, #1644: e5810000 str r0, [r1]48: eb000000 bl 50 <delay>4c: eaffffee b c <while>00000050 <delay>:50: e59f201c ldr r2, [pc, #28] ; 74 <delay_loop+0x1c> 54: e3a03000 mov r3, #000000058 <delay_loop>:58: e2422001 sub r2, r2, #15c: e1520003 cmp r2, r360: 1afffffc bne 58 <delay_loop>64: e1a0f00e mov pc, lr68: e0200240 eor r0, r0, r0, asr #46c: 00111000 andseq r1, r1, r070: e0200244 eor r0, r0, r4, asr #474: 00895440 addeq r5, r9, r0, asr #8Disassembly of section .ARM.attributes:00000000 <.ARM.attributes>:0: 00001a41 andeq r1, r0, r1, asr #204: 61656100 cmnvs r5, r0, lsl #28: 01006962 tsteq r0, r2, ror #18c: 00000010 andeq r0, r0, r0, lsl r010: 45543505 ldrbmi r3, [r4, #-1285] ; 0x50514: 08040600 stmdaeq r4, {r9, sl}18: Address 0x00000018is out of bounds.View Code参考《朱⽼师.1.2ARM裸机课件》。
arm 汇编指令ARM汇编指令是一种用于编写ARM处理器程序的语言。
ARM处理器广泛应用于嵌入式系统和移动设备等领域。
ARM汇编指令与x86汇编指令有所不同,它基于RISC(精简指令集计算机)架构。
下面是一些基本的ARM汇编指令:1. 数据传输指令:用于在寄存器之间传输数据。
例如:- mov:将数据从一个寄存器传输到另一个寄存器。
- ldr:将数据从内存传输到寄存器。
2. 算术指令:用于执行加法、减法、乘法和除法等操作。
例如:- add:加法操作。
- sub:减法操作。
- mull:乘法操作。
- div:除法操作。
3. 逻辑指令:用于执行逻辑操作,如与、或、非等。
例如:- and:与操作。
- or:或操作。
- xor:异或操作。
4. 移位指令:用于对数据进行左移、右移或无符号右移。
例如:- lsr:无符号右移。
- asr:带符号右移。
- ror:循环右移。
5. 比较指令:用于比较两个寄存器的值。
例如:- cmp:比较两个寄存器的值,若相等则返回0,否则返回1。
6. 跳转指令:用于改变程序的执行流程。
例如:- b:条件跳转。
- bl:无条件跳转。
- bx:带状态跳转。
7. 循环指令:用于实现循环操作。
例如:- loop:内部循环。
- ldp:外部循环。
8. 调用指令:用于实现函数调用。
例如:- blx:带状态调用。
- bx:不带状态调用。
9. 系统调用指令:用于实现与操作系统交互的功能。
例如:- swi:执行系统调用。
10. 存储器访问指令:用于访问内存数据。
例如:- str:将数据存储到内存。
- ldr:从内存中加载数据。
以上仅为ARM汇编指令的一部分,实际上,ARM汇编指令还有很多其他功能。
为了更好地理解和使用ARM汇编指令,可以参考相关的教程和手册,并进行实际操作。
ARM的BIN文件反汇编方法
最近在调试uboot的代码时,用的新版本的uboot,lowlevel_init函数里是空的,而且在链接文件中也没有发现对lowlevel_init.o的链接。
在bl lowlevel_init 之前和之中加了两个电灯,发现在bl之后的部分并没有被执行,所以想看看具体程序有没有运行这个函数。
在网上找反汇编bin文件的时候发现有朋友提供的方法,很好用。
使用arm-linux 工具链里面的arm-linux-objdump 就能反汇编
cd到bin文件所在的目录,在命令行下输入:
arm-linux-objdump -D -b binary -m arm xxx.bin > xxx.asm
参数:
-D 反编译所有代码
-m 主机类型, arm
-b 文件格式, binary
对于ELF格式的文件只要一个-D参数即可
就可以把xxx.bin反汇编到xxx.asm文件。
反汇编调试内核驱动Oops提⽰【转】反汇编调试内核驱动arm-none-linux-gnueabi-objdump -S kmod-demo1.o > a.txt什么是Oops?从语⾔学的⾓度说,Oops应该是⼀个拟声词。
当出了点⼩事故,或者做了⽐较尴尬的事之后,你可以说"Oops",翻译成中国话就叫做“哎呦”。
“哎呦,对不起,对不起,我真不是故意打碎您的杯⼦的”。
看,Oops就是这个意思。
在Linux内核开发中的Oops是什么呢?其实,它和上⾯的解释也没什么本质的差别,只不过说话的主⾓变成了Linux。
当某些⽐较致命的问题出现时,我们的Linux内核也会抱歉的对我们说:“哎呦(Oops),对不起,我把事情搞砸了”。
Linux内核在发⽣kernel panic时会打印出Oops信息,把⽬前的寄存器状态、堆栈内容、以及完整的Call trace都show给我们看,这样就可以帮助我们定位错误。
下⾯,我们来看⼀个实例。
为了突出本⽂的主⾓--Oops,这个例⼦唯⼀的作⽤就是造⼀个空指针引⽤错误。
#include <linux/kernel.h>#include <linux/module.h>static int__init hello_init(void){int*p = 0;*p = 1;return0;}static void__exit hello_exit(void){return;}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");很明显,错误的地⽅就是第8⾏。
接下来,我们把这个模块编译出来,再⽤insmod来插⼊到内核空间,正如我们预期的那样,Oops出现了。
[ 100.243737] BUG: unable to handle kernel NULL pointer dereference at (null)[ 100.244985] IP: [<f82d2005>] hello_init+0x5/0x11 [hello][ 100.262266] *pde = 00000000[ 100.288395] Oops: 0002 [#1] SMP[ 100.305468] last sysfs file: /sys/devices/virtual/sound/timer/uevent[ 100.325955] Modules linked in: hello(+) vmblock vsock vmmemctl vmhgfs acpiphp snd_ens1371 gameport snd_ac97_codec ac97_bus snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidisnd_seq_midi_event snd_seq snd_timer snd_seq_device ppdev psmouse serio_raw fbcon tileblit font bitblit softcursor sndparport_pc soundcore snd_page_alloc vmci i2c_piix4 vga16fb vgastate intel_agp agpgart shpchp lp parport floppy pcnet32 mii mptspi mptscsih mptbase scsi_transport_spi vmxnet[ 100.472178] [ 100.494931] Pid: 1586, comm: insmod Not tainted (2.6.32-21-generic #32-Ubuntu) VMware Virtual Platform[ 100.540018] EIP: 0060:[<f82d2005>] EFLAGS: 00010246 CPU: 0[ 100.562844] EIP is at hello_init+0x5/0x11 [hello][ 100.584351] EAX: 00000000 EBX: fffffffc ECX: f82cf040 EDX: 00000001[ 100.609358] ESI: f82cf040 EDI: 00000000 EBP: f1b9ff5c ESP: f1b9ff5c[ 100.631467] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068[ 100.657664] Process insmod (pid: 1586, ti=f1b9e000 task=f137b340 task.ti=f1b9e000)[ 100.706083] Stack:[ 100.731783] f1b9ff88 c0101131 f82cf040 c076d240 fffffffc f82cf040 0072cff4 f82d2000[ 100.759324] <0> fffffffc f82cf040 0072cff4 f1b9ffac c0182340 f19638f8 f137b340 f19638c0[ 100.811396] <0> 00000004 09cc9018 09cc9018 00020000 f1b9e000 c01033ec 09cc9018 00015324[ 100.891922] Call Trace:[ 100.916257] [<c0101131>] ? do_one_initcall+0x31/0x190[ 100.943670] [<f82d2000>] ? hello_init+0x0/0x11 [hello][ 100.970905] [<c0182340>] ? sys_init_module+0xb0/0x210[ 100.995542] [<c01033ec>] ? syscall_call+0x7/0xb[ 101.024087] Code: <c7> 05 00 00 00 00 01 00 00 00 5d c3 00 00 00 00 00 00 00 00 00 00[ 101.079592] EIP: [<f82d2005>] hello_init+0x5/0x11 [hello] SS:ESP 0068:f1b9ff5c[ 101.134682] CR2: 0000000000000000[ 101.158929] ---[ end trace e294b69a66d752cb ]---Oops⾸先描述了这是⼀个什么样的bug,然后指出了发⽣bug的位置,即“IP: [<f82d2005>] hello_init+0x5/0x11 [hello]”。
ARM 内核寄存器和基本汇编语言讲解•一、ARM内核寄存器▪ 1.1 M3/M4内核寄存器▪ 1.2 A7内核寄存器▪ 1.3 ARM中的PC指针的值•二、ARM汇编语言▪ 2.1 ARM汇编基础▪ 2.2 汇编伪指令▪ 2.3 ARM汇编指令集•三、代码反汇编简析▪ 3.1 不同编译器的反汇编▪ 3.2 C 和汇编比较分析开头直接来看几个简单的汇编指令:MOV R0,R1MOV PC,R14上面的指令中使用了汇编MOV指令,但是其中的R0,R1,R14,PC分别是什么?哪来的?怎么用?要讲ARM 汇编语言,必须得先了解ARM的内核寄存器,内核处理所有的指令计算,都需要用到内核寄存器,所以ARM汇编里面指令大都是基于寄存器的操作。
文章前推荐韦东山老师的单片机核心视频,视频可以在韦东山老师官网里面找到:百问网ARM版本简单介绍:对于M3/M4而言:R13,栈指针(Stack Pointer)•R13寄存器中存放的是栈顶指针,M3/M4 的栈是向下生长的,入栈的时候地址是往下减少的。
•裸机程序不会用到PSP,只用到MSP,需要运行RTOS的时候才会用到PSP。
•堆栈主要是通过POP,PUSH指令来进行操作。
在执行PUSH 和 POP 操作时, SP 的地址寄存器,会自动调整。
R14 ,连接寄存器(Link Register)•LR 用于在调用子程序时存储返回地址。
例如,在使用BL(分支并连接,Branch and Link)指令时,就自动填充 LR 的值(执行函数调用的下一指令),进而在函数退出时,正确返回并执行下一指令。
如果函数中又调用了其他函数,那么LR将会被覆盖,所以需要先将LR寄存器入栈。
•保存子程序返回地址。
使用BL或BLX时,跳转指令自动把返回地址放入r14中;子程序通过把r14复制到PC来实现返回•当异常发生时,异常模式的r14用来保存异常返回地址,将r14如栈可以处理嵌套中断R15,程序计数器(Program Count)•在Cortex-M3中指令是3级流水线,出于对Thumb代码的兼容的考虑,读取pc时,会返回当前指令地址+4的值。
在bin文件中,就是一条条的机器指令,每条指令4个字节。
在ADS中打开一个.s文件,选择project->disassemble可以看到汇编的机器码汇编代码如下(ADS中的一个例程\ARM\ADSv1_2\Examples\asm\armex.s):AREA ARMex, CODE, READONL Y ; name this block of codeENTRY ; mark first instruction; to executestartMOV r0, #10 ; Set up parametersMOV r1, #3ADD r0, r0, r1 ; r0 = r0 + r1stopMOV r0, #0x18 ; angel_SWIreason_ReportExceptionLDR r1, =0x20026 ; ADP_Stopped_ApplicationExitSWI 0x123456 ; ARM semihosting SWIEND ; Mark end of file执行project->disassemble后:** Section #1 'ARMex' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR + SHF_ENTRYSECT] Size : 28 bytes (alignment 4)start$aARMex0x00000000: e3a0000a .... MOV r0,#0xa0x00000004: e3a01003 .... MOV r1,#30x00000008: e0800001 .... ADD r0,r0,r1stop0x0000000c: e3a00018 .... MOV r0,#0x180x00000010: e59f1000 .... LDR r1,0x180x00000014: ef123456 V4.. SWI 0x123456$d0x00000018: 00020026 &... DCD 131110使用UltraEdit看bin文件如下:可以看到,与上面的一样。
其中MOV的机器码如下(ARM体系结构pdf:p156):cond,AL(Always)为0b1110最后有一个131110不知道是什么意思。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 另一个例子汇编代码如下(ADS中的一个例程\ARM\ADSv1_2\Examples\asm\ subrout.s):AREA subrout, CODE, READONL Y ; name this block of codeENTRY ; mark first instruction; to executestartMOV r0, #10 ; Set up parametersMOV r1, #3BL doadd ; Call subroutinestopMOV r0, #0x18 ; angel_SWIreason_ReportExceptionLDR r1, =0x20026 ; ADP_Stopped_ApplicationExitSWI 0x123456 ; ARM semihosting SWIdoaddADD r0, r0, r1 ; Subroutine codeMOV pc, lr ; Return from subroutine.END ; Mark end of file执行project->disassemble后:** Section #1 'subrout' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR + SHF_ENTRYSECT] Size : 36 bytes (alignment 4)start$asubrout0x00000000: e3a0000a .... MOV r0,#0xa0x00000004: e3a01003 .... MOV r1,#30x00000008: ebfffffe .... BL doadd ; 0x18stop0x0000000c: e3a00018 .... MOV r0,#0x180x00000010: e59f1008 .... LDR r1,0x200x00000014: ef123456 V4.. SWI 0x123456doadd0x00000018: e0800001 .... ADD r0,r0,r10x0000001c: e1a0f00e .... MOV pc,r14$d0x00000020: 00020026 &... DCD 131110使用UltraEdit看bin文件如下:不知道为什么,ADS里面的BL doadd的机器码和bin中的机器码不一样。
BL的机器指令如下:0x00000008: ebfffffe .... BL doadd ; 0x18按bin中的机器码,EB000002,1110_1101_0000_0000____0000_0000_0000_0010会在执行bl指令时的PC后面加上2*4byte,正好跳过3条指令。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 下面这个例子将doadd写到另一个.s文件中。
subrout.s文件:AREA subrout, CODE, READONL Y ; name this block of codeENTRY ; mark first instruction; to executeIMPORT doadd ; importstartMOV r0, #10 ; Set up parametersMOV r1, #3BL doadd ; Call subroutinestopMOV r0, #0x18 ; angel_SWIreason_ReportExceptionLDR r1, =0x20026 ; ADP_Stopped_ApplicationExitSWI 0x123456 ; ARM semihosting SWIEND ; Mark end of filefun.s文件:AREA subrout, CODE, READONL Y ; name this block of codeEXPORT doadddoadd FUNCTIONADD r0, r0, r1 ; Subroutine codeMOV pc, lr ; Return from subroutine.ENDFUNCLTORGENDUE查看bin结果:可以看出,跳转指令变为跳转3个指令,doadd函数放在了bin的最后。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 这个例子将上面的subrout.s文件改为(工程subroutprj_2F_DCD):AREA subrout, CODE, READONL Y ; name this block of codeENTRY ; mark first instruction; to executeIMPORT doadd ; importstartLDR r0, Param1 ; Set up parametersLDR r1, Param2BL doadd ; Call subroutinestopMOV r0, #0x18 ; angel_SWIreason_ReportExceptionLDR r1, =0x20026 ; ADP_Stopped_ApplicationExitSWI 0x123456 ; ARM semihosting SWIParam1 DCD 10Param2 DCD 3END ; Mark end of fileMOV只能操作reg和立即数操作内存,MOV要改为LDRUE查看bin为:LDR r0, Param1的机器码为:E59F0010=0111_0101_1001_1111_0000_0000_0001_0000Rn为R15=PC,Rd=R0,address=16(4*Instruction)+PC输出的Image Symbol Table为:================================================================================Image Symbol TableMapping SymbolsSym Value Execution Region$a 0x00000000 ER_RO$d 0x00000020 ER_RO其中$a表示ARM Code,$d表示Data这是整个bin文件的区域分配,从0开始为ARM Code,然后从20开始为Data,其中ARM Code是fun section 和subrout section合在一起的,Data也是两个数据合在一起的(似乎是armlink把input section中同一属性的段合并到output section中)。
ADS中输出调试信息Image MapSymbolSection cross-reference在list file中choose一个文件,比如boot270.txt,可以把信息输出到txt中下面这个输出是subroutprj_2F_DCD的输出,在arm反汇编.doc里。
================================================================================Image Symbol TableMapping SymbolsSym Value Execution Region$a 0x00000000 ER_RO$d 0x00000020 ER_ROLocal SymbolsSymbol Name Value Ov Type Size Object(Section)E:\dsparm\pxa270\project\subroutprj_2F_DCD\subrout.s 0x00000000 Number 0 subrout.o ABSOLUTE<Anonymous Symbol> 0x00000000 Data 16 subrout.o(.debug_abbrev) <Anonymous Symbol> 0x00000000 Data 128 subrout.o(.debug_info) <Anonymous Symbol> 0x00000000 Data 108 subrout.o(.debug_line) subrout0x00000008 ARM Code 36 subrout.o(subrout)start0x00000008 ARM Code 0 subrout.o(subrout)stop0x00000014 ARM Code 0 subrout.o(subrout)Param10x00000020 Data 4 subrout.o(subrout)Param20x00000024 Data 4 subrout.o(subrout)E:\dsparm\pxa270\project\subroutprj_2F_DCD\fun.s 0x00000000 Number 0 fun.o ABSOLUTE<Anonymous Symbol> 0x00000000 Data 60 fun.o(.debug_frame) <Anonymous Symbol> 0x00000010 Data 16 fun.o(.debug_abbrev) fun0x00000000 ARM Code 8 fun.o(fun)<Anonymous Symbol> 0x0000006c Data 96 fun.o(.debug_line)<Anonymous Symbol> 0x00000080 Data 124 fun.o(.debug_info)Global SymbolsSymbol Name Value Ov Type Size Object(Section)BuildAttributes$$ARM_ISAv4$M$PE$A:L22$X:L11$S22$~IW$~STKCKD$~SHL$OSPACE 0x00000000 Number 0 anon$$obj.o ABSOLUTEdoadd0x00000000 ARM Code 8 fun.o(fun)UE查看bin结果从bin看到,doadd两条指令放在了bin的最前面,这样start的值value为0x00000008fun的值value为0x00000000start和fun都是ARM Code,是代码的标号label,标号的值代表一个地址,所以start和fun在bin 中的地址即为它们的值。