指令速记


title: 指令速记
tags: ARM
date: 2018-10-11 19:13:53

引入

https://www.cnblogs.com/chen-farsight/p/6068905.html

标号

标号,就是地址的值,具体到时取地址,还是取地址的内容,看操作符,比如参考LDR

纯数字lable参考

LDR

LDR指令分为加载指令ldr rn,[Rn]....与伪指令ldr Rn, =expr.一个很常见的用法如下:(具体解析在ADR)

.text
.global _start

_start:
    nop
_addr1:
ldr r0,=_addr1	//R0=addr1
ldr r0,_addr1	//R0=*addr1

ldr pc,=_start	//取绝对地址
nop
adr pc,_start	//取相对于当前pc的一个地址
nop
  • ldr rn,=lable,表示将lable的值,也就是Rn=lable,一般将其转换为ldr r0, [pc, #20]从某个flash取值

    • 在这种使用等号的形式中,经常使用宏来赋值

      //test.h
      #define TEST_NUM    0x12345678
      
      //test.S
      #include "Test.h"
      ldr r0,=TEST_NUM
      
  • ldr rn,lable,表示将lable值的所在内存的值赋值给Rn,也就是Rn=*lable,转换为类似ldr r0, [pc, #-12]

ADR与LDR

ADR r0,_start,这里会将_start转换为相对于当前pc值的一个值,看一段汇编.注意,三级流水线,pc=当前+8

.text
.global _start

_start:
    nop
_addr1:
ldr r0,=_addr1
ldr r0,=_addr1

ldr pc,=_start
nop
adr pc,_start
adr r0,_start
nop


00000000 <_start>:
   0:	e1a00000 	nop			(mov r0,r0)

00000004 <_addr1>:
		ldr r0,=_addr1;
		//将标号的值赋值给R0
		//4+20+8=hex(32)=0x20, *0x20=00000004
   4:	e59f0014 	ldr	r0, [pc, #20]	; 20 <.text+0x20>
   
   		ldr r0,_addr1
   		//将标号地址存放的值给R0
   		//8-12+8=4,也就是将[4]中的内容取出来
   8:	e51f000c 	ldr	r0, [pc, #-12]	; 4 <_addr1>
   
   		ldr pc,=_start
   		//直接取值,从0x24的位置取值0
   c:	e59ff010 	ldr	pc, [pc, #16]	; 24 <.text+0x24>
  10:	e1a00000 	nop			(mov r0,r0)
  
  		adr pc,_start
  		// pc=pc+8-28=0x14+8-28=0
  		// 这里是通过计算offset得到pc
  14:	e24ff01c 	sub	pc, pc, #28	; 0x1c
  		adr r0,_start
  18:	e24f0020 	sub	r0, pc, #32	; 0x20
  1c:	e1a00000 	nop			(mov r0,r0)
  20:	00000004 	andeq	r0, r0, r4
  24:	00000000 	andeq	r0, r0, r0

原文地址:https://www.cnblogs.com/zongzi10010/p/10023553.html