ARM指令
目标:
通过C代码和反汇编工具研究:
1 生成了Thumb指令还是ARM指令,如何通过编译参数改变;
2 对于ARM指令,能否产生条件执行的指令;
3 设计C的代码场景,观察是否产生了寄存器移位寻址;
4 设计C的代码场景,观察一个复杂的32位数是如何装载到寄存器的;
5 写一个C的多重函数调用的程序,观察和分析:
5 调用时的返回地址在哪里?
5 传入的参数在哪里?
5 本地变量的堆栈分配是如何做的?
5 寄存器是caller保存还是callee保存?是全体保存还是部分保存?
6 MLA是带累加的乘法,尝试要如何写C的表达式能编译得到MLA指令。
1:生成了Thumb指令还是ARM指令
写一个简单的C程序:
#include<stdio.h> int main(){ int a=1,b=2; int c=a+b; printf("%-2d",c); return 0; } |
Gcc编译:
[email protected] ~ $ gcc -c asm.c |
生成asm.o。
objdump反汇编
[email protected] ~ $ objdump -d asm.o |
可见生成的汇编是32位的。是ARM指令
查看gcc help找到生成thumb的参数
[email protected] ~ $ gcc --target-help |
生成thumb指令:
[email protected] ~ $ gcc -mthumb -c asm.c |
报错:
[email protected] ~ $ gcc -mthumb -msoft-float -c asm.c |
生成 新的asm.o。
objdump反汇编
[email protected] ~ $ objdump -d asm.o |
可以看出汇编指令变为16位,是Thunb指令。
2:ARM条件执行指令
编写如下C代码
#include<stdio.h> int main(){ int a=1,b=3; if(a<b) a<<2; if(a==b) b+=1; printf("%d %d",a,b); return 0; } |
用Gcc 编译
[email protected] ~ $ gcc 2.c -c |
Objdump反汇编
完全没有吧条件跳转优化
所以用 -O3 优化编译
[email protected] ~ $ gcc 2.c -c -O3 |
反汇编后
发现优化过头了,直接把条件跳转优化没了。
把条件语句写入函数中。
include<stdio.h> int f(int a,int b){ if(a<b) a<<2; if(a==b) b+=1; printf("%d %d",a,b); return 0; } int main(){ f(10,2); f(3,3); return 0; }
|
编译,后反汇编
F函数中的addeq 就是条件执行语句。
3:设计C的代码场景,观察是否产生了寄存器移位寻址
设计如下代码:
#include<stdio.h> int array(int*a,int index){ return a[index]; } int main(){ int a[10],i; int b=8;
for(i=0;i<10;i++) a[i]=i+1; printf("%d",array(a,b)); return 0; }
|
编译后反汇编
Array函数的取数组值时,指令用[r0,r1,lsl #2]来取地址。
4:观察一个复杂的32位数是如何装载到寄存器的;
代码如下:
#include<stdio.h> int f(){ int a = 0x1234ABCD; int b = 0x11000000; a=a+b; return a; } int mian(){ int b; b=f()-2; return 0; } |
编译
此时不能做优化,不然32位数直接就放在内存中。
[email protected] ~ $ gcc -c 4.c |
反汇编结果如下:
可见在编译是,编译器吧0x1234abcd 放到了代码段中,用地址访问。而0x11000000,编译器用立即数来得到 mov r3 , #285212672.
5:写一个C的多重函数调用的程序,观察和分析:
代码如下:
#include<stdio.h> int f1(int a){ int b; b=a*a+a; return b; } int f2(int a,int b){ int c; c=f1(a)+f(b); return c; } int main(){ int x=1; x=f(5,7); return 0; }
|
编译
[email protected] ~ $ gcc -c 5.c |
反汇编结果:
5.1:调用时的返回地址在哪里?
由反汇编可以看出返回地址在lr中,函数结束时,会把返回地址lr pop到pc中
5.2传入的参数在哪里?
传入的参数在r0-r3中,当参数不够用时,用更高寄存器r4+
5.3本地变量的堆栈分配是如何做的?
本地变量x存在寄存器r3中
8c: e50b3008 str r3, [fp, #-8] |
用以上指令把x压入fp堆栈中。
5.4寄存器是caller保存还是callee保存?是全体保存还是部分保存?
是callee保存,部分保存
6:尝试要写C的表达式能编译得到MLA指令。
代码如下:
#include<stdio.h> int f2(int a,int b,int c){ int d; d=a*b+c; return d; } int main(){ int x=1; x=f(5,7,5); return 0; } |
编译一定要优化,不然只会有mul指令
反汇编如下:
浙江大学嵌入式课程非荣誉出品
转载于:https://my.oschina.net/daijy/blog/122230