嵌入式 ARM 汇编编程例题 - Go语言中文社区

嵌入式 ARM 汇编编程例题


文章目录

用汇编语言实现 128 位数的减法。

第一个 128 位数由高到低位于 R7~R4 中
第二个 128 位数由高到低位于 R11~R8 中

SUBS	R0,R4,R8
SBCS	R1,R5,R9
SBCS	R2,R6,R10
SBC		R3,R7,R11

已知 32 位变量 X、Y 存放在存储器的地址 0x90010、0x90014 中,要求实现 Z=X+Y,其中 Z 的值存放在 0x90018 中

	   AREA EX4_41,CODE,READONLY
       ENTRY
       CODE32
START  LDR R0,=0x90010       ;变量 X 的地址送入 R0
       LDR R1,[R0],#4        ;变量 X 的值读入 R1
       LDR R2,[R0],#4        ;变量 Y 的值读入 R2
       ADD R1,R1,R2          ;X+Y 结果存入 R1
       STR R1,[R0]           ;结果存入 z 中
       B START
       END   

已知 32 位有符号数 X 存放在存储器的地址 0x90010 中,要求实现:

在这里插入图片描述
其中 Y 的值存放在 0x90010 中

	   AREA EX4_42,CODE,READONLY
       ENTRY
       CODE32
START  LDR R1,=0x90010       ;加载变量 X 的地址->R1
       MOV R0,#0             ;0->R0
       LDR R2,[R1]           ;将 X 的值加载到 R2
       CMP R2,#0             ;X 与 0 比较 , 影响标志位
       SUBLT R2,R0,R2        ;X<0 执行该语句 , 提到-X
       STR R2,[R1]           ;保存结果
       B START
       END

已知 32 位有符号数 X 存放在存储器的地址 0x90010 中,要求实现

在这里插入图片描述
其中 Y 的值存放在 0x90010 中。

	   AREA EX4_43,CODE,READONLY
       ENTRY
       CODE32
START  LDR R1,=0x90010       ;加载变量 X 的地址->R1
       LDR R2,[R1]           ;加载 X 的值->R2
       CMP R2,#0             ;与 0 比较
       BEQ ZERO              ;为 0 则跳转到 ZERO 处理
       BGT PLUS              ;大于 0 则跳转到 PLUS 处理
       MOV R0,#-1            ;否则小于 0, 将 R0 设置为-1
       B FINISH              ;跳转到结束
PLUS   MOV R0,#1             ;大于 0, 将 R0 设置为 0
       B FINISH              ;跳转到结束
ZERO   MOV R0,#0             ;等于 0, 将 R0 设置为 0
FINISH STR R0,[R1]           ;将结果 R0 保存
       B START
       END 

多分支 ARM 汇编的程序

	   AREA EX4_44,CODE,READONLY
       ENTRY
       CODE32
START  CMP R0,#8             ;与 8 比较
       ADDLT PC,PC,R0,LSL#2  ;小于 8 则根据 R0 计算跳转地址 ,
                             ;并用该地址修改 PC      
       B method_d            ;大于 8 程序跳转到默认分支段执行
       B method_0            ;分支表结构 , 其偏移量由 R0 决定
       B method_1
       B method_2
       B method_3
       B method_4
       B method_5
       B method_6
       B method_7
method_0                     ;method_0 的入口
       MOV R0,#1             ;method_0 的功能
       B end0
method_1                     
       MOV R0,#2             
       B end0
method_2                     
       MOV R0,#3             
       B end0
method_3                     
       MOV R0,#4             
       B end0
method_4                     
       MOV R0,#5             
       B end0
method_5                     
       MOV R0,#6             
       B end0
method_6                     
       MOV R0,#7             
       B end0
method_7                     
       MOV R0,#8             
       B end0
method_d                     
       MOV R0,#0             
end0   B START
       END

编制程序使 S=1+2×3+3×4+4×5+……+N(N+1),直到 N 等于 10 为止。

	   AREA EX4_45,CODE,READONLY
       ENTRY
       CODE32
START  MOV R0,#1             ;R0 用作累加 , 置初值 1,S
       MOV R1,#2             ;R1 用作第一个乘数 , 初值为 2,N
REPEAT ADD R2,R1,#1          ;R2 用作第二个乘数 ,N+1
       MUL R3,R2,R1          ;实现 N*(N+1) 部分积存于 R3
       ADD R0,R0,R3          ;将部分积累加至 R0
       ADD R1,R1,#1          ;修改 N 的值得到下一轮乘数
       CMP R1,#10            ;循环次数比较
       BLE REPEAT            ;未完则重复
       B START
       END

用汇编语言实现 1+2+3+…+N

CMP			R2,#1
			BEQ		SUM_END		; 若 N 的值为 1,则返回。			
			MOV		R1,#1		; 初始化计数器 R1=1
			MOV		R0,#0		; 初始化结果寄存器 R0=0
SUM_L1		ADD		R0,R0,R1		; R0 = R0 + R1
			BCS			SUM_ERR		; 结果溢出,跳转到 SUM_ERR		
			CMP		R1,R2		; 将计数器的值与 N 比较
			BHS		SUM_END		; 若计数器的值≥N,则运算结束
			ADD		R1,R1,#1
			B		SUM_L1
SUM_END

用 ARM 汇编语言编写完整的程序,实现 1+2+3+…+N

; 功能:计算 1+2+...+N 的值
; 说明:N≥0,当 N=0 时结果为 0;当 N=1 时结果为 1。
N			EQU		100				; 定义 N 的值为 100
			AREA	Example5,CODE,READONLY	; 声明代码段 Example5
			ENTRY				; 标识程序入口
			CODE32				; 声明 32 位 ARM 指令
ARM_CODE	LDR		SP,=0x40003F00	; 设置堆栈指针
            ADR		R0,THUMB_CODE+1
			BX		R0			; 跳转并切换处理器状态
			LTORG				; 声明文字池
			CODE16				; 声明 16 位 Thumb 指令 
THUMB_CODE	LDR		R0,=N		; 设置子程序 SUM_N 的入口参数
			BL		SUM_N		; 调用子程序 SUM_N
			B		THUMB_CODE
			
; 名称:SUM_N
; 功能:计算 1+2+...+N 的值
; 入口参数:R0		N 的值
; 出口参数:R0		运算结果
; 占用资源:R0
; 说明:当 N=0 时结果为 1;当 N=1 时结果为 1。若运算溢出,结果为 0。
SUM_N			
			PUSH	{R1-R7,LR}	; 寄存器入栈保护
			MOVS	R2,R0		; 将 N 的值复制到 R2,并影响条件码标志
			BEQ		SUM_END		; 若 N 的值为 0,则返回。(此时 R0 没有被更改)
			CMP		R2,#1
			BEQ		SUM_END		; 若 N 的值为 1,则返回。(此时 R0 没有被更改)
			MOV		R1,#1		; 初始化计数器 R1=1
			MOV		R0,#0		; 初始化结果寄存器 R0=0
SUM_L1		ADD		R0,R0,R1		; R0 = R0 + R1
			BCS			SUM_ERR		; 结果溢出,跳转到 SUM_ERR		
			CMP		R1,R2		; 将计数器的值与 N 比较
			BHS		SUM_END		; 若计数器的值≥N,则运算结束
			ADD		R1,R1,#1
			B		SUM_L1
SUM_ERR		MOV		R0,#0			
SUM_END		POP		{R1-R7,PC}	; 寄存器出栈,返回
			END	

编写汇编程序计算 X!的值

X			EQU		9			; 定义 X 的值为 9
n			EQU		8			; 定义 n 的值为 8
			AREA	Example4,CODE,READONLY	; 声明代码段 Example4
			ENTRY			; 标识程序入口
			CODE32			; 声明 32 位 ARM 指令
START		LDR		SP,=0x40003F00		; 设置堆栈 (满递减堆栈,使用 STMFD/LMDFD 指令)
			LDR		R0,=X
			LDR		R1,=n
			BL		POW					; 调用子程序 POW,返回值为 R0
HALT		B		HALT	
; 名称:POW
; 功能:整数乘方运算。
; 入口参数:R0		底数
;          R1		指数
; 出口参数:R0		运算结果
; 占用资源:R0、R1
; 说明:本子程序不考虑溢出问题
POW			
			STMFD	SP!,{R1-R12,LR}		; 寄存器入栈保护
			MOVS	R2,R1				; 将指数值复制到 R2,并影响条件码标志
			MOVEQ	R0,#1				; 若指数为 0,则设置 R0=1
			BEQ		POW_END				; 若指数为 0,则返回
			CMP		R2,#1
			BEQ		POW_END				; 若指数为 1,则返回。(此时 R0 没有被更改)
			MOV		R1,R0				; 设置 DO_MUL 子程序的入口参数 R0 和 R1
			SUB		R2,R2,#1			; 计数器 R2 = 指数值减 1
POW_L1		BL		DO_MUL				; 调用 DO_MUL 子程序,R0 = R1 * R0
			SUBS	R2,R2,#1			; 每循环一次,计数器 R2 减 1
			BNE		POW_L1				; 若计数器 R2 不为 0,跳转到 POW_L1
POW_END		LDMFD	SP!,{R1-R12,PC}		; 寄存器出栈,返回  		
; 名称:DO_MUL
; 功能:32 位乘法运算。
; 入口参数:R0		乘数
;          R1    	被乘数
; 出口参数:R0		计算结果
; 占用资源:R0、R1
; 说明:本子程序不会破坏 R1
DO_MUL		MUL	 R0,R1,R0			; R0 = R1 * R0
			MOV	PC,LR				; 返回			
			END	

编制程序,求两个数组 DATA1 和 DATA2 对应的数据之和,并把和数存入新数组 SUM 中,计算一直进行到两数之和为零时结束,并把新数组的长度存于 R0 中。

	   AREA BlockData,DATA,READWRITE    ;定义数据段
DATA1  DCD 2,5,0,3,-4,5,0,10,9          ;数组 DATA1
DATA2  DCD 3,5,4,-2,0,8,3,-10,5         ;数组 DATA2
SUM    DCD 0,0,0,0,0,0,0,0,0            ;数组 SUM

       AREA Ex4_46,CODE,READONLY        ;定义代码段
       ENTRY      
       CODE32
START  LDR R1,=DATA1            ;数组 DATA1 的首地址存入到 R1
       LDR R2,=DATA2            ;数组 DATA2 的首地址存入到 R2
       LDR R3,=SUM              ;数组 SUM 的首地址存入到 R3
       MOV R0,#0                ;计数器 R0 的初始值置 0
LOOP   LDR R4,[R1],#04          ;取 DATA1 数组的一个数 , 同时修改地址指针
       LDR R5,[R2],#04          ;取 DATA1 数组的一个数 , 同时修改地址指针
       ADDS R4,R4,R5            ;相加并影响标志位
       ADD R0,R0,#1             ;计数器加 1
       STR R4,[R3],#04          ;保存结果到 SUM 中 , 同时修改地址指针
       BNE LOOP                 ;若相加的结果不为 0 则循环
       END 

在以 BUF 为首地址的字存储区中存放有 10 个无符号数 0x0FF, 0x00, 0x40, 0x10, 0x90, 0x20, 0x80, 0x30, 0x50, 0x70, 请将它们按从小到大的顺序排列在 BUF 存储区中,编写程序。

N EQU 10
       AREA EX4_47,CODE,READONLY
       ENTRY
       CODE32
START  LDR R0,=BUF              ;指向数组的首地址
       MOV R1,#0                ;外循环计数器
       MOV R2,#0                ;内循环计数器
LOOPI  ADD R3,R0,R1,LSL #2      ;外循环首地址放入 R3
       MOV R4,R3                ;外循环首地址放入 R4
       ADD R2,R1,#1             ;内循环计数器初值
       MOV R5,R4                ;内循环下一地址初值
       LDR R6,[R4]              ;取内循环第一个值 R4
LOOPJ  ADD R5,R5,#4             ;内循环下一地址值
       LDR R7,[R5]              ;取出下一地址值 R7
       CMP R6,R7                ;比较
       BLT NEXT                 ;小则取下一个
       SWP R7,R6,[R5]           ;大则交换 , 最小值 R6
       MOV R6,R7
NEXT   ADD R2,R2,#1             ;内循环计数
       CMP R2,#N                ;循环中止条件
       BLT LOOPJ                ;小于 N 则继续内循环 , 实现比较一轮
       SWP R7,R6,[R3]           ;否则内循环一轮结束
       ADD R1,R1,#1             ;外循环计数
       CMP R1,#N-1              ;处循环中止条件
       BLT LOOPI                ;小于 N-1 继续执行外循环
       B START

       AREA BlockData,DATA,READWRITE
BUF    DCD 0x0ff,0x00,0x40,0x10,0x90,0x20,0x80,0x30,0x50,0x70
       END

编写一程序,查找存储器从 0x400000 开始的 100 个字中为 0 的数目,将其结果存到 0x400190 中。

MOV R0,#0x400000      
MOV R1,#0      
MOV R7,#100 
LP    
LDR R2,[R0],#4      
CMP R2,#0      
BNE NEXT      
ADD R1,R1,#1
NEXT     
SUBS R7,R7,#1    
BNE LP    
STR   R1,[R0]    
B   $

用完整 ARM 汇编语言编写程序:使用 LDR 指令读取 0x40001000 上的数据,将数据加 3,若结果小于 100 则使用 STR 指令把结果写回原地址,若结果大于等于 100,则把 0 写回原地址。然后再次读取 0x40001000 上的数据,将数据加 1,判断结果是否小于 100 周而复始循环。

COUNT	EQU		0x40001000	; 定义一个变量,地址为 0x40001000	
		AREA	Example2,CODE,READONLY	; 声明代码段 Example2 
		ENTRY				; 标识程序入口
		CODE32				; 声明 32 位 ARM 指令
START	LDR		R1,=COUNT	; R1 <= COUNT
		MOV		R0,#0		; R0 <= 0 
		STR		R0,[R1]		; [R1] <= R0,即设置 [COUNT] 为 0
						
LOOP   	LDR		R1,=COUNT	
		LDR		R0,[R1]		; R0 <= [R1] 
		ADD		R0,R0,#3	; R0 <= R0 + 1
		CMP		R0,#100		; R0 与 100 比较,影响条件码标志
		MOVHS	R0,#0		; 若 R0 大于等于 100,则此指令执行,R0 <= 0
		STR		R0,[R1]		; [R1] <= R0,即保存 COUNT
		B		LOOP
		END	

用 ARM 汇编语言编写完整的子程序,该程序从 0x40001000 地址处连续读取 100 个字符,并将这 100 个字符复制到目的地址标号 DIST 处。

		AREA ||.text||,CODE,READONLY
DIST	DCB “123456789……01234567890”;100 个字符
		CODE 32
		ENTRY
MY _SUB  
        STMFD R13!,{R0-R3}
        MOV R0,=# 0x40001000
        LDR R1,= DIST
        MOV R2,#100
LOOP   
        SUBS R2,R2,#1
        LDRB R3,[R0],#1
        STRB R3,[R1],#1
        BNE  LOOP
        LDMFD R13!,{R0-R3}
        MOV PC,LR
        END

存储器从 0x400000 开始的 100 个单元中存放着 ASCII 码,编写程序,将其所有的小写字母转换成大写字母,对其它的 ASCII 码不做变换。

	MOV 	R0,#0x400000  
	MOV 	R1,#0 
LP  
	LDRB  R2,[R0,R1]   
	CMP R2,#0x61   
	BLO NEXT   
	CMP R2,#0x7B     ;0x7A 为 z   
	SUBLO  R2, R2,#0x20   
	STRBLO  R2,[R0,R1] 
NEXT   
	ADD R1, R1,#1   
	CMP R1,#100   
	BNE LP

编写一段 ARM 汇编程序:循环累加队列 rjarray 中的所有元素,直到碰上零值元素,结果放在 r4 中

		AREA  total,CODE,READONLY
		ENTRY
Start	MOV	r4,#0
		ADR	r0,rjarray

		Loop	LDR	r1,[r0],#4
		ADD	r4,r4,r1
		CMP	r1,#0
		BNE	loop
stop	B	stop

rjarray
		DCD	0x11
		DCD	0x22
		……
		DCD	0x0
		END

用汇编语言实现以下 C 语言语句 for(i=limit;i>=1;i–) {fact=fact*i}

fact     MUL R0,R1,R0
         SUBS R1,R1,#1
         BNE fact

用 ARM 汇编语言编写完整的 ** 子程序 **,该程序从 NN 地址处连续读取 20 个字符,并将这 20 个字符复制到目的地址标号 MM 处

	AREA  ||.text||,CODE,READONLY
NN	DCB 	“12345678901234567890”
MM	DCB 	“12345678901234567890”
MY _SUB
	STMFD	R13!,{R0-R3}
	LDR		R0,=NN
	LDR		R1,=MM
	MOV		R2,#20
LOOP
	LDRB	R3,[R0],#1
	STRB	R3,[R1],#1
	SUBS	R2,R2,#1
	BNE		LOOP
	LDMFD	R13!,{R0-R3}
	MOV		PC,LR
	END

有 20 个有符号的字数据,依次存放在内存 BUFF 开始字单元中。试用 ARM 汇编语言编写完整的程序(包括代码段、数据段),从中找出最大值、最小值,并分别放入内存字单元 MAX、MIN 中。

	AREA Search,CODE,READONLY		;代码段
	CODE32
NUM	EQU	20			;定义数据个数
	ENTRY
start 
	LDR	R3,=BUFF	;设置初始地址
	LDR	R4,=NUM		;取数据个数
	LDR	R0,[R3]		;R0 存放最大数
	LDR	R1,[R3]		;R1 存放最小数
loop 
	LDR	R2,[R3],#4	;取比较数据
	CMP	R2,R0
	MOVGT	R0,R2			;若取出的数大于 R0 中数据,则更新 R0
	CMP	R2,R1
	CMPLT	R1,R2			;若取出的数小于 R1 中数据,则更新 R1
	SUBS	R4,#0x01		;计数减 1
	BNE  loop				;计数未完,继续
	LDR	R3,=MAX
	STR		R0,[R3]
	LDR	R3,=MIN
	STR		R1,[R3]
stop 
	MOV	R0,#0x18		;返回系统
	LDR 	R1,0x20026
	SWI		0x123456

	AREA DefineData,DATA,READWRITE		;数据段
BUFF DCD 23,54,34,64,35,34,……,98,0F5,39	;定义 20 个有符号字数据
MAX	DCD	0		;最大值单元
MIN	DCD	0		;最小值单元
	END

已知 R0=a, R1=b,用汇编语言实现 if ((a!=0x10)&&(b!=0x30)) a=a+b

        AREA    Exp, CODE, READONLY  
a EQU  0x03        
b EQU  0x04
c EQU  0x10
d EQU  0x30
        ENTRY                 
        CODE32        
start
        LDR     r0, =a
        LDR     r1, =b
        LDR     r2, =c
        LDR     r3, =d
        CMP     r0,r2   ;a!=0x10
        BEQ     stop
        CMP     r1,r3   ;b!=0x30
        BEQ     stop
        ADD     r0,r0,r1 ;a=a+b         
stop
        MOV     r0, #0x18       
        LDR     r1, =0x20026    
        SWI     0x123456        
        END

编写汇编程序计算内存 0x40003000 开始的 20 个字节单元数据之和,如果和小于 100 则将这 20 个单元复制到内存 0x40003020 开始的地址处,否则将这 20 个单元清零

		AREA    Exp, CODE, READONLY
ADDR1   EQU 0x40003000
ADDR2   EQU 0x40003200
CNT     EQU 20 
VALUE   EQU 100
        ENTRY                 
        CODE32        
start
        LDR     r0, =ADDR1
        LDR     r2, =CNT
        LDR     r3,=VALUE
        MOV     R4,#0
l0      LDRB    R5,[r0],#1
        ADD     r4,r4,r5
        SUBS    r2,r2,#0x01
        BNE     l0
l1      CMP     r4,r3
        BCC     l3
        LDR     r0, =ADDR1
        LDR     r2, =CNT
        MOV     R4,#0
l2      strb    r4,[r0],#1
        subs    r2,r2,#1
        bne     l2
        b stop
l3      LDR     r0, =ADDR1
        LDR     r1, =ADDR2
        LDR     r2, =CNT
l4      LDRB    r4,[r0],#1
        STRB    r4,[r1],#1
        subs    r2,r2,#1
        bne     l4        
stop
        MOV     r0, #0x18       
        LDR     r1, =0x20026    
        SWI     0x123456        
        END

数组 a、b 分别存放在 0x4000 与 0x5000 为起始地址的区域内,将以下 C 语言程序转为完整的汇编程序:

for (i=1;i<8;i++)
{
	b[i]=a[i];
	if(b[i]=0)  b[i]=-1;
}
		AREA	COPY1,CODE,READONLY	; 声明代码段 COPY1 
SS1		EQU  0x4000					;源地址
DD1		EQU  0x5000					;目的地址
NUM		EQU  8							;字计数
		ENTRY				      		; 标识程序入口
		CODE32							; 声明 32 位 ARM 指令
START
		LDR		R0, =SS1	    		; 设置源地址
		LDR		R1, =DD1	    		; 设置目标地址
		MOV		R2, #0					; 设置字计数初始值为 0
LOOP
		LDR		R3, [R0], #4			;取一个字源数据
		CMP		R3, #0					;字源数据与 0 比较
		MVNEQ	R3, #0					;为 0,送-1
		STR		R3, [R1], #4			;送目标字单元
		ADD		R2, R2, #1				;字计数加 1
		CMP		R2, #NUM				;达到预定的 NUM 吗?
		BCC		LOOP					;未达到,继续
HALT
		B		HALT					;达到,暂停
		END

编写程序将 R1 的高 8 位数据转移到 R0 的低 8 位中,保存到地址 0x40003000 单元内

		AREA ByteCopY, CODE, READONLY       
COUNT   EQU  0x44332211
A1      EQU  0x40003000 
        ENTRY                   
start
        LDR R1,=COUNT 
        MOV R0,R1,LSR#24
        LDR R1,=A1
        STR R0,[R1] 
        END

用汇编程序实现如下功能:将 R1 的高 16 位数据与低 16 位交换,保存到地址 0x40003000 内

A1      EQU  0x40003000 
start
        LDR R3,=A1 
        MOV R0,R1,LSR#16
        AND R2,R1,#0XFF
        ORR R0 R0 R2 
        STR R0,[R3] 
        END

编写子程序实现将存储器中起始地址 S1 开始的 6 个字数据移动到 S2 处(要求使用 LDM 和 STM 语句)。

STMFD SP!,{R0-R6,LR}
LDR R6,=S1;
LDMIA R6!,{R0-R5}
LDR R6,  =S2
STMIA R6!,{R0-R5}
LDMFD SP!,{R0-R6,PC}

附加说明

对上面一些代码做些说明

STOP B STOP ;相当于停机,程序不往下执行了
|DATA| ||.text||
这些 | 是一种标号表示方法
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/sinat_41104353/article/details/85652230
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢