ARM指令

目标:

通过C代码和反汇编工具研究:

生成了Thumb指令还是ARM指令,如何通过编译参数改变;

对于ARM指令,能否产生条件执行的指令;

设计C的代码场景,观察是否产生了寄存器移位寻址;

设计C的代码场景,观察一个复杂的32位数是如何装载到寄存器的;

写一个C的多重函数调用的程序,观察和分析

调用时的返回地址在哪里?

传入的参数在哪里?

本地变量的堆栈分配是如何做的?

寄存器是caller保存还是callee保存?是全体保存还是部分保存?

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

ARM指令

可见生成的汇编是32位的。是ARM指令

查看gcc help找到生成thumb的参数

[email protected] ~ $ gcc --target-help

ARM指令

生成thumb指令:

[email protected] ~ $ gcc -mthumb -c asm.c

报错:

ARM指令

[email protected] ~ $ gcc -mthumb -msoft-float -c asm.c

生成 新的asm.o

objdump反汇编

[email protected] ~ $ objdump -d asm.o

ARM指令

可以看出汇编指令变为16位,是Thunb指令。

2ARM条件执行指令

编写如下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反汇编

ARM指令

完全没有吧条件跳转优化

所以用 -O3 优化编译

[email protected] ~ $ gcc 2.c -c -O3

反汇编后

ARM指令

发现优化过头了,直接把条件跳转优化没了。

把条件语句写入函数中。

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;

}

编译,后反汇编

ARM指令

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;

}

编译后反汇编

ARM指令

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

反汇编结果如下:

ARM指令

可见在编译是,编译器吧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

反汇编结果:

ARM指令

ARM指令

ARM指令

5.1:调用时的返回地址在哪里?

由反汇编可以看出返回地址在lr中,函数结束时,会把返回地址lr poppc

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指令

反汇编如下:

ARM指令

 

浙江大学嵌入式课程非荣誉出品

 

转载于:https://my.oschina.net/daijy/blog/122230