汇编语言0x2c,ARM汇编语言(4) 指令、伪操作、伪指令学习
LDR指令与LDR伪指令的4种形式:
LDR R0,[R1]:指令,将R1指向的内存地址存放的内容加载到R0中;
LDR R0,LABEL:指令,将标号LABEL所代表的内存地址处存放的内容加载到R0中;
LDR R0,=10000:伪指令,将常熟10000赋予R0,采用LDR指令+文字池的方式实现;
LDR R0,=LABEL:伪指令,将标号LABEL所代表的内存地址赋予R0;
指令部分:
伪操作部分:
符号定义伪操作:定义变量,对变量进行赋值,定义寄存器名称
GBLA:全局的算术变量,初始化为0;
GBLL:全局的逻辑变量,初始化为{FALSE};
GBLS:全局的串变量,初始化为“”;
LCLA:局部的算术变量,初始化为0;
LCLL:局部的逻辑变量,初始化为{FALSE};
LCLS:局部的串变量,初始化为“”;
SETA:给算术变量赋值;
SETL:给逻辑变量赋值;
SETS:给串变量赋值;
RLIST:为一个通用寄存器列表定义名称;
CN:为一个协处理器的寄存器定义名称;
CP:为一个协处理器定义名称;
DN:为一个双精度的VFP寄存器定义名称;
SN:为一个单精度的VFP寄存器定义名称;
FN:为一个FPA浮点寄存器定义名称;
数据定义伪操作
LTORG:声明一个数据缓冲池的开始;
MAP:定义一个结构化的内存表的首地址,同义词为^;
FIELD:定义一个结构化内存表中的数据域,同义词#;
SPACE:分配一块内存单元,并用0初始化,同义词%;
{label} SPACE exprexpr表示分配的内存字节数;
DCB:分配一段字节内存单元,并用expr初始化之,同义词=;
{label} DCB expr, {expr}...expr是-128~255的数值或字符串;
DCD,DCDU:分配一段字内存单元,分配的内存都是字对齐的,并用expr初始化之,同义词&,DCDU分配的内存单元不严格字对齐;
DCDO:分配一段字内存单元,分配的内存都是字对齐的,并将每个字单元的内容初始化为expr标号基于静态基址寄存器R9的偏移量;
DCFD,DCFDU:
DCFS,DCFSU:
DCI:(ARM)分配一段字内存单元,分配的内存都是字对齐的,并用expr初始化;(Thumb)分配一段半字内存单元,分配的内存都是半字对齐的,并用expr初始化;
DCQ,DCQU:
DCW,DCWU:
汇编控制伪操作
IF,ELSE,ENDIF:根据条件将一段源代码包括在汇编语言程序中或者将其排除在程序之外;
IF logical expression
instructions or directives
ELSE
instructions or directives
ENDIF
WHILE,WEND:根据条件重复汇编相同的或者几乎相同的一段源代码;
WHILE logical expression
instructions or directives
WEND
MACRO,MEND:定义宏定义体;
MEXIT:从宏中跳转出去;
栈中数据帧描述伪操作;
信息报告伪操作;
其它伪操作:
CODE16,CODE32:
EQU:为数字常量,基于寄存器的值和程序中的标号定义一个字符名称,同义词*;
name EQU expr {, type}
AREA:
ENTRY:
END:
ALIGN:
EXPORT:
GLOBAL:
IMPORT:
EXTERN:
GET:
INCLUDE:
INCBIN:
KEEP:
NOFP:
REQUIRE:
REQUIRE8:
PRESERVE8:
RN:
ROUT:
伪指令部分:伪指令不是真正的指令,在汇编编译器对源程序进行汇编处理时被替换成对应的ARM或者Thumb指令;
ADR(小范围的地址读取伪指令):将基于PC的地址值或者基于寄存器的地址值读取到寄存器中;
ADR{cond} register, expr
expr是基于PC或者基于寄存器的地址表达式,取值范围如下:
地址值不是字对齐时,取值范围-255~255;
地址值是字对齐时,取值范围-1020~1020;
地址值是16字节对齐时,取值范围更大;
ADRL(中等范围的地址读取伪指令):将基于PC的地址值或者基于寄存器的地址值读取到寄存器中;
ADRL{cond} register, expr
expr是基于PC或者基于寄存器的地址表达式,取值范围如下:
地址不是字对齐时,-64KB~64KB;
地址是字对齐时,-256KB~256KB;
地址是16字节对齐时,取值范围更大;
LDR:将一个32位的常数或者一个地址值读取到寄存器中;
LDR{cond} register, ={expr | label-expr}
expr为32位常量;
label-expr为基于PC的地址表达式或者外部表达式;
NOP:汇编时被替换成ARM中的空操作;
实例程序:
1、
AREA LDR_Code, CODE, READONLY
ENTRY
LDR r0, =src
LDR r1, =dst
MOV r2, r0
MOV r3, r1
MOV r5, #100
LDR r6, =100
LDR r7, =999999
srcDCD 0, 1
;, 2, 3, 4, 5, 6, 7, 8, 9
dstDCD 0, 0
;, 0, 0, 0, 0, 0, 0, 0, 0
END
反汇编代码:
$a
LDR_Code
0x00000000: e59f0024 $... LDR r0,0x2c
0x00000004: e59f1024 $... LDR r1,0x30
0x00000008: e1a02000 . .. MOV r2,r0
0x0000000c: e1a03001 .0.. MOV r3,r1
0x00000010: e3a05064 dP.. MOV r5,#0x64
0x00000014: e3a06064 d`.. MOV r6,#0x64
0x00000018: e59f7014 .p.. LDR r7,0x34
src
$d
0x0000001c: 00000000 .... DCD 0
0x00000020: 00000001 .... DCD 1
dst
0x00000024: 00000000 .... DCD 0
0x00000028: 00000000 .... DCD 0
0x0000002c: 0000001c .... DCD 28
0x00000030: 00000024 $... DCD 36
0x00000034: 000f423f ?B.. DCD 999999
(1)为LDR伪指令生成的代码,似乎有问题,不是基于PC的值,还是有默认的规则?
使用GNU ARM Assembly将上面的代码重新实现一次:
.section .text
.global _start
_start:
LDR r0, =src
LDR r1, =dst
LDR r2, =1000
LDR r3, =5555
MOV r4, r2
MOV r5, r3
.section .data
src: .word 0, 0
dst: .word 0, 1
编译通过了,不确定代码有没有问题,后面再检查
将上面的代码使用arm-none-eabi-as编译不链接,然后使用arm-none-eabi-objdump反汇编:
Disassembly of section .text:
00000000 <_start>:
0: e59f0010 ldr r0, [pc, #16] ; 18 <_start>
4: e59f1010 ldr r1, [pc, #16] ; 1c <_start>
8: e3a02ffa mov r2, #1000 ; 0x3e8
c: e59f300c ldr r3, [pc, #12] ; 20 <_start>
10: e1a04002 mov r4, r2
14: e1a05003 mov r5, r3
18: 00000000 andeq r0, r0, r0
1c: 00000008 andeq r0, r0, r8
20: 000015b3 strheq r1, [r0], -r3
诚如文档中对LDR的介绍:
LDR r0, =src
LDR r1, =dst
LDR r2, =1000
LDR r3, =5555
这四条命令都进行了处理,以LDR r0, =src为例:
0: e59f0010 ldr r0, [pc, #16] ; 18 <_start>
src的值被存储,ldr指令将[pc, #16]地址中的值加载到寄存器r0中,
ARM处理器中,pc的值为当前执行的指令的地址值加上8,因此,执行该条
指令时,pc的值为8,此时pc加上16,则为十进制的24,十六进制的
0x18,但是此时地址单元0x18中存储的却是一条指令:
andeq r0, r0, r0
为什么?
将之前编译生成的.o文件使用arm-none-eabi-ld进行连接,生成可执行文件,
然后反汇编,此时代码变为:
Disassembly of section .text:
00008000 <_start>:
8000: e59f0010 ldr r0, [pc, #16] ; 8018 <_start>
8004: e59f1010 ldr r1, [pc, #16] ; 801c <_start>
8008: e3a02ffa mov r2, #1000 ; 0x3e8
800c: e59f300c ldr r3, [pc, #12] ; 8020 <_start>
8010: e1a04002 mov r4, r2
8014: e1a05003 mov r5, r3
8018: 00010024 andeq r0, r1, r4, lsr #32
801c: 0001002c andeq r0, r1, ip, lsr #32
8020: 000015b3 strheq r1, [r0], -r3
此时,src的值应该存放在0x8000 + 8 + 16,8和16都是十进制的,因此应该是0x8018,
但是0x8018地址单元中为:
andeq r0, r1, r4, lsr #32
lsr在上一篇寻址方式中有所介绍,此时r4中的值通过上面的指令可知为十进制的1000,十六进制的0x3E8,
0x3E8的二进制:
0000 0000 0000 0000 0000 0011 1110 1000,执行lsr #32操作,右移32位,则变为0,
r1中此时不管是什么值,AND指令执行按位取与操作,指令的执行结果自然是0,存放到r0寄存器中?
此处应该是个pool?为什么是指令?
(2)$a、$d分别表示什么意思?
摘录自:Using as ThegnuAssembler的Mapping Symbols章节
The ARM ELF specification requires that special symbols be inserted into object files to
mark certain features:
$a At the start of a region of code containing ARM instructions.
$t At the start of a region of code containing THUMB instructions.
$d At the start of a region of data.
待补充...
汇编语言0x2c,ARM汇编语言(4) 指令、伪操作、伪指令学习相关推荐
- 【Android 逆向】arm 汇编 ( 使用 IDA 解析 arm 架构的动态库文件 | 分析 malloc 函数的 arm 汇编语言 )
文章目录 一.分析 malloc 函数的 arm 汇编语言 一.分析 malloc 函数的 arm 汇编语言 在上一篇博客 [Android 逆向]arm 汇编 ( 使用 IDA 解析 arm 架构的 ...
- ARM汇编指令(ARM寻址方式、汇编指令、伪指令
1.寻址方式 所谓寻址方式就是:处理器根据指令中给出的地址信息来寻找物理地址的方法. 1)立即寻址 立即寻址也叫立即数寻址,这是一种特殊的寻址方式,操作数本身就是在指令中给出的. 只要取出指令也就是取 ...
- ARM汇编指令以及伪指令
文章目录 ARM寄存器 ARM指令的一般编码格式 ARM指令的条件域 ARM寻址方式 数据处理指令的操作数寻址方式 立即数寻址方式 寄存器寻址方式 寄存器移位寻址方式 字或无符号字节的Load/Sto ...
- ARM裸机开发篇3:ARM汇编语言程序设计
写在前面: 本文章为<ARM Cortex-A7裸机开发篇>系列中的一篇,全系列总计11篇.笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板). 针对FS-MP ...
- 树莓派ARM汇编语言编程十讲(第1讲)
内容简介 树莓派单板机(Raspberry Pi Single Computer)是一种极了不起的产品,用户可以以非常低的成本获得一个Linux环境并带GPIO硬件扩展的迷你计算机系统.新一代树莓派4 ...
- ARM汇编语言中的程序结构
在 ARM ( Thumb )汇编语言程序中,以程序段为单位组织代码.段是相对独立的指令或数据序列,具有特定的名称.段可以分为代码段和数据段,代码段的内容为执行代码,数据段存放代码运行时需要用到的数据 ...
- ARM 汇编语言入门
[翻译]二进制漏洞利用(二)ARM32位汇编下的TCP Bind shell:https://bbs.pediy.com/thread-253511.htm ARM汇编语言入门 From:ARM汇编语 ...
- 使用arm混合汇编计算两个64位的和_混合使用C、C++和汇编语之: C、C++ 和 ARM 汇编语言之间的调用...
12.4C' target='_blank' style='cursor:pointer;color:#D05C38;text-decoration:underline;'>C.C++和ARM汇 ...
- 汇编语言笔记10-CALL和RET指令
☞模块化程序设计 模块化程序设计 汇编语言通过call和ret指令实现了模块化程序设计.可以实现多个相互联系.功能独立的子程序来解决一个复杂的问题. 子程序的框架 1 assume cs:code 2 ...
最新文章
- 《Head First Java》的思考总结:第三篇
- 高德技术开放日 | 聊聊技术与成长那些事,大量实习岗、社招岗开放
- python字典append_python中字典重复赋值,append到list中引发的异常
- SpringAMQP+RabbitMQ调试中的问题解决
- Java------String DAte 转化
- 大数据流水线系统PiFlow v0.5
- QT网络编程TCP/UDP开发流程 制作网络调试助手
- 射击类游戏的制作思路
- 如何划分IP地址及范围
- AndroidStudio 个人总结的快捷键
- mysql 根据身份证号码更新性别
- SSM+Layui实现上传图片
- iOS代码实现布局(三)—用CocoaPods导入第三方库Masonry
- python 读取excel中单元格的内容
- 【Rust日报】2020-11-03 《Rust日报》总第1000期
- 关学生使用计算机心得,关于计算机课的心得体会范文
- 联想电脑chrome浏览器打开总是自动跳转到百度界面
- 大连海洋大学计算机调剂,2020年大连海洋大学硕士研究生调剂复试的通知
- 网课搜题公众号搭建 查题接口教程
- 【ArduPilot开发指南】目录