嵌入式程序设计基础(ARM9)

一.伪指令

1.数据定义伪指令
DCB 字节分配
DCW/DCWU 半字(2字节)分配
DCD/DCDU 字(4字节)分配
DCQ/DCQU 8个字节分配
SPACE 分配一块连续的存储单元

(1)DCB
格式:标号 DCB 表达式
说明:分配一块字节单元,用表达式值初始化
表达式:使用双引号的字符串,或0~255的数字。
DCB可用“=”代替。
例:
Array1 DCB 1,2,3,4,5 ;数组
str1 DCB "Your are welcome!" ;构造字符串并分配空间

(2)DCW/DCWU
例:
Arrayw1 DCW 0xa,-0xb,0xc,-0xd
;构造固定数组,分配半字存储单元

(3)DCD/DCDU
例:
Arrayd1 DCD 1334,234,245435 ;构造数组,并分配字存储单元
Label DCD Str1 ;该字单元存放str1的地址

(4)DCQ/DCQU
例:
Arrayd1 DCQ 234234,98765541
;构造数组,分配字单元存储空间
;注:DCQ不能给字符串分配空间

(5)SPACE
格式:标号 SPACE 表达式
说明:分配一片连续的存储区域,初始化为0。
表达式:要分配的字节数
SPACE也可以用”%”代替
例:freespace SPACE 1000 ;分配1000字节的存储空间

2.ALIGN
格式:ALIGN [表达式[,偏移量]]
说明:通过填充字节,使当前的位置满足一定的对齐方式。
表达式:表达式的值为2的n次幂, 0≤n≤31,如1、2、4、8、16等,用于指定对齐方式。
没有表达式:默认,字对齐。
偏移量:数字表达式,自动对齐到“表达式值+偏移量”
例:

B  START
ADD R0,R1,R2		
DATA1 DCB "abcde"	
ALIGN 4			
START LDR R5,[R6]

3.AREA
格式: AREA 段名 属性,……
功能:定义段。
说明:如果段名以数字开头,那么该段名需用“|”字符括起来,如|7wolf|,用C的编译器产生的代码一般也用“|”括起来。
属性:表示该代码段/数据段的相关属性,多个属性用“,”分隔。
常见属性如下:

  • DATA:定义数据段。
  • CODE:定义代码段。
  • READONLY:表示本段为只读。
  • READWRITE:表示本段可读写。
  • ALIGN=表达式,表达式的值为2的n次幂。
  • COMMON属性:定义一个通用段,这个段不包含用户代码和数据。

注意:一个程序至少包含一个段,可以有多个数据段,多个代码段。
例:AREA test,CODE,READONLY

4.ENTRY
功能:指定汇编程序的入口

5.END
功能:告诉编译器源程序结束

6.EQU
格式:名称 EQU 表达式 [,类型]
功能:等值。
说明:将程序中的数字常量、标号、寄存器值等赋予一个等效的名称,这一点类似于C语言中的#define。
如果表达式为32位的常量,可以指定表达式的数据类型,类型域可以有以下3种:CODE16、CODE32、DATA。
可用“*”代替EQU。
例:

num1    EQU 1234    ;定义num1为1234
addr5   EQU str1+0x50       
d1      EQU 0x2400,CODE32   
;定义d1的为0x2400,
;且该处为32位的ARM指令

7.GET
格式:GET 文件名
说明:将一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置展开进行汇编处理。
使用方法:在某源文件中定义一些宏指令,用MAP和FIELD定义结构化的数据类型,用EQU定义常量的符号名称,然后用GET将这个源文件包含到其他的源文件中。
使用方法与C语言中的“#include”相似。
GET只能用于包含源文件,包含其他文件则需要使用INCBIN伪指令。
例:

AREA	mycode,DATA,READONLY
GET	E:\code\prog1.s	
;通知编译器在当前源文件
;包含源文件E:\code\ prog1.s
GET  	prog2.s	         		
;通知编译器当前源文件包含
;可搜索目录下的prog2.s
...
END 

8.INCBIN
格式:INCBIN 文件名
说明:将一个数据文件或者目标文件包含到当前的源文件中,编译时被包含的文件不作任何变动地存放在当前文件中,编译器从后面开始继续处理。
例:

AREA	constdata,DATA,READONLY
INCBIN	data1.dat	
;源文件包含文件data1.dat
INCBIN 	E:\DATA\data2.bin
;源文件包含文件E:\DATA\data2.bin
...
END 

9.IMPORT

10.EXPORT

11.ADR 小范围地址读取
格式:ADR{<cond>} <Rd>,<expr>
功能:基于PC相对偏移的地址值(expr 地址表达式)->Rd
例:

LOOP MOV R1,#OXF0
     ADR R2,LOOP
;将LOOP的地址放入R2

12.ADRL 中等范围地址读取
格式:ADRL{<cond>} <Rd>,<expr>
功能:类似于ADR, 但比ADR读取更大范围的地址
例:

  ADRL R0,DATA_BUF
  ADRL R1,DATA_BUF+80
DATA_BUF
  SPACE 100  ;定义100字节缓冲区

13.LDR 大范围地址读取
格式:LDR{<cond>} <Rd>,<=expr/label-expr>
说明:32位的立即数或一个地址值→Rd。
注:
(1)若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令;否则汇编器将常量放入文字池(从PC到文字池的偏移量必须小于4 KB),并使用一条程序相对偏移的LDR指令从文字池读出常量。
(2)与ARM指令的LDR相比,伪指令的LDR的参数有”=”符号。

例:

LDR R0,=0x12345678      ;加载32位立即数0x12345678
LDR R0,=DATA_BUF+60     ;加载DATA_BUF地址+60
...
LTORG  ;声明文字池
...

14.NOP空操作
功能:不产生任何有意义的操作,只是占用一个机器时间
注:NOP在汇编时将会被替代成ARM中的空操作,比如可能为”MOV R0,R0″指令等。

二.汇编语言语句格式

语句格式

三.汇编程序设计示例

1.基本结构

AREA  example,CODE,READONLY     ;定义代码段为example
      CODE32 	
      ENTRY 			;程序入口
Start		
	MOV R0,  #40		;R0=40
	MOV R1,  #16		;R1=16 
	ADD R2,  R0,  R1        ;R2= R0 +R1
	MOV R0,  #0x18		;传送到软件中断的参数
	LDR R1,  =0x20026	;传送到软件中断的参数
	SWI 0x123456		;通过软件中断指令返回
	END 			;文件结束

2.子程序调用

AREA    Init,CODE,READONLY ;定义一个代码段
	ENTRY  		   ;定义一个程序入口
LOOP1	
        MOV R0, #211	        ;给参数R0赋值211
	MOV R1, #106	        ;给参数R1赋值106
	MOV R2, #64		;给参数R2赋值64
	MOV R3, #5		;给参数R3赋值5
	BL SUB1  		
        ;调用子程序SUB1
        ;同时将子程序的返回地址存放在链接寄存器R14(LR)中
	MOV R0, #0x18	        ;传送到软件中断的参数
	LDR R1, = 0x20026	;传送到软件中断的参数
	SWI 0x123456		;通过软件中断指令返回
SUB1	
        SUB R0, R0, R1	        ;子程序代码
	SUB R0, R0, R2	
	SUB R0, R0, R3	
        MOV PC, LR		;从子程序返回
	END

3.条件执行举例

C语言代码:

int gcd(int a,int b)
{
	while(a!=b){
		if(a>b)
			a=a-b;
		else
			b=b-a;
	}
	return a;
}

ARM代码段:

R0=a,R1=b
gcd
  CMP R1,R1         ;比较a和b大小
  SUBGT R0,R0,R1    ;if (a>b) a=a-b (if a==b do nothing)
  SUBLT R1,R1,R0    ;if (b>a) b=b-a (if a==b do nothing)
  BNE gcd           ;if (a!=b) then 跳转到gcd处继续执行
  MOV PC,LR         ;子程序结束,返回

c语言代码:

if(a==0 || b==1)
 c=d+e;

ARM代码段:

CMP R0,#0       ;判断是否等于0
CMPNE R1,#1     ;如果R0不等于0,判断R1是否等于1
ADDEQ R2,R3,R4  ;R0=0或R1=1时,R2=R3+R4

4.循环语句

  MOV R0,#loopcount
loop
  ...
  SUBS R0,R0,#1
  BNE loop

四.在C/C++程序中内嵌汇编指令的语法格式

在ARM的C语言程序中可以使用关键字__asm来加入一段汇编语言的程序。

__asm
{
   instruction/*comment*/
   ...
}

示例:

#include <stdio.h>
void my_strcpy (const char *src, char *dest) 	//声明一个函数
{
	char ch;   			//声明一个字符型变量。
	__asm   			//调用关键词__asm。
	{
	  LOOP  			//循环入口。
	    LDRB ch,[src],#1  	// ARM指令,ch←[src], src ←src +1。
	    STRB ch,[dest],#1	// ARM指令, [dest]←ch,[dest]←[dest]+1。
	    CMP ch,#0		// 比较ch是否为零,判断字符串是否结束。		 
            BNE LOOP		// NE为不相等条件, ch是否为零,否则循环。
	}
}

Related post

  1. 将python脚本挂至服务器后台自动运行

    2020-07-05

  2. Leetcode Java常用代码

    2024-02-17

  3. 设计模式-工厂模式

    2020-09-09

  4. attention model

    2020-07-26

There are no comment yet.

COMMENT

Take a Coffee Break

Recommend post

  1. 常用工具指令

    2022-09-18

Category list

ABOUT

Welcome to FullStar, a captivating online destination where the realms of software development and personal reflections intertwine.

April 2025
M T W T F S S
 123456
78910111213
14151617181920
21222324252627
282930  

Life Logs

  1. 回首

    2023-07-14

Return Top