搞不懂为什么学校开嵌入式用汇编……
第一次实验:寻址方式使用练习
1 | N EQU 9 |
第二次实验:汇编指令使用练习
一、实验目的:
1、 寻址方式巩固练习
2、 练习汇编指令
3、 掌握指令的条件
二、实验要求:
1、认真阅读电子版教材;
2、按照课件学习汇编指令;
3、书写实验报告。
三、实验原理
ARM指令助记符格式如下:
<opcode> {<cond>} {S} <Rd>, <Rn>, <shift\_op2>
< >内项目是必需的, { }内项目是可选的
①
② {
③ {S}:指令后加S,在指令完毕后会自动更新CPSR中的条件码标志位的值。
④
⑤
⑥ <shift_op2> :第二个操作数,可是寄存器也可是立即数等。
指令助记符编译后的机器码格式如下:
1、条件码
几乎所有指令均根据CPSR中条件码的状态和指令条件码域的设置有条件地执行。当指令执行条件满足时,指令被执行,否则被忽略。指令条件码及其助记符后缀表示如下表所示。
2、指令中第2个操作数<shift_op2>
第二个操作数,可以是一个寄存器,也可以是一个立即数,还可以是一个寄存器与移位操作组成,移位操作包括如下5种类型。
LSL:逻辑左移(Logical Shift Left)。寄存器中字的低端空出的位补0。
LSR:逻辑右移(Logical Shift Right)。寄存器中字的高端空出的位补0。
ASR:算术右移(Arithmetic Shift Right)。算术移位的对象是带符号数。在移位过程中必须保持操作数的符号不变。若源操作数为正数,则字的高端空出的位补0;若源操作数为负数,则字的高端空出的位补1。
ROR:循环右移(ROtate Right)。从字的最低端移出的位填入字的高端空出的位。
RRX:扩展为1的循环右移(Rotate Right eXtended by 1 place)。操作数右移1位,空位(位[31])用原C标志填充。
3、加载/存储指令
格式:LDM(或STM){类型} 基址寄存器{!},寄存器列表{∧}
功能:LDM(或STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈或出栈。其中,{类型}为以下几种情况。
IA:每次传送后地址加4。
IB:每次传送前地址加4。
DA:每次传送后地址减4。
DB:每次传送前地址减4。
FD:满递减堆栈。
ED:空递减堆栈。
FA:满递增堆栈。
EA:空递增堆栈。
四、实验内容
1、指令条件实验练习
1 | AREA EXAMPLE,CODE,READONLY |
2、加载/存储指令
1 | AREA example,CODE,READONLY |
3、数据处理指令
1 | area example,code,readonly |
第三次试验汇编程序设计练习
一、实验目的:
1、 使用ADS调试汇编程序
2、 学习汇编程序设计
二、实验要求:
1、认真阅读电子版教材;
2、按照课件学习汇编程序设计;
3、书写实验报告。
三、实验原理
上次实验中在调试过程中可利用反汇编查看编译后的对应的机器语言编码。
下图中的Ro Base的值就是设置编译后机器码存放的只读存储器的首地址。
ARM指令的机器语言编码由32位二进制代码组成,这些二进制代码的含义如下图所示:
数据处理的指令的opcode([24:21])域二进制代码表示的含义如下图所示,其中s域表示要不要修改CPSR的标志位,Rn代表目录寄存器编号,Rd代表着第一个操作数的寄存器编号,operand2代表第2个操作数。
2、汇编语言
汇编语言用助记符书写,助记符由指令助记符、伪操作助记符和伪指令助记符组成。指令助记符有一一对应的机器编码,伪指令助记符由编译器编译成机器编码,而伪操作助记符只是起到控制编译的作用,并不对应的机器编码。有时把伪操作和伪指令统称为伪指令。
ADS中常用的伪指令
上次实验中在调试过程中可利用反汇编查看对应的机器码。例如“LDR R0,=N” 编译后用“mov r0,#9”替代;“LDR R4,=0X30000000”编译后用“ mov r4,#0xc0, 10 ”替代;“LDR SP,=0X3200000C ”编译后用“ ldr r13,0x0000804c ”替代。但程序中的AREA、END等伪操作找不到有对应的机器码。
3、汇编语言程序结构
按程序执行的流程可分为顺序程序、分支程序、循环程序和子程序等类型。任何复杂的程序结构可看作这些基本结构的组合。例如实验6的例程就属于顺序程序结构。
ARM汇编中大部分的指令都支持条件执行,因此类似C语言中的if-else分支很容易实现。
例: CMP R1,#3 ; 比较R1和#3
1 | ADDHI R0,R0,R1 ; if R1>3 then R0=R0+R1 |
ADDLS R0,R0,#3 ; if R1<3 then R0=R0+3
B、BL可以条件执行,从而构成复杂的分支架构。
例:
CMP R1,#3 ; 比较R1和#3
BHI END ; if R1>3 then END
ADD R0,R0,#3 ; R0=R0+3
END
用预先设定的标号与B、BL结合可以设计各种循环结构。
例:
LOOP
ADD R0,R0,R1 ; R0=R0+R1
CMP R0,#3 ; 比较R0和#3
BLS LOOP ; if R0<3 then 跳转到LOOP 循环
在ARM汇编语言程序中,子程序的调用一般是通过BL指令来实现的。
格式:BL 子程序名
该指令在执行时完成如下操作:将子程序的返回地址存放在连接寄存器LR中,同时将程序计数器PC指向子程序的入口点,当子程序执行完毕需要返回调用处时,只需要将存放在LR中的返回地址重新复制给程序计数器PC即可。在调用子程序的同时,也可以完成参数的传递和从子程序返回运算的结果,通常可以使用寄存器R0~R3完成。
例: 调用子程序。子程序doadd完成加法运算,操作数放在R0和R1寄存器中,结果放在R0中。
1 | ENTRY |
1 | 【例】 实现1+2+……+N。 |
四、实验内容
1、把实验原理中的程序补全后在ADS中验证;
2、验证伪指令;
3、打开C:\Program Files\ARM\ADSv1_2\Examples\asm文件夹,查看其中的实例。
1 | 【例1】 |
1 | 【例2】 |
第四次实验:ARM C程序设计
一、实验目的:
1、 学习ARM的C语言程序编写方法
2、 学会使用ADS软件调试C语言程序
二、实验要求:
1、认真阅读电子版教材;
2、按照课件学习学习在ADS中调试C程序;
3、书写实验报告。
三、实验原理
映像文件(image):是指一个可执行文件,在执行的时候被加载到处理器中。一个映像文件有多个线程,是ELF(Exccutable and linking format)格式的。
段(Scction):描述映像文件的代码或数据块。
RO段包括程序中的指令和常量,属性是readonly
RW段包括程序中的已初始化变量 ,属性是read/write
ZI段是程序中的以0初始化的变量 。
ADS1.2手册给出的默认存储器映像如下图所示,其中heap为堆,stack为堆栈:
由于程序一般放在只读存储器中,但只读存储器只能读不能写,而且读取速度慢,故程序在运行时往往需要把只读存储器的程序和数据加载到读写存储器中,并设置堆区及堆栈区,以便存放程序运行时产生的数据。
ADS在运行时,会自动加系统定义的main函数,该函数主要完成程序和数据的复制、以及产生ZI;然后系统建立堆和堆栈、初始化库函数后才进入用户编写的主函数。
为了能系统顺利进入用户编写的主函数,需要用汇编语言编写启动引导代码(有些软件如keil可针对不同芯片可以自动加载启动代码),当然用户代码的主函数也可以不用main命名,有些书为了加以区分系统主函数,以Main命名,本次实验是以ledmain命名。
1 | IMPORT ledmain |
IMPORT伪操作告诉编译器ledmain在别的文件中定义,在此文件中引用,用global 伪操作表示start是一个全局标号。
本次实验是用C语言编写控制led小灯的程序,硬件电路连接如下图, s3c2410的GPF端口的7:4位接LED小灯,arm处理器相应端口输出低电平,LED灯亮,高电平灯灭。首先需要将这个端口配置成输出端口,然后通过配置去掉内部的上拉阻,最后通过给端口送0或1达到亮灭的目的。
s3c2410的GPF端口的
配置寄存器的地址为:0x56000050
数据寄存器地址为:0x56000054
上拉电阻控制寄存器地址为:0x56000058
四、实验内容
1、创建工程项目
2、添加设计文件
(1)先用编写如下的汇编语言文件,并起名为init.s并添加到工程中。
1 | IMPORT ledmain |
(2)编写C语言源程序
1 |
|
3、编译和链接前设置
部分设置可参考实验六。
4、编译和链接项目工程
5、调试
打开反汇编,可以看到存储器的0x8000处的指令是bl ledmain,并且给此存储地址起名为start。程序代码地址与编译器设置有关。
存储器分配情况的:
0x8004-0x8018:portinit子程序
0x801c-0x8040:ledon子程序
0x8044-0x808c:ledoff子程序
0x8090-0x80a4:ledonoff子程序
0x80a8-0x80bc:ledmain程序
用单步运行,可以看到c程序与对应汇编程序之间的关系以及GPF端口数据变化情况。
五、实验报告要求
1、以报告的形式总结实验过程;
2、总结如何使用ADS调试C程序。