linux下ARM汇编指令简单学习、使用

目录

一、ARM汇编指令参考手册

二、ARM Architecture Reference Manual.pdf中重点知识截图

三、函数参数的传递

四、常用ARM汇编指令

五、实例一:汇编

六、实例二:C转汇编

七、总结


注:
1、以下测试在ubuntu 9.10(32位)上进行,其他平台未测试
2、本文只是我个人的理解,不一定完全正确
3、版权所有,转载请注明作者和出处

一、ARM汇编指令参考手册

1、ARM Architecture Reference Manual.pdf-------------------比较旧的ARM芯片的参考手册,如S3C2440等

2、ARM7TDMI Technical Reference Manual.pdf-------------ARM7TDMI内核芯片参考手册

3、ARM7TDMI-S Technical Reference Manual.pdf----------ARM7TDMI-S内核芯片参考手册

4、ARM920T Technical Reference Manual.pdf---------------ARM920T内核芯片参考手册

5、ARM®v7-A-R Architecture Reference Manual.pdf-------ARM®v7-A或-R内核芯片参考手册

6、ARM®v7-M[E.d] Architecture Reference Manual.pdf----ARM®v7-M内核芯片参考手册

以上手册大家自行下载,懒人可以到我的资源中下载:https://download.csdn.net/download/tsummer2010/12327263

二、ARM Architecture Reference Manual.pdf中重点知识截图

1、ARM架构版本信息

2、指令编码表

3、条件码 

4、 MOV指令格式

5、LDR指令格式

6、STR指令格式

7、B,BL指令格式

8、BIC指令格式

9、ADD指令格式

10、SUB指令格式

11、STM指令格式

12、LDM指令格式

13、几个关键缩写

 

三、函数参数的传递

1、传参规则是由The ARM-THUMB Procedure Call Standard(ATPCS.pdf )规范中规定的,详情自行搜索ATPCS规范

2、简单记住:函数的第一个到第四个参数分别用R0-4传入,超过4个参数的情况这里不深究

四、常用ARM汇编指令

LDR R1,[R2];R1<--[R2] 把R2所指向的存储单元中的值存入到寄存器R1中
STR R1,[R2];R1-->[R2] 把R1寄存器中的值存入到寄存器R2所指向的存储单元中
MOV R1,R2  ;R1<--[R2]
LDR R1,=0x123456      伪指令
B                     分支跳转指令
BL
ADD R0,R1,#2  ;R0=R1+2 加指令
SUB R0,R1,#2  ;R0=R1-2 减指令
LDMIA 先读后增,读内存,写入多个寄存器【高编号的寄存器存入到高内存地址】
STMDB 先减后存,把多个寄存器写入内存  【高编号的寄存器存入到高内存地址】
      !表示最终的被修改后的值

五、实例一:汇编

注:以jz2440开发板为例测试

-----------------汇编源码---------------
.text
.global _start

_start:

  @关闭看门狗
  LDR R0,=0x53000000@把看门狗控制器的地址放入寄存器中 
  LDR R1,=0x8001    @把一个立即数放入寄存器中
  STR R1,[R0]       @把立即数写入看门狗控制器的地址中

  /*配置LED管脚IO为输出模式
  LED10,红色,GPF4,[9:8]  ,01=output
  LED11,红色,GPF5,[11:10],01=output
  LED12,红色,GPF6,[13:12],01=output
  */
  @LDR R0,=0x100
  @LDR R1,=0x56000050
  @STR R0,[R1]
  
  LDR R0,=0x56000050 @把GPF的地址放入寄存器中
  LDR R1,[R0]        @读出GPF地址中的值
  BIC R1,R1,#0x3f00  @清除bit13~bit8
  ORR R1,R1,#0x1500  @设置为输入01
  STR R1,[R0]        @把寄存器中的值写入GPF的地址中
  
  @LDR R0,=0
  @LDR R1,=0x56000054
  @STR R0,[R1]
  
  /*3个IO设置为亮灭亮
  */
  LDR R0,=0x56000054@把GPFDAT的地址放入寄存器中
  LDR R1,[R0]       @读出GPFDAT地址中的值
  BIC R1,R1,#0x70
  ORR R1,R1,#0x20
  STR R1,[R0]

wait:
  B wait

-----------------反汇编----------------

led_on.elf:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:
   0:	e3a00453 	mov	r0, #1392508928	; 0x53000000
   4:	e59f102c 	ldr	r1, [pc, #44]	; 38 <.text+0x38>
   8:	e5801000 	str	r1, [r0]
   c:	e59f0028 	ldr	r0, [pc, #40]	; 3c <.text+0x3c>
  10:	e5901000 	ldr	r1, [r0]
  14:	e3c11c3f 	bic	r1, r1, #16128	; 0x3f00
  18:	e3811c15 	orr	r1, r1, #5376	; 0x1500
  1c:	e5801000 	str	r1, [r0]
  20:	e59f0018 	ldr	r0, [pc, #24]	; 40 <.text+0x40>
  24:	e5901000 	ldr	r1, [r0]
  28:	e3c11070 	bic	r1, r1, #112	; 0x70
  2c:	e3811020 	orr	r1, r1, #32	; 0x20
  30:	e5801000 	str	r1, [r0]

00000034 <wait>:
  34:	eafffffe 	b	34 <wait>
  38:	00008001 	andeq	r8, r0, r1
  3c:	56000050 	undefined
  40:	56000054 	undefined

六、实例二:C转汇编

1、启动文件

.text
.global _start

_start:
  
  /*设置内容:sp,栈*/
  /*程序自动识别是NOR启动还是NAND启动
   *原理:向0地址写入0,如果读出的是0则是nand启动,反之为nor启动
   *      因为向nor写入数据必须要有专门的时序才可以正确写入。nand
   *      是可以直接写入的
  */
  MOV R1,#0   @
  LDR R0,[R1] @读出原来0地址的数据
  STR R1,[R1] @把0写入0地址中,0->[0]
  LDR R2,[R1] @读出0地址的数据,R2=[0]
  
  @cmp用法
  @cmp r0, #0
  @beq LABEL1 ; r0==0那么向前跳转到LABEL1处执行
  @bne LABEL2 ; 否则向后跳转到LABEL2处执行

  CMP R1,R2   @R1==R1如果相等则是nand启动
  LDR SP,=0x40000000+4096 @先假设是nor启动
  MOVEQ SP,#4096  @nand启动
  STREQ R0,[R1] @恢复原来0地址的值

  /*调用main函数*/
  BL main
  
halt:
  B halt

2、C文件

#include<stdint.h>

//看门狗计数器定义
#define WTCON  (*((uint32_t *)0x53000000))//配置寄存器
#define WTDAT  (*((uint32_t *)0x53000004))//溢出值寄存器
#define WTCNT  (*((uint32_t *)0x53000008))//计数寄存器

//io寄存器GPF申明
#define GPFCON (*((uint32_t *)0x56000050))
#define GPFDAT (*((uint32_t *)0x56000054))
#define GPFUP  (*((uint32_t *)0x56000058))

void delay(volatile uint32_t time)
{
  while(time--);
}

int main(void)
{
  uint32_t data=0;
  
  WTCON=0x8001;//关闭看门狗
  
  //设置GPIO为输出
  data=GPFCON;
  data&=0xFFFFC0FF;
  data|=0x00001500;
  GPFCON=data;
  
  //设置GPIO为输出高低
  data=GPFDAT;
  data|=0x70;//全灭
  GPFDAT=data;
  while(1)
  {
    data=0x30;
    GPFDAT=data;
    delay(10000);
    
    data=0x50;
    GPFDAT=data;
    delay(10000);
    
    data=0x60;
    GPFDAT=data;
    delay(10000);
  }
  return 0;
}

3、反汇编文件


led_on.elf:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:
   0:	e3a01000 	mov	r1, #0	; 0x0
   4:	e5910000 	ldr	r0, [r1]
   8:	e5811000 	str	r1, [r1]
   c:	e5912000 	ldr	r2, [r1]
  10:	e1510002 	cmp	r1, r2
  14:	e59fd00c 	ldr	sp, [pc, #12]	; 28 <.text+0x28>
  18:	03a0da01 	moveq	sp, #4096	; 0x1000
  1c:	05810000 	streq	r0, [r1]
  20:	eb00000e 	bl	60 <main>

00000024 <halt>:
  24:	eafffffe 	b	24 <halt>
  28:	40001000 	andmi	r1, r0, r0

0000002c <delay>:
  2c:	e1a0c00d 	mov	ip, sp
  30:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
  34:	e24cb004 	sub	fp, ip, #4	; 0x4
  38:	e24dd004 	sub	sp, sp, #4	; 0x4
  3c:	e50b0010 	str	r0, [fp, #-16]
  40:	e51b3010 	ldr	r3, [fp, #-16]
  44:	e2433001 	sub	r3, r3, #1	; 0x1
  48:	e50b3010 	str	r3, [fp, #-16]
  4c:	e51b3010 	ldr	r3, [fp, #-16]
  50:	e3730001 	cmn	r3, #1	; 0x1
  54:	0a000000 	beq	5c <delay+0x30>
  58:	eafffff8 	b	40 <delay+0x14>
  5c:	e89da808 	ldmia	sp, {r3, fp, sp, pc}

00000060 <main>:
  60:	e1a0c00d 	mov	ip, sp
  64:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
  68:	e24cb004 	sub	fp, ip, #4	; 0x4
  6c:	e24dd004 	sub	sp, sp, #4	; 0x4
  70:	e3a03000 	mov	r3, #0	; 0x0
  74:	e50b3010 	str	r3, [fp, #-16]
  78:	e3a02453 	mov	r2, #1392508928	; 0x53000000
  7c:	e3a03902 	mov	r3, #32768	; 0x8000
  80:	e2833001 	add	r3, r3, #1	; 0x1
  84:	e5823000 	str	r3, [r2]
  88:	e3a03456 	mov	r3, #1442840576	; 0x56000000
  8c:	e2833050 	add	r3, r3, #80	; 0x50
  90:	e5933000 	ldr	r3, [r3]
  94:	e50b3010 	str	r3, [fp, #-16]
  98:	e51b3010 	ldr	r3, [fp, #-16]
  9c:	e3c33c3f 	bic	r3, r3, #16128	; 0x3f00
  a0:	e50b3010 	str	r3, [fp, #-16]
  a4:	e51b3010 	ldr	r3, [fp, #-16]
  a8:	e3833c15 	orr	r3, r3, #5376	; 0x1500
  ac:	e50b3010 	str	r3, [fp, #-16]
  b0:	e3a03456 	mov	r3, #1442840576	; 0x56000000
  b4:	e2833050 	add	r3, r3, #80	; 0x50
  b8:	e51b2010 	ldr	r2, [fp, #-16]
  bc:	e5832000 	str	r2, [r3]
  c0:	e3a03456 	mov	r3, #1442840576	; 0x56000000
  c4:	e2833054 	add	r3, r3, #84	; 0x54
  c8:	e5933000 	ldr	r3, [r3]
  cc:	e50b3010 	str	r3, [fp, #-16]
  d0:	e51b3010 	ldr	r3, [fp, #-16]
  d4:	e3833070 	orr	r3, r3, #112	; 0x70
  d8:	e50b3010 	str	r3, [fp, #-16]
  dc:	e3a03456 	mov	r3, #1442840576	; 0x56000000
  e0:	e2833054 	add	r3, r3, #84	; 0x54
  e4:	e51b2010 	ldr	r2, [fp, #-16]
  e8:	e5832000 	str	r2, [r3]
  ec:	e3a03030 	mov	r3, #48	; 0x30
  f0:	e50b3010 	str	r3, [fp, #-16]
  f4:	e3a03456 	mov	r3, #1442840576	; 0x56000000
  f8:	e2833054 	add	r3, r3, #84	; 0x54
  fc:	e51b2010 	ldr	r2, [fp, #-16]
 100:	e5832000 	str	r2, [r3]
 104:	e3a00c27 	mov	r0, #9984	; 0x2700
 108:	e2800010 	add	r0, r0, #16	; 0x10
 10c:	ebffffc6 	bl	2c <delay>
 110:	e3a03050 	mov	r3, #80	; 0x50
 114:	e50b3010 	str	r3, [fp, #-16]
 118:	e3a03456 	mov	r3, #1442840576	; 0x56000000
 11c:	e2833054 	add	r3, r3, #84	; 0x54
 120:	e51b2010 	ldr	r2, [fp, #-16]
 124:	e5832000 	str	r2, [r3]
 128:	e3a00c27 	mov	r0, #9984	; 0x2700
 12c:	e2800010 	add	r0, r0, #16	; 0x10
 130:	ebffffbd 	bl	2c <delay>
 134:	e3a03060 	mov	r3, #96	; 0x60
 138:	e50b3010 	str	r3, [fp, #-16]
 13c:	e3a03456 	mov	r3, #1442840576	; 0x56000000
 140:	e2833054 	add	r3, r3, #84	; 0x54
 144:	e51b2010 	ldr	r2, [fp, #-16]
 148:	e5832000 	str	r2, [r3]
 14c:	e3a00c27 	mov	r0, #9984	; 0x2700
 150:	e2800010 	add	r0, r0, #16	; 0x10
 154:	ebffffb4 	bl	2c <delay>
 158:	eaffffe3 	b	ec <main+0x8c>
Disassembly of section .comment:

00000000 <.comment>:
   0:	43434700 	cmpmi	r3, #0	; 0x0
   4:	4728203a 	undefined
   8:	2029554e 	eorcs	r5, r9, lr, asr #10
   c:	2e342e33 	mrccs	14, 1, r2, cr4, cr3, {1}
  10:	Address 0x10 is out of bounds.

七、总结

深入理解汇编后,可以对系统启动等有更加完整、深刻的理解;当然理解后就行了,其他汇编不用再深究,因为汇编编程甚至用机器码是非常痛苦的,会用C就好,汇编工作交给汇编器吧。即汇编要会且理解,但不必深究。

 

2020-04-14 于北京,北京防疫形势相当严峻,京津冀绿码不通用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值