您的位置 首页 元件

ARM指令学习笔记

要学arm指令集,首先要了解什么是arm。众所周知arm是advancedRISCmachines。而risc又是什么东西呢?即:reducedinstructionsetcomputer,精…

要学arm指令集,首要要了解什么是arm。众所周知arm是advancedRISCmachines。而risc又是什么东西呢?即:reducedinstructionsetcomputer,精简指令集核算机。是一种是一种履行较少类型核算机指令的微处理器,起源于80年代的MIPS主机。因为指令少越简略,就需求更少的晶体管和电路元件,故它能够以更快的速度履行操作(每秒履行更多百万条指令,即MIPS)。我想这也是nds游戏机要用arm处理器的原因,因为它小且快,再者廉价。Arm呢,它是英国的一家公司,规划了许多高功用、廉价、耗能低的RISC处理器、相关技能及软件。技能具有功用高、成本低和能耗省的特征。适用于多种范畴,比方嵌入操控、消费/教育类多媒体、DSP和移动式运用等。这个公司ARM公司既不出产芯片也不出售芯片,它只出售芯片技能授权。纵观咱们周围的手机,诺基亚n86,n97,n95,n96……摩托诺拉,索爱,苹果,三星,无一不许多运用arm处理器。而咱们所要触摸的nds中的处理器ARM946E-S和ARM7TDMI是ARM公司研发的内嵌式32BITRISCCPU。它具有低功耗、高功用、体积小、低价格等长处。十分适合掌机运用。ARM946E-S是一种有5级流水线,集成有Thumb扩展功用、调试功用和哈佛总线的内核。在相同工艺下,它是ARM7TDMI功用的两倍以上。有了个简略了解之后,开端投入到了arm指令的学习。

参阅———-<百度>“arm百度百科”,”NDS百度百科”

接下来便是对arm指令的学习。

因为有过前面8086指令的学习,而且也写过像高精度核算这样的汇编程序,看arm指

心里边老在比较这两套指令。

arm7TDMI(-S)指令体系有两套指令集,别离是32位的Arm指令集和16位的thumb指令集。简略点说:arm支撑arm内核的一切特征,具有高效、快速的特征;而thumb指令集灵敏、细巧。二者能够相互调用,Thumb指令集能够看做是Arm的紧缩方法的子集,是针对代码的密度问题而提出的,Thumb指令都有对应的Arm指令,但却不是一个完好的体系,例如:Thumb指令集没有协处理器指令,信号量指令以及拜访CPSR或SPSR的指令,没有乘加指令及64位乘法指令等,且指令的第二操作数受到约束;除了跳转指令B有条件履行功用外,其它指令根本为无条件履行.,等等。不逐个叙说。而Arm指令集出了具有许多Thumb没有的功用外,它最大的特征便是:高效。

Arm的寄存器是37个,包括

31generalregisters(Rxx)

6status registers(xPSR)

对这37个寄存器的详细描绘咱们能够从nocash.emubase.de这个网站上得到。

学习arm指令,最早触摸的是寻址指令。

Arm寻址指令可分为九类:

Arm指令 80×86中有吗?

1.寄存器寻址

2.当即寻址;
3.寄存器移位寻址; 无

4.寄存器直接寻址;
5..基址寻址;

6.多寄存器寻址; 无

7.仓库寻址; 无

8.块仿制寻址; 无
9.相对寻址。

能够看到arm寻址指令里边有个很大的特征是它的寄存器移位寻址,即第二个操作数在与第一个操作数结合之前能够挑选进行移位操作,例如:MOVR0,R2,LSL#3。而在80×86指令中这得要三步走:一次赋值(不然影响寻址变量的值)、一次移位、一次寻址。不只带来了视觉上的不便利,而且给书写带来了费事(更简略犯错)。别的,Arm指令还能够进行多寄存器寻址,无疑简化了操作(详细点讲,便是少写许多”LD””ST”)。还能够看到咱们在arm指令中只需加个”!”就能够决议中心值是否保存。愈加便利的是咱们能够自由挑选变址前后指针的改变,例如块仿制寻址中就有四种:STMIA,STMIB,STMDA,STMDB.连递减仍是递加,先变址仍是先仿制,Arm都给你预先规划好了,不能不说它周全,这些都是80×86里没有的,极大地便利了程序员的程序规划。

顺带说一下其另一个快捷之处,加载/装填数据时,能够在指令后加H/B来表明对半字/字节的数据操作,默许情况下是字。而且ARM能够完结一组寄存器和一块接连内存之间传送数据,如LDMIA和STMIA指令。

看完寻址,接下来才是Arm指令的要点,

Arm指令的根本格局为:

{}{s},{,}

————————arm的32伪指令二进制格局

其间<>内的项是有必要的,而{}内的项是可选的。

Opcode:指令助记符

Cond:履行条件

S:是否影响cpsr寄存器的值

Rd:方针寄存器

Rn:第一个操作数的寄存器

Oprand2:第二个操作数

ARM指令能够分为6大类

(1) 跳转指令 B、BL、BLX、BX

(2)数据处理指令 数据传送\算术逻辑运算\比较

(3)程序状况寄存器传输指令

(4)load/store指令

(5)协处理指令

(6)反常间断指令

能够看到项,这又是arm指令的一特征,能够将各种运算指令与条件指令结合起来用,例如80×86中写个找ra,rb中教大数存入rc寄存器中需求这样写

MOVE rcra

CMP rarb

JG NEXT

MOVE rcrb

NEXT

…………..

而在arm中能够很便利地写成

MOVE rcra

CMP rarb

MOVECC rcrb

灵敏运用第二个操作数还能大大提高代码的功率,例如咱们要将r1寄存器中的数乘以9,能够在arm中很便利地写成

ADD R1,R1,R1,LSL#3

换成80×86,那便是一堆进程了

MOVE R2,R1

SHL R2,3

ADD R1,R2

便是说arm的指令更人性化,加上后来对arm伪指令的学习,我个人觉得arm指令集是汇编中的高档言语了。

在ARM中乘法操作能够用于恣意两个寄存器成果能够保存到恣意寄存器,而80×86则需求先将被乘数保存于AL/AX中再做乘法。而且高位和方位还要分隔保存至AX/AL和DX/AH中,费事!

ARM的间断指令有:

(1)复位反常

(2)未界说指令反常

(3)软件间断反常

(4)预取指间断反常

(5)数据间断反常

(6)间断恳求反常

(7)快速间断(FIQ)恳求反常

品种繁复学起来很头疼,不像80×86自始至终便是INT间断那样清新。间断这块自己不甚了解,还需持续努力学习,

接下来的学习就到了伪指令。首要伪指令不是ARM指令会集的指令,仅仅为了编程便利编译器界说了伪指令,运用时能够像其他ARM指令相同运用,但在编译时这些指令会被等效的ARM指令代替。尽管有些伪指令仅仅一些极端简略的替换,但却极大地便利咱们编程。能够说它是以它是一种特别的助记符。

关于伪指令的学习也仅仅概念性的,无法深入,许多指令尽管知道意思但彻底不知道哪儿用的着。有待往后的时刻吧。

总的来说,ARM指令有一下几种

1.符号界说伪指令

全局变量声明:GBLA、GBLL和GBLS。
部分变量声明:LCLA、LCLL和LCLS。
变量赋值:SETA、SETL和SETS。
为一个通用寄存器列表界说称号:RLIST。
为一个协处理器的寄存器界说称号:CN。
为一个协处理界说称号:CP。
为一个VFP寄存器界说称号:DN和SN。
为一个FPA浮点寄存器界说称号:FN。

2.数据界说伪指令
声明一个文字池:LTORG。
界说一个结构化的内存表的首地址:MAP。
界说结构化内存表中的一个数据域:FIELD。
分配一块内存空间,并用0初始化:SPACE。
分配一段字节的内存单元,并用指定的数据初始化:DCB。
分配一段字的内存单元,并用指令的数据初始化:DCD和DCDU。
分配一段字的内存单元,将每个单元的内容初始化为该单元相关于静态基址寄存器的偏移量:DCDO。
分配一段双字的内存单元,并用双精度的浮点数据初始化:DCFD和DCFDU。
分配一段字的内存单元,并用单精度的浮点数据初始化:DCFS和DCFSU。
分配一段字的内存单元,并用单精度的浮点数据初始化,指定内存单元寄存的是代码,而不是数据:DCI。
分配一段双字的内存单元,并用64位整数数据初始化:DCQ和DCQU。
分配一段半字的内存单元,并用指定的数据初始化:DCW和DCWU。

断语过错:ASSERT。这个指令比较奇特,能够在程序首写一些比方ASSERTtop<>temp的断语过错指令,在汇编编译器对汇编程序的第二遍扫描中,假如其间
ASSERT条件不成立,ASSERT伪指令将陈述该过错信息,然后削减过错。有点像C++中try和catch。

3.汇编操控伪指令/宏伪指令

汇编操控伪指令用于条件汇编、宏界说、重复汇编操控等。该类伪指令如下:
条件汇编操控:IF、ELSE和ENDIF
宏界说:MACRO和MEND
重复汇编:WHILE及WEND

这些便是它有点像高档言语的当地,能够用伪指令完结某些高档句子。其实高档言语不便利是一个个汇编指令的打包吗?迥然不同。

值得提及的是MACRO和MEND,这个东西感觉便是C中的#define,很强壮。

其伪指令格局:
MACRO
{$label}macroname{$parameter}{$parameter}…

其间:$label宏指令被打开时,label可被替换成相应的符号,一般为一个标号在一个 符号前运用$表明被汇编时将运用相应的值代替$后的符号。
macroname所界说的宏的称号。
$parameter宏指令的参数。当宏指令被打开时将被替换成相应的值,相似于函数 中的方法参数。

能够完结参数的传递!!这种伪指令让人看上去就有想去测验运用的激动,今后必定会有机遇的!

这儿简略设想下运用:

C言语中:#definebigger(a,b)(a>b)

能够写成(或许会有错,仅仅测验一下罢了):

MACRO

$labelbigger$a,$b

$label

;GL1为一个界说的全局变量

CMP $a,$b

MOVEGT GL1,1

MOVELE GL1,1

MEND

调用testbiggera,b

然后在GL1中得到巨细成果

当然咱们能够直接比较,这儿仅仅为了演示一下。

4.杂项伪指令

杂项伪指令在汇编编程规划较为常用,如段界说伪指令,进口点设置伪指令,包括 文件伪指令,标号导出或引进声明等,该类伪指令如下:
鸿沟对齐:ALIGN。
段界说:AREA。
指令集界说:CODE16和CODE32。
汇编完毕:END。
程序进口:ENTRY。
常量界说:EQU。
声明一个符号能够被其它文件引证:EXPORT和GLORBAL。
声明一个外部符号:IMPORT和EXTERN。
包括文件:GET和INCLUDE。
包括不被汇编的文件:INCBIN。
保存符号表中的部分符号:KEEP。
制止浮点指令:NOFP。
指示两段之间的依靠联系:REQUIRE。
仓库8字节对准:PEQUIRE8和PRESERVE8。
给特定的寄存器命名:RN。
符号部分标号运用范围的边界:ROUT。

终究一块是C与汇编混合编程。

(1)c中内嵌汇编。曾今看过个故事:一个物理学家写一个模仿天体运转的程序,别离从算法和指令两方面经行优化,用了一个月的时刻将一个本来要几年才干出成果的程序缩短到十几分钟。这其间有个很重要的一步,便是将某些重用性很大的高档言语程序块用汇编言语直接书写。大大缩短了程序运转的极限时刻。曾今也猎奇过,高档言语里边怎样去内嵌汇编?

_asm

{

指令[;指令]

[指令]
}

内嵌汇编程序对寄存器、常量、标号等有许多约束,就不多说了。

(2)汇编中内嵌c言语程序

(3)C与汇编相互调用

在学习ARM指令的进程中,遇到过许多问题,第一次碰到往往十分不解,还有些个该留意的当地,当然了,问题和需呀留意的当地远不止这些。这些仅仅个人觉得一些比较典型的,写在这儿与诸位共享:

1.#immed_8r常数表达式时“该常数有必要对应8位位图,即常数是由一个8位的常数循环移位偶数位得到的。”

其意思是这样:#immed_8r在芯片处理时表明一个32位数,可是它是由一个8位数(比方:01011010,即0x5A)经过循环移位偶数位得到(10000000000000000000000000010110,便是0x5A经过循环右移2位(偶数位)的到的)。

而10100000000000000000000000010110,就不契合这样的规则,编译时必定犯错。因为你或许经过将10110101循环右移位得到它,可是不或许经过循环移位偶数位得到。

10110000000000000000000000010110,也不契合这样的规则,很明显:101101011有9位。

2.什么叫带符号扩展.

当从16位向32位赋值时,若挑选无符号扩展,那高位补零。挑选有符号扩展,那32中的16位依照16位最高位补齐。

例如1101010110101010——->11111111111111111101010110101010

0101010110101010——->000000000000000101010110101010

关于为什么这样补,能够参照补码界说,这儿介绍一种简略的补码核算方法:

N位绝对值为k的数的补码为:2^n-k.比那个取反加一得来得清新一点。

3.咱们说有四品种型的仓库寻址方法,LDMFA,STMFA,LDMEA,STMEA。

留意F表明full,E表明empty,A表明after,B表明before。

咱们假定:在C言语中stack[]为仓库数组,top为堆的顶指针。为便利了解。我用c言语描绘了一下。

仓库是一种数据结构,按先进后出(FirstInLastOut,FILO)的方法作业,运用一个称作仓库指针的专用寄存器指示当时的操作方位,仓库指针总是指向栈顶。

当仓库指针指向终究压入仓库的数据时,称为满仓库(FullStack),而当仓库指针指向下一个即将放入数据的空方位时,称为空仓库(EmptyStack)。

一起,依据仓库的生成方法,又能够分为递加仓库(AscendingStack)和递减仓库(DecendingStack),当仓库由低地址向高地址生成时,称为递加仓库,当仓库由高地址向低地址生成时,称为递减仓库。这样就有四品种型的仓库作业方法,ARM微处理器支撑这四品种型的仓库作业方法,即:

◎Fulldescending满递减仓库

仓库首部是高地址,仓库向低地址添加。栈指针总是指向仓库终究一个元素(终究一个元素是终究压入的数据)。

ARM-Thumb进程调用规范和ARM、ThumbC/C++编译器总是运用Fulldescending类型仓库。

C言语表明:stack[–top]=value

◎Fullascending满递加仓库

仓库首部是低地址,仓库向高地址添加。栈指针总是指向仓库终究一个元素(终究一个元素是终究压入的数据)。

C言语表明:stack[top–]=value

◎Emptydescending空递减仓库

仓库首部是低地址,仓库向高地址添加。栈指针总是指向下一个即将放入数据的空方位。

C言语表明:stack[++top]=value

◎Emptyascending空递加仓库

仓库首部是高地址,仓库向低地址添加。栈指针总是指向下一个即将放入数据的空方位。

操作仓库的汇编指令

C言语表明:stack[top++]=value

4.算术位移/逻辑位移/循环位移

算术位移,逻辑位移逻辑右移最高位补0,最低位进入CF,相当于每移一位除以2,一般关于无符号数运用 如:133/8=16余5 MOVAL,10000101B MOVCL,03H SHRAL,CL AL=10H=16 算术右移最高位(即符号位)坚持不变,而不是补0最低位进入CF.相当于每移一位除2,一般关于有符号数运用8/8 MOVAL,10000000B MOVCL,03H SARAL,CL AL=0F0H=-16

———-别离对应逻辑左移、逻辑右移、算术右移、循环右移

5.关于ARM的B,BL跳转指令

假定跳转指令处的地址是A,跳转方针处的地址是B.
B,BL指令保存的是偏移地址,这个地址的核算方法是:
1.B-(A+8).A+8是因为ARM的流水线使得指令履行到A处时,PC实践的值是A+8.2.第一步得到的值是4的倍数,因为ARM的指令是4对齐的,即最低两位为00.所以将这个值右移两位.
3.得到终究偏移

履行时:
1.取出偏移
2.左移两位
3.参加PC,这时PC的值刚好为方针处的地址值,即方针地址指令进入取指,流水线前两级被清空

可是为什么是减去8呢?这因为ARM7是三级流水线。

那什么三级流水线是什么?

PC代表程序计数器,流水线运用三个阶段,因而指令分为三个阶段履行:1.取指(从存储器装载一条指令);2.译码(辨认即将被履行的指令);3.履行(处理指令并将成果写回寄存器)。即履行时取指现已提早两个字了,即8个字节。

6.什么是软间断?

  软间断是使用硬件间断的概念,用软件方法进行模仿,完结微观上的异步履行作用。许多情况下,软间断和”信号”有些相似,一起,软间断又是和硬间断相对应的,”硬间断是外部设备对CPU的间断”,”软间断一般是硬间断服务程序对内核的间断”,”信号则是由内核(或其他进程)对某个进程的间断”(《Linux内核源代码情形剖析》第三章)。  软间断的一种典型运用便是所谓的”下半部”(bottomhalf),它的得名来自于将硬件间断处理别离成”上半部”和”下半部”两个阶段的机制:上半部在屏蔽间断的上下文中运转,用于完结关键性的处理动作;而下半部则相对来说并不是十分紧迫的,一般仍是比较耗时的,因而由体系自行安排运转机遇,不在间断服务上下文中履行。bottomhalf的运用也是鼓励内核开展出现在的软间断机制的原因。  软间断是linux体系原“底半处理”的晋级,在原有的基础上开展的新的处理方法,以习惯多cpu、多线程的软间断处理。  一般来说,软间断是由内核机制的触发事情引起的(例如进程运转超时),可是不行忽视有许多的软间断也是因为和硬件有关的间断引起的,例如当打印机端口发生一个硬件间断时,会告诉和硬件相关的硬间断,硬间断就会发生一个软间断并送到操作体系内核里,这样内核就会依据这个软间断唤醒睡觉在打印机使命行列中的处理进程。  在网络编程中,软间断用来引发协议层代码的履行

7.关于程序状况的切换

程序不能经过修正直接修正CPSR中的T操控位直接将程序状况切换到Thumb状况,有必要经过BX等指令完结程序状况的切换

8.关于LDMIA指令,Rn的终究值是加载的值,而不是添加后的地址

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/yuanjian/274790.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部