2.汇编代码的简单实现
- 使用汇编的原因很简单,就是汇编代码的高效。在机器启动的时候,利用汇编的高效,对硬件进行初始化,为加载内核,提供条件。
- 目前常用的ARM汇编指令有两种:
*ARM标准汇编:适用于ARM公司的汇编器,适合在Windows平台下使用。
*GNU汇编:使用与GNU交叉编译工具链中的汇编器,适合于Linux平台开发。
3.汇编程序框架:注意下面的操作环境是Redhat 6.4 + eclipse C/C++ +CDT插件。
汇编代码的基本框架
?
汇编用到的地方,启动代码,效率要求高效的地方。
上面是启动代码的框架。
下面搭建框架:
start.S:
.text
.global _start
_start:
????mov r2,#2
????mov r3,#3
Makefile:
all : start.o
????arm-linux-ld -Tgboot.lds -o start.elf $^
%.o : %.S
????arm-linux-gcc -g -o [email protected] $^ -c
clean:
????rm *.o *.elf
简单工程的运行的结构:
链接器脚本:
Gboot.lds:
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS {
????. = 0x50008000;
????
????. = ALIGN(4);
????.text :
????{
????start.o (.text)
????*(.text)
????}
?
????. = ALIGN(4);
????.data :
????{
????*(.data)
????}
????
????. = ALIGN(4);
????bss_start = .;
????.bss :
????{
????*(.bss)
????}
????bss_end = .;
}
运行的结果:
接下来是汇编代码的操作实现:
mov r1,#6
mov r2,r1
mov r3,#10
@mvn:传值取反的值
????mvn r0,#4 @r0:4取反变为-5
????mvn r1,#0b111000
????mvn r2,r1 @r2:0b111000
Sub的实例:
?
Add的实例:
当然,我们也可以在执行的时候指定参数的值:如下图,我们指定了r0=44,r2=66.
运行了之后:
?
And的实例;
Bic的实例:第三个数是源码,源码位为1的,对应的位清0,源码位是0的,对应的位不变。
从上面的执行结果看到,r1的最高位,和最低两位的1,对应源码位的值都是1,所以,被清0,中间四位,对应源码的四个0,保持不变1010.所以最后输出了0b101000.
?
- 比较指令
Cmp指令的操作:比较的结果不会保持,回去影响cpsr对应的位:N或Z位。
我们可以看到r1-1=1是正数,cpsr的最高位四位2=0010,N,Z位都是0.
这里r1-3=-1,cpsr的最高四位8=1000,即是N位被置为1,表示结果是负数。
这里r1-2=0,cpsr的次高位被置为1,表示两个数相等。
Txt指令的操作:测试位、按位与,结果为0 ,Z位被置为1,结果不为0,Z位置为0
按位与之后的值不为0,所以cpsr的Z位不会被置为1.
按位与之后的结果是为0的,所以cpsr的Z位被置1.结果高四位的值是4.
- 跳转指令:
B指令:
上面的例子中,gt表示大于的时候跳转,6>5所以跳转到标签branch1处执行。不会执行add r3,r1,r2.
上面,跳转的条件不成立,顺序执行,不跳转。但是会顺序执行,所以加个b end跳转到end,执行空操作。
?
?
?
?
?
?
Bl:带链接的跳转:
Lr:
反汇编的代码:
由上面看到lr保存的是bl返回来后的下一条地址,把他赋值给pc指针进行跳转。
?
- 移位指令:
- Lsl左移指令:
11左移两位:1100
- ror循环右移:
循环右移,最低位的1,被循环移动到了最高位。
?
?
?
?
?
- 程序状态字访问指令。
在GNU汇编中,我们不允许上面的 指令来操作访问我们的程序字状态寄存器指令,所以我们需要将他们的值移出,再进行操作访问,修改等,操作完还要移进去。所以就设计到两个指令:MSR和MRS指令。搬出mrs,搬回去msr。
执行了之后:
最后:
我们就是得通过上面的操作来改变cpsr里的值的。
- 存储器访问指令:
上面的都是核里面的指令,内存是通过存储器访问质指令。
Ldr指令:内存保存到寄存器
Str指令:寄存器保存到内存。
我们把r1设置成了开发板内存的地址,如上图,接下来在memory里创建一个监控的地址:
接下来看看运行了上面的指令后的变化:如下图,我们的0xff已经被保存到了0x50008000.
下面是ldr:
R2的值就是存进r0里的值,被取出来了。
?
?
这个汇编操作的工程代码:
.text
.global _start
_start:
[email protected]和str的操作
????mov r0,#0xff
????str r0,[r1]
????ldr r2,[r1]
[email protected]程序状态字寄存器访问
????mrs r0,cpsr
????orr r0,#0b100
????msr cpsr,r0
[email protected]:循环右移
????mov r1,#0b11
????mov r1,r1,ror#1
[email protected]:左移
????mov r1,#0b11
????mov r1,r1,lsl#2
[email protected]指令:带链接跳转
????bl func1
[email protected]指令:
????mov r1,#6
????mov r2,#7
????cmp r1,r2
????bgt [email protected]表示大于的时候跳转
????add r3,r1,r2
????b end
func1:
????mov r1,#23
????mov pc,[email protected]函数的返回,固定格式。
?
branch1:
????sub r3,r1,r2
end:
????nop
[email protected]指令:
????mov r1,#0b101
????tst r1,#0b01
?
????mov r1,#0b101
????tst r1,#0b10
[email protected]指令的操作:
????mov r1,#2
????cmp r1,#1
?
????mov r1,#2
????cmp r1,#3
?
????mov r1,#2
????cmp r1,#2
[email protected]:位清除指令
????mov r1,#0b1101011
????bic r2,r1,#0b1000011
[email protected]的用法:逻辑与
????mov r1,#5
????and r2,r1,#0
?
????mov r1,#5
????and r2,r1,#1
[email protected]:加法:
????add r1,r0,r2
[email protected]:减法,注意被减数不能是立即数
????mov r2,#4
????sub r0,r2,#2
????mov r1,#3
????sub r3,r1,r0
[email protected]这是注释,mov指令
????mov r1,#6
????mov r2,r1
????mov r3,#10
[email protected]:传值取反的值
????mvn r0,#4 @r0:4取反变为-5
????mvn r1,#0b111000
????mvn r2,r1 @r2:0b111000