【MIPS】--- 教你看懂MIPS架构的基本汇编程序(全是干货)
作者:互联网
使用龙芯Ls2k1000系列处理器,遇到内存的问题,真的是百般刁难。要梳理内存初始化流程,然后最麻烦的是龙芯的内存乃代码全是汇编源码,看起来着实有点头疼,被汇编按在地上摩擦了无数回后,也算是对汇编有个基本的认识。接下来用一篇文档教你如何快速入门看懂龙芯MIPS的汇编源码!
按照国际惯例,先抛问题
1. 汇编常用指令
2. MIPS架构处理器的寄存器简析
3. 汇编语法总结
4. 基本的编程思想
问题一:汇编常用指令
这里我就不一一介绍了,龙芯的GS265_user_Guid中对大多数指令已有了简单的介绍,直接查阅即可。
有人说,汇编早已淘汰,属于计算机历史上侏罗纪时代的古董产物;还有人说,汇编是让你深刻理解计算机处理机制的神兵利器。
个人感觉,争执这种问题都是瞎扯。对于汇编这种语言,要求自己能看懂即可。简单概括,一次看懂,终身受益。不同处理器无非指令不一样,但是汇编处理的逻辑和方式都一样。因此,各位看官要好好理解本文哦。
问题二:MIPS架构处理器的寄存器简析
1. 通用寄存器
MIPS32架构定义了32个通用寄存器,使用$0、$1……$31表示,都是32位。其中$0一般用做常量0,具体的用法可以参考下图。
这其中你最常用的应该就是a0-a3, t0-t9, s0-s7,编程中的变量运算等等,都离不开这些寄存器。
2. 特殊寄存器
MIPS32架构中定义的特殊寄存器有三个:PC(Program Counter程序计数器)、HI(乘除结果高位寄存器)、LO(乘除结果低位寄存器)。进行乘法运算时,HI和LO保存乘法运算的结果,其中HI存储高32位,LO存储低32位;进行除法运算时,HI和LO保存除法运算的结果,其中HI存储余数,LO存储商。
3. MIPS架构属于小端模式,具体什么是小端,参考之前的一篇文章
问题三: 汇编语法总结---直接以LS2k代码为例进行实战讲解
1. 标号1,2,3……,这些标号什么意思,如何理解?
标号的意思基本可以理解为打个标签,方便汇编代码执行跳转指令。
2. 标号用途详解
汇编不同于C,没有那么智能,仅能顺序执行,但代码逻辑必定不能线性执行。我们以循环执行nop空与语句为例进行说明:
C编程,如下:
汇编编程,如下:
含义解释如下:
dli : 取双字常数装载到a3寄存器
subu: 无符号减,等于于 a3=a3-1
nop : 空操作,一般用于短延时
Bgtz: 大于0,则跳转
通过上述例子,应该能理解这些一大堆标号的意思,其中跳转是有时会看到1b,1f, 1b表示向上跳转至标号为1的代码处执行;1f表示向下跳转至标号为1的代码处执行,一般都是同一个函数内由于代码执行逻辑非线性,才会用这种简单的标号表示。如果类似于高级编程语言那种函数的话,一般会重新封装一个函数来做,这是你看到的标号,就不是简单的数字,有可能就是自己起的名字了。
问题四: 汇编实战练习
想实际理解汇编代码,最简单的方式,实战来个程序即可。接下来以我自己写的一个例子进行讲解。当内存控制器中的某个寄存器值为0x68,则执行拉低GPIO的操作。
1. 问题背景,内存Training是GateLeveling过程中,需要进行8个Byte的PreambleCheck,这个preaam_check_init函数将会被循环执行8次,每次执行会改变的变量是dll_gate寄存器地址。实际测量得dll_gate2寄存器校验出错,因此在开始进行dll_gate2值校验之前,我要拉低一个GPIO作为触发信号,然后进行信号测量。
2. dll_gate寄存器的地址大致如下:
3.判断0x68寄存器的值,符合条件则跳转的代码如下:
1) t1含义解释:t1表示得是dll_gate得地址,也就是从0x38, 0x58, 0x78……等
2) 红框内代码解释:
line1: 将t1得知放进a0(别问为啥,因为没有为啥), 此时a0表示当前正在校验得dll_gate地址
line2: a0 = a0&0xff, 仅保留低2位。因为目标地址是0x78,放置高位垃圾值影响我得判断
line3: If a0==0x68, 跳转至inspur_gpio_test这个函数下执行
4. inspur_gpio_test的程序如下,分为五步解释:
Tips: 明确我们得目的是将GPIO27信号进行拉低拉高,产生跳变,先理解GPIO相关得寄存器如何配置:
接下来进行代码分析(分成了五个小块):
1)设置GPIO方向寄存器
1 li t4, 0xbfe10500 //将0xbfe10500这个地址装载到t4寄存器 2 lb t6, 0x3(t4) //将0xbfe10500+3这个地址得单Byte值装载到t6 3 and t6, t6, 0xf7 //t6 = t6&0xf7 (这步就是设置GPIO270为输出模式的操作) 4 sb t6, 0x3(t4) //将设置后的t6写入到寄存器中
Tips:
问题1: 0x3(t4)这种书写表示什么意思?
答: 简单可以理解一个地址操作,就是t4地址再便宜0x3
问题2. and t6, t6, 0xf7为何是清0操作?
答:根据龙芯手册表述,GPIO方向控制寄存器位阈为[63:0],也就是8个Byte,从低到高,每个bit表示一个GPIO,因此GPIO27应该是0xbfe10500这个起始位置的第27个bit,基本表示如下:
2)设置GPIO27输出低电平
1 li t4, 0xbfe10510 //将GPIO电位设置寄存器的基地址放入t4 2 lb t6, 0x3(t4) //将0xbfe10510+3的地址的单byte数据放入t6寄存器 3 and t6, t6, 0xf7 //将GPIO27的bit清0,使得GPIO27输出低 4 sb t6, 0x3(t4) //将t6的值保存至对应寄存器中
3)延时,前面举过例子,这里不做详解
1 dli a3,0xff //delay 2 1: 3 subu a3, 0x1 4 nop 5 bgtz a3, 1b
4)设置GPIO27输出为高(由于前面已将GPIO电位设置寄存器地址放进t4,且没有修改,这里可直接用)
1 lb t6, 0x3(t4) //参考问题三中以延时函数举例的说明 2 ori t6, t6, 0x08 3 sb t6, 0x3(t4)
5)函数执行完毕,跳回到之前的位置继续向下执行
1 PRINTSTR("\r\n start inspur GPIO end\r\n") 2 b Inspur //跳转至Inpsur标签位置继续执行
通过这样的例子,希望能更加清楚的让各位了解汇编代码的执行,不同架构处理器区别仅在于指令不一样。但是汇编的执行流程和逻辑均类似,可以对比学习
如有其他问题,请直接回复留即可,我看到后会尽快和您交流。
也欢迎您关注我的个人公众号,一起成长,一起交流。
如有需要龙芯MIPS架构指令手册文档的,关注我的公众号后,回复"MIPS指令",自动获取。
标签:汇编,GPIO,t6,t4,跳转,汇编程序,干货,寄存器,MIPS 来源: https://www.cnblogs.com/szhb-5251/p/13091460.html