Lab2: ARM指令


实验步骤

使用交叉编译工具或本机编译工具,通过 C 代码和反汇编工具研究:

1.     生成了 Thumb 指令还是 ARM 指令:如何通过编译参数改变,相同的程序,ARM和Thumb编译的结果有何不同, 如指令本身和整体目标代码的大小等;

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

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

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

5.     写一个 C 的多重函数调用的程序,观察和分析: a. 调用时的返回地址在哪里? b. 传入的参数在哪里?c. 本地变量的堆栈分配是如何做的? d. 寄存器是 caller保存还是 callee 保存?是全体保存还是部分保存?

6.     MLA 是带累加的乘法,尝试要如何写 C 的表达式能编译得到MLA 指令。

7.     BIC是对某一个比特清零的指令,尝试要如何写 C 的表达式能编译得到BIC 指令。

8.     编写一个汇编函数,接受一个整数和一个指针做为输入,指针所指应为一个字符串,该汇编函数调用C语言的printf()函数输出这个字符串的前n个字符,n即为那个整数。在C语言写的main()函数中调用并传递参数给这个汇编函数 来得到输出。

 

实验报告要求

1.  画出你所实际实施的连接示意图;

同lab1

 

2.     给出所用的器材的列表;

l  Raspberry Pi 一块;

l  5V/1A 电源;

l  MicroUSB 线一根;

l  USB-TTL 串口线一根;

l  PC(Ubuntu14.04)一台;

l  以太网线一根;

l  路由器;

 

3.     给出各项测试所用的C代码和产生的汇编代码情况,并解释汇编代码;

1)生成了 Thumb 指令还是 ARM 指令:如何通过编译参数改变,相同的程序,ARM和Thumb编译的结果有何不同, 如指令本身和整体目标代码的大小等;

测试C代码:

#include<stdio.h>
int main(void){
     int a = 0;
     a += 1;
     return 0;
}

编译生成ARM指令:

gcc -c test.c

反汇编结果查看命令:

objdump -d test.o


可以发现,ARM指令本身是32位的,最左列地址每次以4字节增加,整体目标代码852K。gcc编译默认使用ARM编译。

编译生成Thumb指令:

gcc -c -mthumb -msoft-float test.c
odjump -d test.o

可以发现,Thumb指令是16位的,最左列地址每次以2字节增加,整体目标代码是820K,比ARM指令生成的略小。

 

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

C测试代码:

#include<stdio.h>
int f(int a, int b){
   if(a>b)  a++;
   else b++;
   return a;
}
int main(void){
   int t = f(1,2);
}

可以发现,汇编代码中有cmp,ble等条件分支指令,说明ARM指令支持条件执行。

 

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

C测试代码:

#include<stdio.h>
int main(void){
  int a[4] = {0,1,2,3};
  int i;
  for(i = 0; i < 2; i++){
     a[3] += a[i*2];
  }
}

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

C测试代码:

#include<stdio.h>
int main(void){
  int a= 0x12345678;
  return 0;
}


可以发现,32位数被存在命令段,通过ldr、sdr指令加载。

5)写一个 C 的多重函数调用的程序,观察和分析: a. 调用时的返回地址在哪里?b. 传入的参数在哪里? c. 本地变量的堆栈分配是如何做的?d. 寄存器是 caller 保存还是 callee保存?是全体保存还是部分保存?

C测试代码:

#include<stdio.h>
int f1(int u, int v, int x, int y, int z){
   u *= 2;
   return u;
}
int f(int a, int b, int c, int d){
   a = a+b+c+d;
   b = b+c+d;
   c = c+d;
   int t = f1(a,b,c,d, a+b+c+d);
   return t;
}
int main(void){
   f(1,2,3,4);
}

a.      调用时返回地址放在链接寄存器lr中。

b.     传入的参数放在r0,r1,r2,r3四个寄存器中,多余的参数放在堆栈中。

c.      本地变量存放在堆栈高地址,传进来的参数放在堆栈低地址。

d.     寄存器r0,r1,r2,r3是caller保存,寄存器r4以上由callee保存。

 

6)MLA 是带累加的乘法,尝试要如何写 C 的表达式能编译得到 MLA 指令。

C测试代码:

#include<stdio.h>
inr f1(int a, int b, int c){
  return a*b+c;  
}

int main(void){
   f1(1,2,3);
}

反汇编结果:

gcc -c mla.c -O3
-O3 是用来表示优化指令,有O1,O2,O3三档优化。这里要出现MLA,必须要用优化

可以发现使用了MLA指令。

 

7)BIC是对某一个比特清零的指令,尝试要如何写 C 的表达式能编译得到BIC 指令。

C测试代码:

#include<stdio.h>
int f(int a, int b){
  int t = a & ~b;
  return t;
}
int main(void){
   f(0x83, 0x0F);
}

反汇编:

gcc -c bic.c -O3

可以发现使用了bic指令,进行了高4位比特清零。

 

8)编写一个汇编函数,接受一个整数和一个指针作为输入,指针所指应为一个字符串,该汇编函数调用C语言的printf()函数输出这个字符串的前n个字符,n即为那个整数。在C语言写的main()函数中调用并传递参数给这个汇编函数来得到输出。


C语言实现为:

void f(char* a, int n){

int i;

for( i = 0; i < n; i++)

   printf(“%c”, a[i]);

}

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值