实验器材
硬件
- 树莓派板子一块;
- 5V/1A电源一个;
- microUSB线一根;
- USB-TTL串口线一根(FT232RL芯片或PL2303芯片)。
- PC(Windows/MacOS/Linux)一台;
- 以太网线一根;
- 路由器一台
软件
- PC上的USB-TTL串口线配套的驱动程序;
- PC上的串口终端软件putty
实验步骤
给出各项测试所用的C代码和产生的汇编代码情况,并解释汇编代码
(1)生成了Thumb
指令还是 ARM 指令:如何通过编译参数改变,相同的程序,ARM和Thumb编译的结果有何不同, 如指令本身和整体目标代码的大小等;
a.
编写c代码
b.
编译
结果如下:
指令程度为32位,gcc默认使用arm指令集
c.
使用Thumb编译
结果如下:
指令长度是16
(2)对于ARM
指令,能否产生条件执行的指令;
a.
编写c代码
b.
编译
查看结果:
可以看到有ble等条件分支指令的出现,即ARM支持条件执行指令。
(3)设计 C
的代码场景,观察是否产生了寄存器移位寻址;
a.
编写c代码
b.
编译
查看结果:
可以看到左移指令lsl,所以ARM支持寄存器移位寻址
(4)设计 C
的代码场景,观察一个复杂的 32 位数是如何装载到寄存器的;
a.
编写c代码
b.
编译
查看结果:
可以看到ARM指令将大数字存在命令段,通过ldr指令去加载,而非MIPS等指令集使用lui和ori来实现32位大数字的实现。
(5)写一个 C的多重函数调用的程序,观察和分析:
a. 调用时的返回地址在哪里? b. 传入的参数在哪里? c.
本地变量的堆栈分配是如何做的? d. 寄存器是 caller
保存还是 callee 保存?是全体保存还是部分保存?
a.
编写c程序
b.
编译
查看结果:
调用时的返回地址在LR中。
传入的参数在R0 R1 R2 R3四个寄存器中,多余的参数放在堆栈中。
本地变量存放在堆栈高地址,传进来的参数存放在堆栈低地址。
R0到R3由caller保存,R4以上由callee保存。全体保存。
(6)MLA
是带累加的乘法,尝试要如何写 C
的表达式能编译得到MLA 指令。
a.
编写c程序
b.
编译
查看结果:
可以看出,优化后的代码使用了MLA命令。
(7)BIC是对某一个比特清零的指令,尝试要如何写 C
的表达式能编译得到 BIC 指令。
a.
编写c程序
b.
编译
查看结果:
(8)编写一个汇编函数,接受一个整数和一个指针做为输入,指针所指应为一个字符串,该汇编函数调用C语言的
printf()函数输出这个字符串的前n个字符,n即为那个整数。在C语言写的main()函数中调用并传递参数给这个汇编函数 来得到输出。
汇编程序:
00000000 <f>:
0: e92d4800 push {fp, lr}
4: e28db004 add fp, sp, #4
8: e24dd010 sub sp, sp, #16
c: e50b0010 str r0, [fp, #-16]
10: e50b1014 str r1, [fp, #-20]
14: e3a03000 mov r3, #0
18: e50b3008 str r3, [fp, #-8]
1c: ea000008 b 44 <f+0x44>
20: e51b3008 ldr r3, [fp, #-8]
24: e51b2014 ldr r2, [fp, #-20]
28: e0823003 add r3, r2, r3
2c: e5d33000 ldrb r3, [r3]
30: e1a00003 mov r0, r3
34: ebfffffe bl 0 <putchar>
38: e51b3008 ldr r3, [fp, #-8]
3c: e2833001 add r3, r3, #1
40: e50b3008 str r3, [fp, #-8]
44: e51b2008 ldr r2, [fp, #-8]
48: e51b3010 ldr r3, [fp, #-16]
4c: e1520003 cmp r2, r3
50: bafffff2 blt 20 <f+0x20>
54: e3a0000a mov r0, #10
58: ebfffffe bl 0 <putchar>
5c: e24bd004 sub sp, fp, #4
60: e8bd8800 pop {fp, pc}
C程序: