ARM体系结构与编程笔记

来源:互联网 发布:linux man 退出 编辑:程序博客网 时间:2024/06/05 03:41

存储器映射基本概念

ARM处理器产生的地址叫虚拟地址,把这个虚拟地址按照某种规则转换到另一个物理地址去的方法称为地址映射。这个物理地址表示了被访问的存储器的位置。它是一个地址范围,该范围内可以写入程序代码。

存储器映射控制的必要性

为了让运行在不同存储器空间中的程序对异常进行控制。可以通过存储器映射控制,将位于不同存储空间的异常向量表重新映射至固定地址0x00~0x3F处,以实现异常向量表的来源控制。

APCS规定了子程序调用的基本规则,这些规则包括子程序调用过程中寄存器、数据栈的使用规则以及参数的传递规则。

异常向量表

对于每一个异常事件,都有一个与之相对应的处理程序,它们是关联在一起的,并以一张一维表的格式存储在存储器的固定单元中。这张指定了各异常中断及其处理程序的对应关系的表,称为异常向量表。

ARM处理器对异常中断的响应过程

(1)保存处理器当前状态、中断屏蔽位以及各条件标志位。

(2)设置当前程序状态寄存器CPSR中的相应的位。

(3)将寄存器lr_mode设置成返回地址。

(4)将程序计数器值(PC)设置成该中断的中断向量地址,从而跳转到相应的异常中断处理程序处执行。

异常的响应过程

除了复位异常外,当异常发生后,ARM核会尽可能执行完当前指令,然后自动执行如下动作:

(1)、保存返回地址到LR_<mode>

(2)、复制CPSR到SPSR_<mode>中。

(3)、设置CPSR进入相应的处理器模式。

(4)、设置CPSR的第7位来禁止IRQ。如果异常为快速中断和复位。则还要设置CPSR的第6位来禁止快速中断。

(5)、给PC强制赋向量地址值。

进入异常

1.在适当的LR中保存下一条指令的地址;2.将CPSR复制到适当的SPSR中;3. 将CPSR模式位强制设置为与异常类型相对应的值;4.强制PC从相关的异常向量处取指。

退出异常

1.将LR( R14 )中的值减去偏移量后存入PC,偏移量根据异常的类型而有所不同;2.将SPSR的值复制回CPSR;3.清零在入口置位的中断禁止标志。

ARM处理器异常分为①数据中止 ②快速中断请求③普通中断请求 ④预取指中止 ⑤软件中断 ⑥复位 ⑦未定义指令异常 7种。

异常向量表中程序跳转使用LDR指令,而没有使用B指令。原因:

1.LDR指令可以全地址范围跳转,而B指令只能在前后32MB范围内跳转;

2.芯片具有储器重新映射(Remap)功能。当向量表位于内部RAM或外部存储器中,用B指令不能跳转到正确的位置。

小端存储器系统:

在小端格式中,高位数字存放在高位字节中。因此存储器系统字节0连接到数据线7~0(低位对齐)。

大端存储器系统:

在大端格式中,高位数字存放在低位字节中。因此存储器系统字节0连接到数据线31~24(高位对齐) 。

STMFD sp!,{lr};保存数据栈LDMFD sp!,{pc};恢复

复位:当nRESET信号再次变为高电平时,ARM处理器执行下列操作:

1.强制CPSR中的M[4:0]变为b10011(管理模式);2.置位CPSR中的I和F位;3.清零CPSR中的T位;4.强制PC从地址0x00开始对下一条指令进行取指;5.返回到ARM状态并恢复执行 。

R14(LR)寄存器与子程序调用

1.程序A执行过程中调用程序B;

2.程序跳转至标号Lable,执行程序B。同时硬件将“BL  Lable”指令的下一条指令所在地址存入R14(LR);

3.程序B执行最后,将R14寄存器的内容放入PC,返回程序A;

ARM处理器共有7种工作模式:

①用户模式 :非特权模式,也就是正常程序执行的模式,大部分任务在这种模式下执行。在用户模式下,如果没异常发生不允许应用程序自行改变处理器的工作模式,如果有异常发生,处理器会自动切换工作模式。

②FIQ模式 :也称为快速中断模式,支持高速数据传输和通道处理,当一个高优先级(fast)中断产生时将会进入这种模式。

③IRQ模式 :也成为普通中断模式,当一个低优先级(normal)中断产生时将会进入这种模式。在这种模式下按中断的处理器方式有分为向量中断和非向量中断两种。通常的中断都在IRQ模式下进行。

④SVC模式 :称之为管理模式,它是一种操作系统保护模式。当复位或软中断指令执行时处理器进入这种模式。

⑤中止模式 :当存取异常时将会进入中止模式,用来处理存储器故障、实现虚拟存储或存储保护。

⑥未定义指令异常模式:当执行未定义指令时会进入这种模式,主要是用来处理未定义的指令陷阱,支持硬件协处理的软件仿真,因为未定义指令多发生在协处理器的操作上。

⑦系统模式:使用和User模式相同寄存器组的特权模式,用来运行特权级的操作操作系统任务。

区别:特权模式--程序可以访问所有的系统资源,也可以任意地进行处理器模式的切换。

ARM9采用5级流水线:取指、译码、执行、存储器访问、寄存器回写。

·取指:从指令Cache中读取指令。

·译码:对指令进行译码,识别出对哪个寄存器进行操作并从通用寄存器中读取操作数。

·执行:进行ALU运算和移位操作,如果是对存储器操作的指令,则在ALU中计算出要访问的存储器地址。

·存储器访问:如果是对存储器访问的指令,用来实现数据缓冲功能(通过数据Cache);如果不是对存储器访问的指令,本级流水线为一个空的时钟周期。

·寄存器回写:将指令运算或操作结果写回到目标寄存器中。

CISC:复杂指令集(Complex Instruction Set Computer)

具有大量的指令和寻址方式,指令长度可变;8/2原则:80%的程序只使用20%的指令;大多数程序只使用少量的指令就能够运行。

RISC:精简指令集(Reduced Instruction SetComputer)

只包含最有用的指令,指令长度固定;确保数据通道快速执行每一条指令;使CPU硬件结构设计变得更为简单

1.MOV指令与LDR指令都是往目标寄存器中传送数据,但是它们有什么区别吗?

   MOV指令用于将数据从一个寄存器传送到另一个寄存器中,或者将一个常数传送到一个寄存器中,但是不能访问内存。LDR指令用于从内存中读取数据放入寄存器中。

 

1、ARM7TDMI-S各字母代表的含义?内核特点?采用几级流水线,分别是?

ARM{x}{y}{z}{T}{D}{M}{I}{E}{J}{F}{-S}

大括号内的字母是可选的,各个字母的含义如下:

x         ——系列号,例如ARM7中的“7”、ARM9中的“9”;

y         ——内部存储管理/保护单元,例如ARM72中的“2”、ARM94中的“4”;

z         ——内含有高速缓存Cache;

T        ——技持16位的Thumb指令集;

D        ——支持JTAG片上调试;

M       ——支持用于长乘法操作(64位结果)的ARM指令,包含快速乘法器;

I         ——带有嵌入式追踪宏单元ETM(Embedded Trace Macro),用来设置断点和观察点的调试硬件;

E        ——增强型DSP指令(基于TDMI);

J         ——含有Java加速器Jazelle,与Java虚拟机相比,Java加速器Jazelle使Java代码运行速度提高了8倍,功耗降低到原来的80%;

F         ——向量浮点单元;

S——可综合版本,意味着处理器内核是以源代码形式提供的。这种源代码形式又可以被编译成一种易于EDA工具使用的形式。

内核特点:

32/16 位RISC架构(ARM v4T)。

具有最高性能和灵活性的32位ARM指令集。

代码紧凑的16位Thumb指令集。

统一的总线接口,指令与数据都在32位总线上传输。

3级流水线。

32位算术逻辑单元(ALU)。

极小的核心尺寸以及低功耗。

协处理器接口。

扩展的调试设备:·EmbeddedICE-RT实时调试单元。 ·JTAG接口单元。 ·与嵌入式跟踪宏单元(ETM)直接连接的接口。

ARM7系列内核采用了三级流水线的内核结构,三级流水线分别为取指(Fetch)、译码(Decode)、执行(Execute)

·取指:将指令从存储器中取出,放入指令Cache中。

·译码:由译码逻辑单元完成,是将在上一步指令Cache中的指令进行解释,告诉CPU将如何操作。

·执行:这阶段包括移位操作、读通用寄存器内容、输出结果、写通用寄存器等。也就是将上一步中已被译码的指令进行逻辑电路实现。


1、排序

[plain] view plain copy
  1. AREA TEXT,CODE,READWRITE    
  2.     ENTRY    
  3.     MOV R0,#100  ;循环数目    
  4.     MOV R1,#0        ;初始化数据    
  5. LOOP    
  6.     ADD R1,R1,R0  ;将数据进行相加,获得最后的数据    
  7.     SUBS R0,R0,#1 ;循环数据R0减去1    
  8.     CMP R0,#0        ;将R0与0比较看循环是否结束    
  9.     BNE LOOP        ;判断循环是否结束,接受则进行下面的步骤      
  10.     LDR R2,=RESULT    
  11.     STR R1,[R2]    
  12. RESULT    
  13.     DCD 0    
  14. STOP    
  15.     B STOP   
  16.     ;排列算法:先将所有的数据与第一个进行比较,最后取出最小的数据放到第一个内存单元中    
  17.     ;然后再从第二个内存单元开始进行比较,将第二小的数据放到第二个内存单元中,    
  18.     ;以此内推则能将十个数据进行排列。    
  19.     AREA TEXT,CODE,READWRITE    
  20.     ENTRY    
  21.     LDR R0,=DATA      ;获得DATA数据的起始地址    
  22.     MOV R1,R0        
  23.     MOV R5,#9            ;开始的循环数目是10次,所以应该从9开始    
  24.     MOV R6,R5    
  25. COMPARE    
  26.     ADD R0,R0,#4      ;将R0所存储的地址+4表示为下一个要比较的数的地址      
  27.     SUB R6,R6,#1  ;循环1次减1    
  28.     LDR R2,[R1]  ;将放在寄存器中的数据取出进行大小比较    
  29.     LDR R3,[R0]    
  30.     CMP R3,R2    
  31.     MOVCC R7,R2  ;如果后面的地址的数值比前一个小则交换他们的数据    
  32.     MOVCC R2,R3    
  33.     MOVCC R3,R7    
  34.     STR R2,[R1]  ;将数据存储到相应的内存单元中    
  35.     STR R3,[R0]    
  36.     CMP R6,#0            ;看每次的循环是否结束    
  37.     BNE COMPARE    
  38.     ADD R1,R1,#4      ;每次循环结束以后将初始的指向的内存地址后移一个单元    
  39.     MOV R0,R1            ;重新初始化上个循环中的寄存器中保存的地址    
  40.     SUB R5,R5,#1      ;每次循环以后上面在以后的循环中的次数都会减1    
  41.     MOV R6,R5    
  42.     CMP R5,#0    ;判断所有的循环是否结束    
  43.     BNE COMPARE    
  44. DATA    
  45.     DCD 9,4,6,7,8,1,3,2,0,5    
  46. STOP    
  47.     B STOP   

C语言代码:

[cpp] view plain copy
  1. #include<stdio.h>    
  2. extern void strcopy(char *d, const char *s);    
  3. int main()    
  4. {    
  5.     const char *srcstr="abcdefghi";    
  6.     char dststr[]="ighfedcba";      
  7.     strcopy(dststr,srcstr);    
  8.     return 0;    
  9. }     

ARM汇编代码:

[plain] view plain copy
  1. STACK_TOPEQU 0x40002000    
  2.     PRESERVE8    
  3.     AREA SCopy, CODE, READONLY    
  4.     EXPORT START    
  5.     EXPORT strcopy    
  6.     import main    
  7.     ENTRY    
  8. START    
  9.     LDR R13,=STACK_TOP    
  10.     B main    
  11. strcopy                    
  12.     LDRB r2, [r1],#1    
  13.     STRB r2, [r0],#1    
  14.     CMP  r2, #0            
  15.     BNE  strcopy            
  16.     MOV  pc,lr          
  17.     END   

[plain] view plain copy
  1. stack_top equ0x40002000  
  2. PRESERVE8  
  3. export copy  
  4. AREA copy,CODE,READONLY  
  5. import copystr  
  6. export start  
  7. ENTRY  
  8. start  
  9. ldr r13,=stack_top  
  10. ldr r0,=src  
  11. ldr r1,=dst  
  12. BL copystr  
  13. src      
  14. dcb "abcdefghij"  
  15. dst  
  16. dcb "helloworld"  
  17. end  
[cpp] view plain copy
  1. //C程序  
  2. #include<stdio.h>  
  3. voidcopystr(char *d,char *s)  
  4. {  
  5. while((*d++=*s++)!='\0');  
  6. }  
原创粉丝点击