linux嵌入式编程学习笔记(1)

ARM汇编指令:

指令基本格式: <opcode> {<cond>{s} <Rd>, <Rn>{,<operand2>}}
	其中<>为必选项, {}为可选项
	<opcode>: 助记符, 如LDR, STR等
	cond: 执行条件, 如BEQ, BNE等
	助记符后跟S, 影响CPSR的值, 如SUB加S后为SUBS
	Rd: 目标寄存器
	Rn: 第一个操作数的寄存器
	operand2: 第二个操作数
	
存储器访问指令:
	加载/存储体系结构:
		ARM是RISC结构, 无法直接对存储数据进行操作, 首先要加载到寄存器才能处理
		对寄存器访问使用加载指令LDR和存储指令STR实现
		可以实现半字, 字, 无符号/有符号字节操作
		
	基本命令:
		LDR R1, [R0]: 将R0值作为内存地址, 取出该地址的值保存到R1
		STR R1, [R0]: 将R1的值保存到以R0中的值为地址的存储单元中
		LDRB/STRB: 读取一字节
		LDM/STM: 数据块传输指令, 实现一组寄存器和连续内存单元之间的数据传输
			加载(LDM)或存储(STM)一组寄存器
			支持堆栈操作
		SWP R1, R1, [R0]: 将R1与R0指向的存储单元内容进行互换
		SWP R1, R2, [R0]: 将[R0]读取到R1, 将R2写入到[R0]存储单元中
		
数据传输指令:
	MOV R1, #1: 将立即数1传送到寄存器R1中
	MOV R1, R0: 将R0中的值传送到R1寄存器中
	MOV PC, LR: 子程序返回
	MVN R1, #0xff: 将0xff取反后赋值给R1
	
算术逻辑运算指令:
	加减指令:
		ADD R1, R1, #1: R1 = R1 + 1
		ADC R1, R1, #1: R1 = R1 + 1 + C(CPSR中的进位/借位标志位), 用于64位数据的相加
		SUB R1, R1, R2: R1 = R1 - R2
		SBC R1, R1, R2: R1 = R1 - R2 - C, 用于64位数据的相减
		
	与或非指令:
		AND R0, R0, #3: 将R0与立即数3(00000011)相与, 即保留R0中的0, 1位, 其余位置零(两数相与, 见零则零, 全一则一)
		ORR R0, R0, #3: 置位R0中的0, 1位, 其余位不变(两数相或, 见一则一, 全零则零)
		
	异或指令:
		EOR R0, R0, #3: 反转R0中的0, 1位, 其余位不变(两数异或, 同零异一, 与零异或为原数, 与一异或为取反)
		
	清除指令:
		BIC R0, R0, #3: R0与取反的立即数3(11111100)相与, 即置零R0中的0, 1位, 其余位不变
		
	乘法指令:
		MUL R2, R1, R0: R2 = R1 * R0
		
	带累加的乘法:
		MLA R3, R2, R1, R0: R3 = R2 * R1 +R0
		
比较指令:
	影响CPSR状态寄存器的N(31: 负数标志位), Z(30: 零标志位), C(29: 进位标志位), V(28: 溢出标志位)
	CMP R1, #10: R1 - 10
	CMP R1, R2: R1 - R2
	CMN R0, #1: R0 - (-1), 与负数比较
	TST R1, #1: R1 & 1, 位测试, 测试0位为0或1
	TEQ R1, R0: R1 ^ R0(异或), 测试两数是否相等
	
条件执行:
	几乎所有ARM指令都可以根据CPSR的标志位, 有条件地执行
	
	|-------------------------------------------------|
	| 条件码  |  CPSR标志位    |         含义         |
	|-------------------------------------------------|
	|  EQ     |  Z = 1	       |  相等                |
    |---------|----------------|----------------------|
	|  NE     |  Z = 0	       |  不相等              |
    |---------|----------------|----------------------|
	|  CS/HS  |  C = 1	       |  无符号数大于或等于  |
    |---------|----------------|----------------------|
	|  CC/LO  |  C = 0    	   |  无符号数小于        |
    |---------|----------------|----------------------|
	|  MI     |  N置位	       |  负数                |
    |---------|----------------|----------------------|
	|  PL     |  N清零	       |  整数或零            |
    |---------|----------------|----------------------|
	|  VS     |  V置位	       |  溢出                |
    |---------|----------------|----------------------|
	|  VC     |  V清零	       |  未溢出              |
    |---------|----------------|----------------------|
	|  HI     |  C置位, Z清零  |  无符号数大于        |
    |---------|----------------|----------------------|
	|  LS     |  C清零, Z置位  |  无符号数小于或等于  |
    |---------|----------------|----------------------|
	|  GE     |  N = V	       |  有符号数大于或等于  |
    |---------|----------------|----------------------|
	|  LT     |  N != V	       |  有符号数小于        |
    |---------|----------------|----------------------|
	|  GT     |  Z清零, N = V  |  有符号数大于        |
    |---------|----------------|----------------------|
	|  LE     |  Z置位, N != V |  有符号数小于或等于  |
    |---------|----------------|----------------------|
	|  AL     |        -       |  无条件执行          |
    |---------|----------------|----------------------|
	|  NV     |        -       |  从不执行            |
	|-------------------------------------------------|
	
跳转指令:
	B label: 跳转到label处, 跳转范围为前后32M
	BL label: 
		带链接跳转, 先将下一条指令保存到LR, 然后再跳转
		MOV PC, LR: 常用于函数调用, 然后从子程序返回
	BX Rm: 
		带状态切换跳转, Rm保存的是跳转地址, 处理器根据Rm的0位决定切换到ARM或Thumb状态
		0位状态: 0: 目标地址为ARM指令, 1: 目标地址为Thumb指令
	BLX label: 带链接和状态切换跳转
	
伪指令:
	为了编程方便定义的伪指令, 并不是ARM指令集中的指令
	编译时会将这些伪指令等效为一条或多条机器指令
	
	四条伪指令:
		ADR R0, label: 将标号地址放入R0
			将基于PC的相对偏移地址值存入寄存器中
			相对寻址, 与代码位置无关
			ADR当前指令地址为PC-8
			偏移量为标号地址-(PC-8)
		ADRL: 中等范围的地址读取伪指令
		LDR: 大范围的地址读取伪指令, 常用来加载外部设备的寄存器地址, 参数带有"="
			若等号后立即数小于8bit, 则等价于MOV
			若等号后立即数大于8bit:
				在内存中定义一个字的存储单元, 将立即数存放在存储单元中, 该存储单元通常叫做文字池(literal pool)
				计算出该存储单元到LDR伪指令之间的偏移地址offset, 即可用相对寻址, 将这个立即数存入寄存器
		NOP: 空操作伪指令, 常用来延时 
	LDR, MOV和LDR伪指令的区别:
	
		指令格式:
			LDR伪指令的指令格式为:
				LDR R0, =0xffffffff: 有等号表示是伪指令, 将立即数0xffffffff存入R0
				LDR R0, LOOP: 将标号LOOP所代表的内存地址存入R0
			LDR指令通常用于寄存器间接寻址:
				LDR R0, [R1]: 将R1的值作为内存地址, 取该地址的内容存入R0
				LDR R0, LOOP: 将标号LOOP代表的内存地址处的内容存入R0
			MOV指令通常用于寄存器间的数据传输:
				MOV R0, R1: 将寄存器R1的值存入R0
				MOV R0, #20: 将立即数20存入R0
				
		用途:
			ARM是RISC结构, 不能直接操作内存数据, 要通过LDR/STR指令在内存中和寄存器之间存取数据
			MOV指令用于在寄存器之间存取数据
			LDR伪指令用于加载一个32位立即数或地址到指定寄存器
			
	LDR指令与ADR指令比较:
		相同点:
			都是ARM伪指令, 加载一个地址到指定寄存器
			
		不同点:
			LDR伪指令通常被被翻译为LDR或MOV指令, 而ADR伪指令通常被翻译为ADD所SUB指令
			LDR主要用来操作外设寄存器, ADR主要通过相对寻址, 生成与位置无关的代码, 只要各标号相对位置不变, 就可以做到与位置无关
			LDR使用绝对地址, ADR使用相对地址
			LDR范围为4G, ADR要求标号必须在同一个段中, 偏移地址对齐时为1020, 未对齐时为4096
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值