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+0x18>
4: e59f1010 ldr r1, [pc, #16] ; 1c <_start+0x1c>
8: e3a02ffa mov r2, #1000 ; 0x3e8
c: e59f300c ldr r3, [pc, #12] ; 20 <_start+0x20>
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+0x18>
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+0x18>
8004: e59f1010 ldr r1, [pc, #16] ; 801c <_start+0x1c>
8008: e3a02ffa mov r2, #1000 ; 0x3e8
800c: e59f300c ldr r3, [pc, #12] ; 8020 <_start+0x20>
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 asThegnuAssembler的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.
待弥补…