Download presentation
Presentation is loading. Please wait.
1
Lecture 03: Cortex M3存储系统访问
Refer to Chapter 5 in the reference book “ARM Cortex-M3权威指南”
2
内容 Cortex-M3存储器的分类 ARM的存储结构及存储方式 存储器操作数及变量 操作数的寻址方式 Cortex-M3存储器访问指令 栈操作
3
Cortex-M3存储器的分类 在系统中的地位 存储介质 信息存取方式 主存储器 辅助存储器
主存储器 辅助存储器 存储介质 磁存储器 半导体集成电路存储器 光存储器 激光光盘存储器 信息存取方式 随机存取存储器(RAM) 只读存储器(ROM)
4
ARM存储结构及存储方式 ARM支持以下6种数据类型: 8位有符号和无符号字节(Byte)。 16位有符号和无符号半字(Halfword)
它们必须以两字节的边界对齐(半字对齐)。 32位有符号和无符号字(word) 它们必须以4字节的边界对齐(字对齐)。 字对齐:字单元地址的低两位 A1A0=0b00。即地址末位为0x0, 0x4, 0x8, 0xc。 半字对齐:半字单元地址的最低位 A0=0b0 (地址末位为0x0,0x2,0x4,0x6,0x8,0xa,0xc,0xe)。
5
ARM存储结构及存储方式 一个字由四个字节组成,如果要说明一个字存储的地址,则是指这个字存储的最低的地址单元的地址,即一个字存储地址是A,则实际它占用的存储单元地址是A,A+1,A+2,A+3四个单元,一个半字(2个字节)占用的地址是A,A+1两个单元,若是一个字节,占用的地址是A的一个单元。 例如,地址0x (8位十六进制数)中存放的是一个字节的数据,0x 、0x 、0x 、0x 四个存储单元中存放的是一个字数据。
6
ARM存储结构及存储方式
7
字对齐 ARM的每个地址是对应于一个存储字节而不是一个存储字,但ARM可以访问存储字,访问存储字时,其地址应该是字对齐的。
字对齐,就是字的地址可以被4整除。也就是说,若第1个字在存储空间中是在第0个地址对应的单元(32位),那么,第2个字则应在第4个地址对应的单元,第3个字应在第8个地址对应的单元,依此类推。一个字(32位二进制数)是由4个字节组成,假如某个字其地址是A(A能被4整除),那么,该字的4个字节对应的地址是A、A+1、A+2、A+3。
8
字对齐 分析:假设存储器从地址0(0x )开始存放字数据,一个字数据占四个存储单元,即0(0x )、1(0x )、2(0x )、3(0x )四个单元,那么第二个字数据放在地址4(0x )开始的单元里,第三个数据则放在地址8开始的单元里,依此类推。
9
字对齐 即使存储了其他类型(半字或者字节)的数据,没有用到四个字节,那么下一个数据也必须按字对齐的原则,存放在能被4整除的地址单元里。
例如:一个字(32位)数据存放在4(0x )、5(0x )、6(0x )、7(0x )四个存储单元中,下面一个存储单元即8(0x )存放了一个字节(8位)的数据,如果接着要存放一个字(32位)数据,则这个字数据不能存储在9(0x )开始的存储单元中,而是必须存放在c(0x C)、d(0x D)、e(0x E)、f(0x F)这四个地址单元中,这样才符合地址对齐的规定。
10
ARM存储结构 对于指令,ARM指令系统分为32位ARM指令集和16位的Thumb指令集,在存储时分别以32位和16位的两种不同长度存储。
11
ARM存储结构 ARM存储器以8位为一个单元存储数据(一个字节),每个存储单元分配一个存储地址。
ARM将存储器看作是从零地址开始的字节的线性组合。作为32位的微处理器,ARM体系结构所支持的最大寻址空间为4GB(232字节)。 从零字节到三字节放置第一个存储的字数据,从第四个字节到第七个字节放置第二个存储的字数据,依次排列。 32位的字数据要使用4个地址单元,16位半数据要使用2个地址单元。 就存在一个所存储的字或半字数据的排列顺序问题。ARM体系结构可以用两种方法存储字数据,称为大端格式和小端格式 。
12
ARM存储结构 数据存储格式 大端格式:字数据的高字节存储在低地址中,低字节存储在高地 址中。
小端格式:字数据的高字节存储在高地址中,低字节存储在低地址中。 例:0x 字数据的大、小端存储方式 低位地址 高位地址 大端格式 低位地址 高位地址 小端格式
13
存储器存储方式 存储器以字节为基本存储单元。 每个存储单元都有唯一的地址与之相对 应。 每个字节的二进制码占用一个存储单元 。
0xfe 0xdc 0xba 0x98 0x76 0x54 0x32 0x10 0x 0x 0x 0x 0x 0x 0x 0x 0x98ba 0x 存储器以字节为基本存储单元。 每个存储单元都有唯一的地址与之相对 应。 每个字节的二进制码占用一个存储单元 。 每个双字节的二进制码占用两个连续的 存储单元。 低字节保存在低地址,高字节保存 在高地址。 每个四字节的二进制码占用四个连续的 存储单元。
14
存储器存储方式 存储器每个存储单元都有唯一地址 每个数据的地址都采用低地址来标识 0xfe地址为0x20001000
0xdc 0xba 0x98 0x76 0x54 0x32 0x10 0x 0x 0x 0x 0x 0x 0x 0x 0x98ba 0x 存储器每个存储单元都有唯一地址 每个数据的地址都采用低地址来标识 0xfe地址为0x 0xdc地址为0x 0x98ba地址为0x 0x 地址为0x
15
内容 Cortex-M3存储器的分类 ARM的存储结构及存储方式 存储器操作数及变量 操作数的寻址方式 Cortex-M3存储器访问指令 栈操作
16
存储器操作数 存储器操作数都按一定规律在存储器中排列,为了便于描述,通常采用不同字符组合来标识。
存储在存储空间的数据通常称为存储变量或简称变量。 变量声明 {变量名} 类型 值1,值2, … 变量名 实质是所变量所在存储空间的地址。 主要用于对存储空间的标识,方便编程。 变量类型 字符型(char) DCB 半字型(short) DCW 字型(long) DCD
17
变量定义 以字节定义 x1 DCB 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 以半字定义
x2 DCW 0xdcfe, 0x98ba, 0x5476, 0x1032 以字定义 x3 DCD 0x98badcfe, 0x 混合定义 x4 DCB 0xfe, 0xdc DCW 0x98ba DCD 0x
18
变量定义对照 x DCB 1,2,3 y DCW 1,2,3 z DCD 1,2,3 x DCB 1 char x[]={1};
在C语言中定义一个变量“char x=1;”,这样应用起来方便。但在汇编来看,所有值都放在存储器中,只有地址。汇编中使用的是&x。
19
long x[]={0x98badcfe, 0x10325476, x};
变量定义 x DCD 0x98badcfe, 0x DCD x 0x 0xfe 0x 0xdc 0x 0xba 0x 0x98 0x 0x76 0x 0x54 0x 0x32 x DCD 0x98badcfe, 0x DCD 0x 0x 0x10 0x 0x00 0x10 0x20 0x 0x a 0x b long x[]={0x98badcfe, 0x , x};
20
变量定义 char x[4]; long y[]={4}; 批量字节空间分配 变量名 SPACE n ; for KEIL
常用于大数量的存储空间分配 x SPACE 4 y DCD 4 :分配四个字节(1个字)空间 :分配四个字节(1个字)空间,并将值4保 存在其中。 char x[4]; long y[]={4};
21
内容 Cortex-M3存储器的分类 ARM的存储结构及存储方式 存储器操作数及变量 操作数的寻址方式 Cortex-M3存储器访问指令 栈操作
22
操作数的寻址方式 立即数寻址 MOV Rd, #imm (Rd) = imm 立即数 imm 0-0xffff
奇偶字节均相等 MOVW Rd, #imm Rd的高16位清零 imm MOVT Rd, #imm (Rd) = imm<<16 Rd的低16位不受任何影响 其它立即数如何送至寄存器?
23
操作数的寻址方式 直接寻址 [addr] 首地址为addr的存储空间 读取数值按操作类型确定 [0x20001000] 字符型:0xfe
半字型:0xdcfe 字型:0x98badcfe [0x ] 字符型:0x98 半字型:0x7698 字型:0x 0xfe 0x 0xdc 0x 0xba 0x 0x98 0x 0x76 0x 0x54 0x 0x32 0x 0x10 0x
24
操作数的寻址方式 相对寻址 相对寻址 [Rn, offset] Rn的值(Rn)为基址 地址=基址+偏移量 偏移量为立即数
[Rn, #imm] Addr=(Rn)+imm -0xfffimm 0xfff 偏移量为寄存器值 [Rn, Rm] Addr=(Rn)+(Rm) 偏移量为寄存器值的移位结果 [Rn, Rm, LSL #n] Addr=(Rn)+(Rm)<<n n=1、2、3 0xfe 0x 0xdc 0x 0xba 0x 0x98 0x 0x76 0x 0x54 0x 0x32 0x 0x10 0x
25
内容 Cortex-M3存储器的分类 ARM的存储结构及存储方式 存储器操作数及变量 操作数的寻址方式 Cortex-M3存储器访问指令 栈操作
26
Cortex-M3存储器访问指令 常用的存储器访问指令 实例 描述 LDRB Rd, [Rn, #offset]
LDRH Rd, [Rn, #offset] 从存储器位置Rn+offset处读取半字 LDR Rd, [Rn, #offset] 从存储器位置Rn+offset处读取字 LDRD Rd1, Rd2, [Rn, #offset] 从存储器位置Rn+offset处读取双字 STRB Rd, [Rn, #offset] 往存储器位置Rn+offset处存储字节 STRH Rd, [Rn, #offset] 往存储器位置Rn+offset处存储半字 STR Rd, [Rn, #offset] 往存储器位置Rn+offset处存储字 STRD Rd1, Rd2, [Rn, #offset] 往存储器位置Rn+offset处存储双字
27
a=*(long*)(((char*)x)+m);
Cortex-M3存储器访问指令 存储器只能与寄存器交换数据 读出 LDR Rd, [Rn, offset]; 读一个字 LDRH Rd, [Rn, offset]; 读一个半字 LDRB Rd, [Rn, offset]; 读一个字节 LDRD RdL, RdH, [Rn, offset]; 读一个双字 a=*(long*)(((char*)x)+m); a=*(short*)(((char*)x)+m); a=*(((char*)x)+m); a=*(long long*)(((char*)x)+m);
28
*(long*)(((char*)x)+m)=a;
Cortex-M3存储器访问指令 存储器只能与寄存器交换数据 写入 STR Rd, [Rn, offset]; 写一个字 STRH Rd, [Rn, offset]; 写一个半字 STRB Rd, [Rn, offset]; 写一个字节 STRD RdL, RdH, [Rn, offset]; 写一个双字 *(long*)(((char*)x)+m)=a; *(short*)(((char*)x)+m)=a; *(((char*)x)+m)=a; *(long long*)(((char*)x)+m)=a;
29
Cortex-M3存储器访问指令 存储器的读写 x (Rn) i(Rm) j (Rd) long x[5]; j=x[i]; short x[5]; j=x[i]; char x[5]; j=x[i]; long x[5]; x[i]=j; short x[5]; x[i]=j; char x[5]; x[i]=j; LDR Rd, [Rn, Rm, LSL #2] LDRH Rd, [Rn, Rm, LSL #1] LDRB Rd, [Rn, Rm] STR Rd, [Rn, Rm, LSL #2] STRH Rd, [Rn, Rm, LSL #1] STRB Rd, [Rn, Rm]
30
Cortex-M3存储器访问指令 存储器寻址 LDR R2, [R0,#4] Addr=0x20001000+4=0x20001004
LDRH R2, [R0, R1] Addr=0x =0x R2=0xbadc LDRB R2, [R0, R1, LSL #2] Addr=0x (1<<2)=0x R2=0x76 R0 0x1 R1 0xfe 0x 0xdc 0x 0xba 0x 0x98 0x 0x76 0x 0x54 0x 0x32 0x 0x10 0x
31
练习题 存储器中存有0x80、0x2030、0x456789三个数,将这三个数分别读取至R2、R3、R4中。
LDRB R2, [R0, #0] 0x67 0x89 LDRH R3, [R0, #2] 0x67 0x45 LDR R2, [R0, #6] 0x00 0x01 0x00
32
练习题 如何将超过16位的立即数赋给寄存器呢??? 这三个数可以组成一个32位数0x78563412,将该值保存在R1中,直接采用
将数值0x12、0x34、0x56、0x78按顺序保存在地址为0x 、0x 、0x 、0x 这四个存储单元中。 假定R0当前值为0x 程序 MOV R1, #0x12 STRB R1, [R0, #0x10] MOV R1, #0x34 STRB R1, [R0, #0x11] MOV R1, #0x56 STRB R1, [R0, #0x12] MOV R1, #0x78 STRB R1, [R0, #0x13] 如何将超过16位的立即数赋给寄存器呢??? 这三个数可以组成一个32位数0x ,将该值保存在R1中,直接采用 STR R1, [R0, #0x10] 即可。
33
练习思考 如何将超过16位的任一立即数(如0x78563412 )赋给寄存器呢?
先将0x 作为数据定义出来,再采用LDR将其读入R1。 x DCD 0x LDR R1, x 假定x标识的存储单元地址为0x ,汇编指令实质是以PC 作为基址的相对寻址。 LDR R1, [PC, #offset] offset在编译连接过程中自动生成,无需人为计算,但仅当offset在规定的范围内才无错。 假定当前PC为0x LDR R1, [PC, #8]
34
Cortex-M3存储器访问指令 立即数offset在编译连接过程中自动生成,无需人为计算。 使用LDR伪指令进行立即数赋值
LDR R0, =imm imm满足MOV要求的 等同于 MOV R0, #imm imm满足MOVW要求的 等同于 MOVW R0, #imm imm不满足MOV或MOVW要求的 分为两部分,即以PC作为基址的相对寻址指令和立即数的存储(与指令同在相同的代码区)。 LDR R0, [PC, #offset] ⁞ DCW immL DCW immH 立即数offset在编译连接过程中自动生成,无需人为计算。
35
Cortex-M3存储器访问指令 “.W”表明指令为32位Thumb-2指令,否则位16位Thumb指令 前序存储器访问指令 实例 描述
LDR.W Rd, [Rn, #offset]! 多种数据大小的前序加载指令 (字、字节、半字、双字) LDRB.W Rd, [Rn, #offset]! LDRH.W Rd, [Rn, #offset]! LDRD.W Rd1, Rd2, [Rn, #offset]! LDRSB.W Rd, [Rn, #offset]! 带有符号展开、多种数据大小的前序加载指令(字节、半字) LDRSH.W Rd, [Rn, #offset]! STR.W Rd, [Rn, #offset]! 多种数据大小的前序存储指令 STRB.W Rd, [Rn, #offset]! STRH.W Rd, [Rn, #offset]! STRD.W Rd1, Rd2, [Rn, #offset]! “!”表明基址寄存器Rn会更新,这样指令包含两部分工作,访问存储器+地址修正。-255offset255 Sign extension LDR.W R0, [R1, #offset]! ;读取存储器[R1+offset],R1更新为R1+offset
36
Cortex-M3存储器访问指令 后序存储器访问指令 实例 描述 LDR.W Rd, [Rn], #offset 多种数据大小的后序加载指令
(字、字节、半字、双字) LDRB.W Rd, [Rn], #offset LDRH.W Rd, [Rn], #offset LDRD.W Rd1, Rd2, [Rn], #offset LDRSB.W Rd, [Rn], #offset 带有符号展开、多种数据大小的后序加载指令(字节、半字) LDRSH.W Rd, [Rn], #offset STR.W Rd, [Rn], #offset 多种数据大小的后序存储指令 STRB.W Rd, [Rn], #offset STRH.W Rd, [Rn], #offset STRD.W Rd1, Rd2, [Rn], #offset LDR.W R0, [R1], #offset ;读取存储器[R1],R1更新为R1+offset
37
Cortex-M3存储器访问指令 前序存储器访问 从地址0x20001000开始将后续的三个字分别读到的R1,R2和R3中。
0x20000ffc 从地址0x 开始将后续的三个字分别读到的R1,R2和R3中。 LDR R1, [R0, #4]! LDR R2, [R0, #4]! LDR R3, [R0, #4] 0x 0xfe 0xdc R0 0x20000ffc 0xba 0x98 0x76 R0 0x R1 0x98badcfe 0x54 0x32 0x10 R0 0x R2 0x 0x01 0x23 0x45 R0 0x R3 0x 0x67
38
Cortex-M3存储器访问指令 后序存储器访问 从地址0x20001000开始将后续的三个字分别读到的R1,R2和R3中。
LDR R1, [R0], #4 LDR R2, [R0], #4 LDR R3, [R0] 0x 0xfe 0xdc R0 0x 0xba 0x98 0x76 R0 0x R1 0x98badcfe 0x54 0x32 0x10 R0 0x R2 0x 0x01 0x23 R0 0x R3 0x 0x45 0x67
39
练习题 将数值0x12、0x34、0x56、0x78按顺序保存在地址为0x 、0x 、0x 、0x 这四个存储单元中。 程序 LDR R0, =0x MOV R1, #0x12 STRB R1, [R0, #0x0] MOV R1, #0x34 STRB R1, [R0, #0x3] MOV R1, #0x56 STRB R1, [R0, #0x6] MOV R1, #0x78 STRB R1, [R0, #0x9]
40
练习题 将数值0x12、0x34、0x56、0x78按顺序保存在地址为0x 、0x 、0x 、0x 这四个存储单元中。 程序 LDR R0, =0x MOV R1, #0x12 STRB R1, [R0] MOV R1, #0x34 STRB R1, [R0, #0x3]! MOV R1, #0x56 MOV R1, #0x78 STRB R1, [R0, #0x3]
41
Cortex-M3存储器访问指令 IA:传输完成后(A)地址递增(I) 多次存储器访问指令 “DB:传输前(B)地址递减(D)
实例 描述 LDMIA Rd(!), <reg list> 从Rd指令的存储器位置读取多个字,每次传送后地址增加 STMIA Rd(!), <reg list> 从Rd指令的存储器位置存储多个字,每次传送后地址增加 LDMIA.W Rd(!), <reg list> LDMDB.W Rd(!), <reg list> 从Rd指令的存储器位置读取多个字,每次传送前地址减少 STMIA.W Rd(!), <reg list> STMDB.W Rd(!), <reg list> 从Rd指令的存储器位置存储多个字,每次传送前地址减少 “DB:传输前(B)地址递减(D) (R8)=0x8000; STMIA.W R8!, {R0-R3}; 存储器后R8变为0x8010(增加4个字) STMIA.W R8, {R0-R3}; 存储器后R8不变
42
Cortex-M3存储器访问指令 多次存储器访问 从地址0x20001000开始将后续的三个字分别读到的R1,R2和R3中。
LDMIA R0, {R1-R3} LDMIA R0!, {R1-R3} R0 0x 0x 0xfe 0xdc R0 0x R1 0x98badcfe 0xba R2 0x 0x98 R3 0x R0 0x 0x76 0x54 R0 0x 0x32 R1 0x98badcfe 0x10 R2 0x 0x01 R3 0x R0 0x c 0x23 0x45 0x67
43
Cortex-M3存储器访问指令 后序存储器访问 从地址0x20001000开始将后续的三个字分别读到的R1,R2和R3中。
0x c R0 从地址0x 开始将后续的三个字分别读到的R1,R2和R3中。 LDMDB R0, {R1-R3} LDMDB R0!, {R1-R3} 0x 0xfe 0xdc R0 0x c R1 0x98badcfe 0xba R2 0x 0x98 R0 0x c R3 0x 0x76 0x54 R0 0x c 0x32 0x10 R1 0x98badcfe 0x01 R2 0x 0x23 R3 0x R0 0x 0x45 0x67
44
内容 Cortex-M3存储器的分类 ARM的存储结构及存储方式 存储器操作数及变量 操作数的寻址方式 Cortex-M3存储器访问指令 栈操作
45
栈操作 栈 一定大小的存储空间,按先进后出读写数据 数据读写改变栈指针SP(R13) 栈指针初始在栈底(高地址) 入栈
地址值只能为4的倍数(二进制后两位都为0) 栈 一定大小的存储空间,按先进后出读写数据 数据读写改变栈指针SP(R13) 栈指针初始在栈底(高地址) 入栈 栈指针减4后在相应的地址上写入一个字 PUSH {寄存器列表} STMDB SP!, {寄存器列表} 出栈 取出栈指针所对应的一个字后栈指针加4 POP {寄存器列表} LDMIA SP!, {寄存器列表}
46
假定(R0)=0x12,(R1)=0x3456,(R2)=0x789abcde PUSH {R0} PUSH {R1} PUSH {R2}
入栈 SP 0x c 假定(R0)=0x12,(R1)=0x3456,(R2)=0x789abcde PUSH {R0} PUSH {R1} PUSH {R2} 0x 0xde 0xbc SP 0x c 0x9a 0x78 0x56 SP 0x 0x34 0x00 0x00 SP 0x 0x12 0x00 SP 0x 0x00 0x00 0x00 SP
47
栈操作 入栈 SP 0x c 假定(R0)=0x12,(R1)=0x3456,(R2)=0x789abcde PUSH {R0-R2} STMDB SP!, {R0-R2} 0x 0x12 0x00 0x00 SP 0x c 0x00 0x56 0x34 SP 0x 0x00 0x00 SP 0x c 0xde 0xbc 0x9a SP 0x 0x78 0x00 SP
48
栈操作 出栈 SP 0x 从栈中读出三个数,使(R4)=0x12,(R5)=0x3456,(R6)=0x789abcde POP {R6} POP {R5} POP {R4} SP 0x 0xde 0xbc SP 0x 0x9a (R6)= 0x789abcde 0x78 0x56 SP 0x 0x34 (R5)= 0x3456 0x00 0x00 SP 0x 0x12 (R4)= 0x12 0x00 SP 0x C 0x00 0x00 0x00
49
栈操作 出栈 SP 0x 从栈中读出三个数,使(R4)=0x12,(R5)=0x3456,(R6)=0x789abcde POP {R4-R6} LDMIA SP!, {R4-R6} SP 0x 0x12 0x00 0x00 SP 0x 0x00 0x56 SP 0x c 0x34 0x00 0x00 SP 0x 0xde 0xbc 0x9a 0x78 SP 0x c 0x00
50
栈操作 堆栈内开辟存储空间 在堆栈中开辟三个字空间,从低地址向高地址存放0x1234、0x5678、0xabcd。 PUSH {R0}
LDR R0, =0xabcd LDR R0, =0x5678 LDR R0, =0x1234 PUSH {R0] LDR R0, [SP, #12] R0 0x R0 0x R0 0x0000abcd 0x 0x 0x 0x 0x 0x 0x 0x 0x0000abcd 0x 0x 0x R0 0x R0 0x R0 0x 0x 0x 0x 0x 0x 0x 0x0000abcd 0x0000abcd 0x0000abcd 0x 0x 0x
51
栈操作 使用堆栈中所开辟的存储空间 分别对前面所开的堆栈存储空间中所存储的值进行处理,每次操作的数都在R0中。
STR R0, [SP, #12] LDR R0, [SP, #0] LDR R0, [SP, #4] LDR R0, [SP, #8] LDR R0, [SP, #12] R0 0x R0 0x 0x 0x 0x 0x 0x0000abcd 0x0000abcd 0x 0x R0 0x R0 0x R0 0x0000abcd R0 0x
52
栈操作 释放堆栈中所开辟的存储空间 将前所开辟的空间释放,堆栈指针回到原位置。 STR R0, [SP, #12] POP {R0} R0
0x R0 0x R0 0x 0x 0x 0x 0x 0x 0x 0x0000abcd 0x0000abcd 0x0000abcd 0x 0x 0x R0 0x R0 0x0000abcd R0 0x 0x 0x 0x 0x 0x 0x 0x0000abcd 0x0000abcd 0x0000abcd 0x 0x 0x
Similar presentations