文章目录
1. 基本结构
2. Mu0 基本命令
mem[S]是地址
S是这个地址的索引
A是一个16bit的寄存器
S的范围为:
在编程时,可以用数字的形式来表示命令,可以看到下图中的命令都变成了对应的数字:
3. ARM 基本命令
ADR
LDR
STR
BGE
DCW
如果结果大于32bit,则会保存最后面的32bit
op2可以直接是一个数,也可以是register(MUL, MLA除外)
3.1 状态码
下·
3.2 S code
在命令尾部加上S,可以设置FLAG
如图,只有第一个表格和最后一个表格里的才能同时设置4个FLAG
3.3 LDR和STR的indirect addressing
LDR赋予的r6的是r11包含的地址对应的值
而MOV赋予的是r11包含的地址
LDR这种寻址方式被称为indirect addressing
STR是将r6 register里的值赋予r11对应的memory
LDR r0, =0x…
可以将32bit的数据存入r0
3.3.1 Base plus addressing
可以在 LDR 的方框内加一个数字来改变地址
3.3.2 LOAD 和 STORE
LDR是将数据从memory移到register
STR是将数据从register移到memory
每个内存地址包含 1 byte,也就是 8 bits 的数据,然而LDR 和 STR包含4个byte, 也就是包含4个地址
3.3.2.1 LDHR, LDRB,STRH,STRB
LDHR 只会 load 最后面的 16 bits 数据,剩下的16 bits 清零
LDRB 只会 load 最后面的 8 bits 数据,剩下的24 bits 清零
同理 STRH 只会 store 最后的 16 bits
STRB 只会 store 最后的 8 bits
3.3.3 Big endian & little endian
不同的 ARM processor 形式不同
3.3.3.1 Big endian
3.3.3.2 Little endian
3.4 Compare
用于 compare 的 instructions 不需要目标寄存器,并且总是会设置 FLAG
3.5 Shift
在使用 MOV 命令改变寄存器内容时,可以追加命令来修改这些内容
例如:
LSL #5 将 r2 拥有的值左移了五格之后存进了 r1
一共有五种 shift
- LSL #n 左移n位
- LSR #n 右移n位
- ASR #n 右移n位,新加进来的 bit 为原来的 sign bit
- ROR #n 向右旋转n位,右边消失的会在左边出现
- RRX 向右移动一位,将 carry flag 放在最左,如果有 ‘S’ ,则将最右被移出去的 bit 放进 carry flag
位移的数目也可以用 register 指定
r3 为 19,则会位移19位
3.5.1 用 shift 和 add 来实现 multiply
FLAG
四种FLAG分别为:
- Zero flag Z = 1,结果为0
- Negative flag N = 1,结果为负 (即most significant bit = 1)
- Carry flag C = 1,结果带有一个进位(unsigned 溢出),对于减法,不借位就算是进位,C=1
- Overflow flag V = 1,结果是 signed number 溢出(即两个整数相加得到负数,或两个负数相加得到正数时)
FLAG是微处理器中的一种标记符号,常常用来表示一个命令执行后的结果
0 FLAG 常常被用在循环中, 如下图
将有符号整数转换为16 bit 2’s complement
先将该整数的绝对值转换为二进制。如十进制数9转换为二进制得1001。不足16bit高位补零,得0000 0000 0000 1001。若十进制数是正数,最终结果就是刚刚得到的二进制数。但如果是负数,则再对刚刚得到的二进制数求补。规则是按位取反,末位加一。例如十进制数-9,对上面的二进制数求补得1111 1111 1111 0111
补码的作用
运算中出现负数时,需要取补码再运算
IEEE 754 Format
这一形式可以在计算机中表示浮点数
Example
254.456
254 = 1111 1110
0.456 = 0111 0100 1011 1100
11111110.0111010010111100
1.11111100111010010111100 * 2^7
取小数点后面的数为尾数,即11111100111010010111100
阶码 = 7 + 127 = 128 + 4 + 2 = 10000110
整数,sign number 为 0, 放在最前面
Sign number + 阶码 + 尾数
0100 0011 0111 1110 0111 0100 1011 1100
16进制
0x437E74BC
特殊数字
0x7F800000 代表正无穷
0xFF800000 代表负无穷
地址总线,数据总线,内存容量
最上面的A0, A1是地址总线,因为只有4个地址,所以两个地址总线足够表达4个地址了
如果是22个地址,则需要地址总线能表达的数字大于22,也就是至少需要32bit的地址总线
2^地址总线 需要大于处理器的内存区块数量
数据总线与处理器的字长一样
内存容量为 字长*内存区块数
Words
words代表“字”,不同系统的字包含信息量可能不同
22 words of 32 bits each,说明这个处理器有22个字,每个字的字长是32bit
寻址
Register addressing
Immediate addressing
Immediate addressing 的问题
Branch
通过 branch 可以让程序在一个不同的内存位置继续执行
Conditional branch 实例
Unconditional branch 无论如何都会执行
上图的程序,在执行到B时会跳转到对应的地址继续执行
这里的 B 也可以在后缀加上状态码
Conditional branches 实例
Conditional branch 只有特定情况才会执行,通常和 flag 相关
Branch 限制
目标地址必须在 branch instruction 当前地址的 32MB 以内
Branch 记忆
通常会用 label 代替地址,不然会很混乱
示例如下:
这里用 continue 代替了地址
Cache memory
越大的内存意味着越慢的读写速度
用 cache memory 可以同时拥有内存和速度
Cache memory 会保存最近从main memory获取的数据的副本
cache 的性能表现为’hit rate‘,当代cache 的 hit rate 应该超过 90%
16进制,10进制互相转换
10进制:428
428/16 = 26…12=C
26/16 = 1…10=A
1AC
16进制:3FA
3
∗
1
6
2
+
F
∗
1
6
1
+
A
∗
1
6
0
=
768
+
240
+
10
=
1018
3*16^2+F*16^1+A*16^0=768+240+10=1018
3∗162+F∗161+A∗160=768+240+10=1018
IEEE 754 example
-40
sign 为 1, 负数
exponent 为
2
7
+
2
2
=
132
2^7+2^2=132
27+22=132
132-127=5
matissa 为 1 + 2 ( − 2 ) = 1.25 1+2^{(-2)}=1.25 1+2(−2)=1.25
结果为
1.5
第一位为 0 ,正数
expoent 为
2
7
−
1
=
127
2^7 - 1=127
27−1=127
127-127=0
matissa 为 1 + 2 ( − 1 ) = 1.5 1+2^{(-1)}=1.5 1+2(−1)=1.5
结果: 1.5 × 2 0 = 1 1.5\times2^0=1 1.5×20=1
1
matissa = 1
结果= 1 × 2 0 = 1 1\times2^0=1 1×20=1
Loop
进入 loop 前先把计数清零
While
在进入 loop 之前用 B 先跳入 loop 最后一行
For loop
Count down loop
冒泡算法
比较相邻的元素。如果第一个比第二个大,就交换他们两个。 [1]
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 [1]
针对所有的元素重复以上的步骤,除了最后一个。 [1]
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 [1]
Table
系数始于0
每一个data 的 size 是 4 bytes (32bits)
LSL#2 乘以 2^2
LDRH 只提取一半 (2 bytes)
LDRB 提取四分之一 (1 byte)