【Raspberry Pi系列】4. ARM指令

我们有必要了解我们手中的板子到底最根本的机制——汇编语言。树莓派是建立在ARM指令的基础上的。接下来的几篇文章并不试图从机器码的角度来详细分析ARM汇编的详细原理,而是通过实际的通过C语言反汇编的分析以及自行编写简单的汇编指令,来对ARM指令有一些基础的了解。

这里我们假设读者已经有了MIPS汇编基础或者Intel处理器汇编的基础。关于基本的运算指令、存储/读取指令、转移指令不会详细介绍。不过下面部分代码还是给出了部分汇编代码的注释,以供理解。


器材

硬件

  • 实验主板一块,本试验使用树莓派
  • 5V/1A电源一个
  • microUSB线一根

自备器材

  • PC(Linux)一台;
  • USB无线网卡;

软件

  • 交叉编译工具链。

步骤

1. 交叉编译之生成Thumb指令&ARM指令

Thumb是ARM体系结构中一种16位的指令集。Thumb指令集可以看作是ARM指令压缩形式的子集,它是为减小代码量而提出,具有16bit的代码密度。

Thumb指令体系并不完整,只支持通用功能,必要时仍需要使用ARM指令,如进入异常时。其指令的格式与使用方式与ARM指令集类似,而且使用并不频繁,Thumb指令集作一般了解。

这一步我们通过编译参数改变,相同的程序,ARM和Thumb编译的结果有何不同, 包括比较指令本身和整体目标代码的大小等。首先我们写一段用于交叉编译的代码:

#include <stdio.h>
int main(){
  int t = 72;
  printf("%d Hello world!\n",t);
}

然后复制为arm.c以及thumb.c来分别进行编译,首先对arm.c编译为ARM指令,使用指令:arm-bcm2708hardfp-linux-gnueabi-gcc -c arm.c

对thumb.c进行编译,这时我们需要设置对应的参数,使用命令arm-bcm2708hardfp-linux-gnueabi-gcc -c -mthumb -msoft-float thumb.c

此时使用交叉编译工具链中的objdump工具来进行反汇编,查看我们获得的对应的.o文件中的指令内容,使用指令分别查看,结果截图如下:

反汇编结果

返汇编结果

可以看到明显ARM指令是32位指令,编码为8位十六进制,而Thumb指令则是16位指令,从指令条数来看Thumb是要比ARM要复杂,但是从整体的文件大小来看,是Thumb要比较小:
arm&thumb比较

2. ARM 指令中的条件执行指令

下面我们来对指令中的条件执行指令,查看具体翻译之后的结果观察是否出现我们想要看到的指令。首先编写一段具有条件执行指令的代码:

#include <stdio.h>
int main(){
        int a=72,b=15;
        int res;
        if(a>b)
                res = a-b;
        else
                res = b-a;
}

编译后反汇编得到代码如下图所示:
结果

此时观察到ble指令出现,整个流程的注释可以如下所示:

00000000 <main>:
   0:   e52db004    push {fp}          ;(str fp, [sp, #-4]!)  保护fp帧指针
   4:   e28db000    add fp, sp, #0     ;将sp的值赋给fp,保护sp指针值
   8:   e24dd014    sub sp, sp, #20    ;栈增长5个字节
   c:   e3a03048    mov r3, #72        ;0x48,将r3寄存器赋值为72
  10:   e50b3008    str r3, [fp, #-8]  ;将r3的值(72)存到fp-8
  14:   e3a0300f    mov r3, #15        ;将r3寄存器赋值位15
  18:   e50b300c    str r3, [fp, #-12] ;存入fp-12
  1c:   e51b2008    ldr r2, [fp, #-8]  ;将fp-8的值载入r2=72
  20:   e51b300c    ldr r3, [fp, #-12] ;r3=15
  24:   e1520003    cmp r2, r3         ;比较r2r3的值的大小
  28:   da000004    ble 40 <main+0x40> ;如果结果为小于则跳转到main+0x40的地址
  2c:   e51b2008    ldr r2, [fp, #-8]
  30:   e51b300c    ldr r3, [fp, #-12]
  34:   e0633002    rsb r3, r3, r2
  38:   e50b3010    str r3, [fp, #-16]
  3c:   ea000003    b   50 <main+0x50> ;直接跳转到main+0x50地址
  40:   e51b200c    ldr r2, [fp, #-12]
  44:   e51b3008    ldr r3, [fp, #-8]
  48:   e0633002    rsb r3, r3, r2
  4c:   e50b3010    str r3, [fp, #-16]
  50:   e1a00003    mov r0, r3
  54:   e28bd000    add sp, fp, #0
  58:   e8bd0800    pop {fp}           ;恢复fp指针
  5c:   e12fff1e    bx  lr             ;返回倒link register 中的值

3. C 代码场景下的寄存器观察

(1)观察是否产生了寄存器移位寻址:

编写测试代码如下所示:

#include <stdio.h>  
int main() {  
        int t[10];  
        int i = 0;  
        int j = 0;  
        for(j=0; j<4; j++) {  
                t[8] = t[i*2];  
        }  
        printf("%d", t[8]);     
        return 0;  
}  

汇编代码如下所示:


                
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值