常用汇编指令

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

常⽤汇编指令
这些是我在学习uboot源码的时候遇到的常见的汇编指令,做个记录,偶尔看的时候能够回忆起来,可能有错的地⽅,请多多指教。

(1).globl _start
@_start是GNU汇编器的默认⼊⼝标签,.globl将_start⽣命为外部程序可访问的标签,.globl是GNU汇编的保留关键字,前⾯加点是GNU汇编的语法。

(2)_start:b start_code
@arm上电之后执⾏的第⼀条指令,复位向量,跳转到start_code
@reset⽤b,就是因为reset在MMU建⽴的前后都有可能发⽣,其他异常只有在MMU建⽴之后才能发⽣。

(3)ldr pc,_not_used
@对于arm中的数据从内存到cpu之间的移动只能使⽤L/S指令,例如:ldr r0,0x12345678,就是把地址为0x12345678中的数据写⼊到r0中。

ldr伪指令:ldr,r0,=0x12345678,mov只能完成寄存器间的数据移动,⽽且把数据长度限制在8位。

(4)ldr pc,_irq
@将_irq中存放的数据放⼊pc中,可以将_irq看成是⼀个变量名或者指针*p,其中存放的内容就是irq,即中断处理的⼊⼝地址。

当发⽣按键动作时,pc会指向“ldr pc,_irq”所在的地址,执⾏这条指令(会被解释成ldr pc,[pc,#offset]),这条指令完成了将irq的地址赋给了pc,从⽽从异常向量表中直接跳⼊中断处理程序。

irq中断向量,还有个fiq中断向量。

@异常:因为内部或者外部的⼀些事件,导致处理器停下正在处理的⼯作,转⽽去处理这些突发事件。

当⼀种异常发⽣的时候,ARM处理器会跳到对应该异常的固定地址去执⾏异常程序,这个固定的地址,就叫做异常向量。

由七个异常向量及其处理函数跳转关系组成的表就是异常向量表。

@指令的运⾏地址和链接地址。

链接地址是在编译连接时编译器确定的地址,运⾏地址是实际运⾏这条指令时,去哪个物理地址去取这条指令,两个地址⼀般相同。

在Flash中相同,Nandflash中则不同。

(5)_not_used: .word not_used
@.word是GNU ARM汇编特有的伪操作,为分配⼀段字内存单元(分配的单元为字对齐的),可以使⽤.word把标识符作为常量使⽤,如
_irq:.word fiq就是将fiq存⼊内存变量_fiq中,即把fiq放到地址_fiq中。

(6).balignl 16,0xdeadbeef
@内存填充⾄4字节对齐,具体解释在博客⾥⾯有,但是不太看得懂
(7)mrs r0,cpsr
@设置成svc32模式
@把cpsr的内容存⼊r0,使⽤了mrs指令,专⽤寄存器到通⽤寄存器的存取。

@CPSR当前程序状态寄存器格式如下:
@ 31 30 29 28 27 26 25 24 ~ ~ ~ 8 7 6 5 4 3 2 1 0
@ ___ ___ ___ ___ ___ ___ ___ ___ _ _ _ _ ___ ___ ___ ____ ____ ____ ____ ____
@| N | Z | C | V | * | * | * | * | * * * | I | F | T | M4 | M3 | M2 | M1 | M0 |
(8)bic r0,r0,#0x1f
@bic指令(bit clear):r0=r0 and (not op2)。

bic r1,r1,r2将r1中的值与r2的反码按位进⾏逻辑与之后,将结果赋给r1。

上边的指令⽬的是把bit0-bit4清零,⼯作模式位清零。

(9)orr r0,r0,#0xd3
@r0:=r0 or 0xd3,以上三条指令执⾏后r0的值为:**** **** **** **** **** ***** 11*1 0011,即设置为管理模式。

把R0与0xd3按位或的结果赋值给R0。

(10)msr cpsr,r0
@把r0存于cpsr。

msr指令是专⽤的通⽤寄存器到特殊功能寄存器的指令,与mrs对应。

@上⾯的指令实现了两个功能,1.屏蔽外部中断(IRQ)和快速中断(FIQ),2.把系统设为SVC32状态(超级保护),即M4~M1=10011,管理模式。

@mrs:状态寄存器到通⽤寄存器的传送指令
@msr:通⽤寄存器到状态寄存器的传送指令
(11)mrc p15, 0, r0, c1, c0, 0
@读协处理器中的寄存器数据到ARM处理器的r0⾥⾯。

应该是ARM访问MMU,⼀般cp15就是MMU。

(12)mcr p15, 0, r0, c1, c0, 0
@保存r0到控制寄存器
(13)什么是icache?
缓存(cache)是主存(DARAM)和CPU之间设置的⼀个⾼速的、容量相对较⼩的存储器,把正在执⾏的指令地址附近的⼀部分指令或数据从主存调⼊这个存储器,供CPU在⼀段时间内使⽤,以提⾼程序的运⾏速度。

出于对简化设计的考虑,也为了提⾼系统的性能,设计采⽤了指令Cache(icache)、数据Cache(dcache)分开的⽅式。

在icache中存储有微处理器需要的指令,在微处理器的取指阶段,通过程序计数器PC提供给icache的地址,微处理器可以获取需要的指令;⽽dcache则是作为⼀个数据的存储,并提供对于Load/Store指令所要操作地址的数据,它地址则来⾃于ALU运算的结果。

MRC指令是将协处理器寄存器中的数据传输到ARM处理器寄存器中,若协处理器未能完成操作,则产⽣未定义的异常。

MCR指令是将ARM处理器寄存器中的数据传输到协处理器寄存器中,未能成功执⾏将产⽣未定义的错误。

(14)逻辑左移(LSL)=算数左移( ASL),丢弃最⾼位,往左移位,右边空出来的位置补个0,。

逻辑右移(LSR),丢弃最低位,向右移动,左边空出来的位置补个0,算数右移(ASR),最⾼位填充符号位,正数填充0,负数填充1。

⽰例;1010101010
逻辑左移⼀位(LSL):
010101010[0]
算数左移⼀位(ASL):
010101010[0]
逻辑右移⼀位(LSR):
[0]101010101
算数右移⼀位(ASR):
[1]101010101
(15)r3, r1, r3, LSR #13
@r3进⾏逻辑右移13位之后的值加上r1,他们的和赋给r3.
(16)cmp r1,r3
ble line_loop
@e就是上⼀条指令的判断结果,如果前⾯的指令判断结果为相等,就执⾏bl指令,调⽤⼦程序,不相等就继续往下执⾏。

(17)blt way_loop
@相当于⼀个跳转指令
(18)and r0, r0, #0xf
@保持r0的0、1、2、3位,其余的清零。

r0与00001111相与,任何数与1相与不变,与0相与就变成0,所以就0、1、2、3位不变,其他的全部清零。

(19)cmp r0, #0
beq main_cpu
@当cmp的结果为0时,程序会跳到beq后的标签处执⾏,否则继续往下执⾏。

@bne指令,也是紧跟着cmp指令,当cmp的结果为1的时候,程序就会跳到bne后⾯的标签处执⾏,否则往下执⾏,与beq刚好相反。

(20)str r1, [r2 , #0x0]
@str指令⽤于从源寄存器中将⼀个32位的⼦数据传送到存储器中,使⽤⽅法与ldr相似。

将r1中的数据写到r2+0位地址的存储器中。

@str r0,[r1],#8//将r0中的⼦数据写⼊到以r1为地址的存储器中,并将新地址r1+8写⼊r1。

@str r1,[r0]将r1寄存器的值,传送到地址值为r0的(存储器)内存中
(21)adr r0, _start
@将_start的相对地址移动到r0,相对地址是以程序计数器pc的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址,与位置⽆关,只要是看boot是在哪⾥开始运⾏的,即pc指向哪⾥。

@ldr操作的是绝对地址
(22)bl _scu_disable
@bl跟b都是跳转指令,bl在跳转之前会将下⼀条指令拷贝到R14(LR,链接寄存器),由于bl保存了下条指令的地址,因此可以使⽤指
令“mov pc,lr”进⾏⼦程序的返回,b指令则⽆法返回,只能是单纯的跳转。

@blx指令⽤于从arm指令集跳转到指令中所指定的⽬标地址,并将处理器的⼯作状态从arm切换到thumb状态,该指令同时将pc当前的内容存储到存储器R14中。

@bx指令⽤于跳转到指令所指定的⽬标地址,⽬标地址既可以是arm指令也可以是thumb指令。

(23)bx lr
@该指令等同于mov pc,lr,即跳转到lr存放的地址处。

lr是连接寄存器,在arm中lr有两种⽤途,⼀个是⽤来存储⼦程序的返回地址,另⼀个是异常发⽣时,lr中保存的值等于异常发⽣时pc的值减4或者减2,因此在各种异常模式下可以根据lr的值返回到异常发⽣前的相应位置继续执⾏。

(24)mvn r0,#0
@mvn指令与mov差不多,区别是在赋值的时候先按位取反。

mvn r0,#4,执⾏之后的结果r0==-5,先将4转化成⼆进制(00000100),取反(11111011),求其补码,因为是负数,所以先对其正数(01111011)求反(10000100),然后加⼀(10000101)=-5。

负数的补码求法:对其正数取反+1。

(25)ldmia r0!, {r3 - r10}
stmia r1!, {r3 - r10}
@stmdb和dmia指令⼀般配对使⽤,stmdb⽤于将寄存器压栈,ldmia⽤于将寄存器弹出栈,作⽤是保存使⽤到的寄存器。

@ldmia r0!, {r3 - r10}//将r3⾄r10弹出栈
@stmia r1!, {r3 - r10}//r0=r0-4,先压r10,sp=r10(即将r10中内容放⼊到r0所指向的地址中);r0=r0-4,再压r9,r0=r9....最后压r3,r0=r3。

(26)orr r0, #(1<<8)
@1左移8位之后再进⾏操作
(27)tst r0,#(1<<6)
@将寄存器与另外⼀个寄存器的内容进⾏按位与运算,根据结果更新cpsr的值,⼀般⽤来检测是否设定了特定的位。

uboot第⼀阶段的⼯作:
(1)构建异常向量表
(2)设置cpu模式为svc模式
(3)开发板供电置锁
(4)时钟初始化
(5)DDR初始化
(6)串⼝初始化
(7)重定位
(8)建⽴映射表并开启mmu
(9)初始化全局变量
(10)初始化堆内存
(11)初始化外部存储设备
(12)获取ip地址和mac地址
(13)进⼊main_loop循环。

相关文档
最新文档