0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

深度剖析ARM内核寄存器及基本汇编语言3

jf_78858299 来源:矜辰所致 作者:矜辰所致 2023-04-24 10:01 次阅读

三、代码反汇编简析

  • 汇编 汇编文件转换为目标文件(里面是机器码,机器码是给CPU使用的,烧录保存在Flash空间的就是机器码)。
  • 反汇编 可执行文件(目标文件,里面是机器码),转换为汇编文件。

3.1 不同编译器的反汇编

3.1.1 Keil下面生成反汇编文件

fromelftext -a -c –output=(改成你想生成的反汇编名字一般是工程名字).dis (需要的axf文件,根据你工程生成axf的路径填写).axf图片设置好以后编译之后就会生成反汇编.dis文件:图片

打开如下所示:图片对于上图中的红色圈出来的语句,我们可以根据本文 第 二 章节的第2小节 ARM汇编格式中的介绍来分析一下:图片

简单分析如下(立即数就不分析了= =!):图片

3.1.2 gcc下生成反汇编文件

在X86架构下的电脑上生成ARM架构的汇编代码有两种方式:

  • 使用交叉编译工具链 指定-S选项可以生成汇编中间文件。ex:gcc -S test.c
  • 使用 objdump 反汇编 arm二进制文件。

上述两种方法的区别为:

(1)反汇编可以生成ARM指令操作码,-S生成的汇编没有指令码 (2)反汇编的代码是经过编译器优化过的。(3)反汇编代码量很大。

对于ARM Cortex-M,使用的是 arm-none-eabi-objdump,常用指令如下:

  • arm-none-eabi-objdump -d -S(可省) a1.o 查看a1.o反汇编可执行段代码
  • arm-none-eabi-objdump -D -S(可省) a1.o 查看a1.o反汇编所有段代码
  • arm-none-eabi-objdump -D -b binary -m arm ab.bin 查看ab.bin反汇编所有代码段

对于使用 arm-none-eabi-gcc 工具链(以STM32CUbeMX)的内核来说,使用如下方式生成反汇编文件:

$(OBJDUMP) -D -b binary -m arm (需要的elf文件,一般是工程名字).elf > (改成你想生成的反汇编名字,一般是工程名字).dis # OBJDUMP = arm-none-eabi-objdump

-D表示对全部文件进行反汇编,-b表示二进制,-m表示指令集架构

Makefile修改如下:

...
TARGET = D6TPir
#######################################
# paths
#######################################
# Build path
BUILD_DIR = build
...
PREFIX = arm-none-eabi-
...
OBJDUMP = $(PREFIX)objdump

dis:
 $(OBJDUMP) -D -b binary -m arm $(BUILD_DIR)/$(TARGET).elf > $(BUILD_DIR)/$(TARGET).dis
# $(OBJDUMP) -D -b binary -m arm $(BUILD_DIR)/$(TARGET).bin > $(BUILD_DIR)/$(TARGET).dis

执行 make dis 即可生成 .dis 文件:图片图片打开文件查看,发现怎么这个汇编语言有点不一样:图片经过研究了一段时间,加上了-M force-thumb后稍微有点样子了:图片! 在网上有各种参考,但是我都测试过了,并没有找到合适的生成完全和标准汇编一致的那种,-M后面的参数也不能乱加,需要根据自己的交叉编译器,因为这里用的是 arm-none-eabi-gcc,所以可以通过arm-none-eabi-objdump --help 查看能用的命令和参数: gcc工具链下的汇编还是不太熟悉,所以我们下面反汇编文件与 C语言的对比,使用Keil下的反汇编进行说明。

3.2 C 和 汇编 比较分析

前面介绍了那么多,最终用一个简单的程序对比一下C语言反汇编后的汇编语言,加深一下印象,当作个实战总结。

基于STM32L051(Cortex-M0)内核,目的是为了比较C和汇编,用了个最简单的程序来分析,没有用到任务外设,程序如下:

//前面省略...
void delay(u32 count)
{
 while(count--);
}

u32 add(u16 val1,u16 val2)
{
 u32 add_val;
 
 add_val = val1 + val2;
 
 return add_val;
}
 int main(void)
 {
 u16 a,b;
 u32 c;
 a = 12345;
 b = 45678;
 c = add(a,b);
 while(1)
 {
   c--;
   delay(200000);
  }
 }

反汇编的代码对应部分如下(因为基于硬件平台,其他异常中断,堆,栈,包括其他一些也有汇编代码,这里省略):

;省略前面
    delay
        0x080001ae:    bf00        ..      NOP      
        0x080001b0:    1e01        ..      SUBS     r1,r0,#0
        0x080001b2:    f1a00001    ....    SUB      r0,r0,#1
        0x080001b6:    d1fb        ..      BNE      0x80001b0 ; delay + 2
        0x080001b8:    4770        pG      BX       lr
    add
        0x080001ba:    4602        .F      MOV      r2,r0
        0x080001bc:    1850        P.      ADDS     r0,r2,r1
        0x080001be:    4770        pG      BX       lr
    main
        0x080001c0:    f2430439    C.9.    MOV      r4,#0x3039
        0x080001c4:    f24b256e    K.n%    MOV      r5,#0xb26e
        0x080001c8:    4629        )F      MOV      r1,r5
        0x080001ca:    4620         F      MOV      r0,r4
        0x080001cc:    f7fffff5    ....    BL       add ; 0x80001ba
        0x080001d0:    4606        .F      MOV      r6,r0
        0x080001d2:    e003        ..      B        0x80001dc ; main + 28
        0x080001d4:    1e76        v.      SUBS     r6,r6,#1
        0x080001d6:    4804        .H      LDR      r0,[pc,#16] ; [0x80001e8] = 0x30d40
        0x080001d8:    f7ffffe9    ....    BL       delay ; 0x80001ae
        0x080001dc:    e7fa        ..      B        0x80001d4 ; main + 20
    $d
        0x080001de:    0000        ..      DCW    0
        0x080001e0:    e000ed0c    ....    DCD    3758157068
        0x080001e4:    05fa0000    ....    DCD    100270080
        0x080001e8:    00030d40    @...    DCD    200000
;省略后面

3.2.1 MOV后面 立即数的疑问

在对比分析这段代码前,在 main 函数中的第一句:

0x080001c0:    f2430439    C.9.    MOV      r4,#0x3039

就有一个大大的疑问, MOV r4,#0x3039中 0x3039 并不是立即数(按照我们第二章 立即数的说明) ,包括接下来的 0xb26e 也不是立即数,怎么可以直接用 mov,按理来说需要用 LDR伪指令的??

至于这个问题,网上简单查找了一下,找到一篇有关说明的文章:ARM 汇编的mov操作立即数的疑问 其中有说到,在 keil 公司方网站里关于arm汇编的说明里有这么一段:

Syntax MOV{cond} Rd, #imm16 where: imm16 is any value in the range 0-65535.

所以是不是在 Keil 中的arm汇编 立即数可以使16位的?

为了验证一下,我稍微修改了一下程序,就是把a的值赋值超过16位(当然定义函数之类的也要跟着改,测试代码中a为u16的无符号整形),测试了一下。

a赋值为 65535,结果如下(65535不是立即数,也可以直接mov):

0x080001c0:    f64f75ff    O..u    MOV      r5,#0xffff

a赋值为 65536,结果如下(65536是立即数,可以直接mov):

0x080001c0:    f44f3580    O..5    MOV      r5,#0x10000

a赋值为一个大于16位的,不是立即数的数,比如:0x1FFFF :

0x080001c0:    4d08        .M      LDR      r5,[pc,#32] ; [0x80001e4] = 0x1ffff

果然,最后当 a 大于16位,不是立即数时候,会使用伪指令 LDR,所以我们可以得出结论:

在 Keil 中的arm汇编中,16位内(包括16位)的数都直接使用 MOV 赋值,大于16位,如果是立即数,直接使用MOV,不是立即数用LDR (立即数的判断方式还是前面讲的那样)

3.2.2 反汇编文件解析

对于上面的示例程序的汇编码,简单解析如下:图片添加一个有意思的测试对于delay函数中的语句,上图是while(count--);改成while(--count);后汇编代码如下:图片

对于上面的测试程序,汇编中并没有使用到 PUSH 和 POP 指令,因为程序太简单了,不需要使用到栈,为了能够熟悉下单片机中必须且经常需要用到的 栈,我们稍微修改一下add函数,在add函数中调用了delay函数:

u32 add(u16 val1,u16 val2)
{
 u32 add_val;
 
 add_val = val1 + val2;
 
 delay(10);
 
 return add_val;
}

对于的add函数汇编代码如下:

add
        0x080001ba:    b530        0.      PUSH     {r4,r5,lr}   ;把r4 r5 lr的值入栈
        0x080001bc:    4603        .F      MOV      r3,r0
        0x080001be:    460c        .F      MOV      r4,r1
        0x080001c0:    191d        ..      ADDS     r5,r3,r4
        0x080001c2:    200a        .       MOVS     r0,#0xa
        0x080001c4:    f7fffff3    ....    BL       delay ; 0x80001ae
        0x080001c8:    4628        (F      MOV      r0,r5
        0x080001ca:    bd30        0.      POP      {r4,r5,pc}  ;把r4 r5 lr的值出栈,

(汇编中可以看到指令后面后面加了个S ,MOVS 、ADDS,这就是我们前面说到的,带了S 会影响 xPSR 寄存器中的值)

可以看到,因为存在函数的多次调用,main函数中调用add函数,add函数中调用delay函数,所以在add函数运行之前,通过 push 把 r4,r5,lr 寄存器的值先存入栈中,等待程序执行完(函数调用结束)再吧 r4,r5,lr 寄存器的值恢复。

上面的程序虽然简单,但是通过我们C程序 与 汇编程序的对比分析,能够让我们更加深入的理解汇编语言。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM
    ARM
    +关注

    关注

    134

    文章

    9045

    浏览量

    366791
  • 寄存器
    +关注

    关注

    31

    文章

    5317

    浏览量

    119996
  • PC
    PC
    +关注

    关注

    9

    文章

    2065

    浏览量

    154016
  • 汇编语言
    +关注

    关注

    14

    文章

    409

    浏览量

    35736
收藏 人收藏

    评论

    相关推荐

    汇编语言长什么样子的呢

    文章目录汇编语言长什么的样子呢?ARM汇编指令条件和状态Status码ARM汇编寻址方式数据操作(ALU操作)逻辑操作(与,或,非,异或)比
    发表于 12-14 07:28

    如何用C语言寄存器汇编语言去实现流水灯

    目录一、初始化1、地址映射和寄存器映射2、接线3、程序下载二、用C语言寄存器实现流水灯三、汇编语言实现流水灯四、心得一、初始化1、地址映射和
    发表于 02-10 07:55

    ARM汇编语言与指令格式资料分享

    1、ARM汇编语言与指令格式介绍汇编语言介绍概念指的是用助记符代替操作码,用地址符号或标签(:#&)代替地址码的编程语言。优缺点优点:可以直接访问硬件目标,代码简短,执行速度快
    发表于 04-22 16:10

    汇编语言教程-段寄存器的说明语句

    汇编语言教程-段寄存器的说明语句   在汇编语言源程序中可以定义多个段,每个段都要与一个段寄存器建立一种对应关系。建立这
    发表于 03-27 17:17 1389次阅读

    ARM汇编语言官方手册(中文)

    ARM汇编语言官方手册(中文)汇编语言ARM汇编语言官方手册(中文)
    发表于 12-28 15:02 212次下载

    汇编语言

    汇编语言举例,比如读寄存器内容的源代码、汇编语言制作的光带菜单及源程序、获得操作系统版本的汇编源代码等
    发表于 12-31 10:40 33次下载

    51单片机汇编语言教程_单片机的特殊功能寄存器

    51单片机汇编语言教程:7课单片机的特殊功能寄存器
    发表于 01-19 15:26 0次下载

    汇编语言学习

    寄存器 一个cpu有多个寄存器 就是cpu中可以存储数据的器件,一个cpu中有多个寄存器汇编语言由一下3类组成 1、
    发表于 11-23 18:06 14次下载
    <b class='flag-5'>汇编语言</b>学习

    [从零学习汇编语言] -寄存器详解

    文章目录前言一、 存储与通用寄存器1. 存储2. 通用寄存器前言上一章我们曾简单的介绍过计算机中的一些硬件和软件的相关概念,还不熟悉的小伙伴可以点击下面的链接进行预习:[
    发表于 11-26 20:51 8次下载
    [从零学习<b class='flag-5'>汇编语言</b>] -<b class='flag-5'>寄存器</b>详解

    [从零学习汇编语言] - 寄存器与内存访问

    [从零学习汇编语言] - 寄存器与内存访问
    发表于 11-26 20:51 13次下载
    [从零学习<b class='flag-5'>汇编语言</b>] - <b class='flag-5'>寄存器</b>与内存访问

    ARM汇编语言官方手册

    ARM汇编语言官方手册
    发表于 10-10 10:44 29次下载

    深度剖析ARM内核寄存器及基本汇编语言1

    M3/M4内核寄存器 * 1.2 A7内核寄存器 * 1.3 ARM中的PC指针的
    的头像 发表于 04-24 09:59 942次阅读
    <b class='flag-5'>深度</b><b class='flag-5'>剖析</b><b class='flag-5'>ARM</b><b class='flag-5'>内核</b><b class='flag-5'>寄存器</b>及基本<b class='flag-5'>汇编语言</b>1

    深度剖析ARM内核寄存器及基本汇编语言2

    M3/M4内核寄存器 * 1.2 A7内核寄存器 * 1.3 ARM中的PC指针的
    的头像 发表于 04-24 10:00 1050次阅读
    <b class='flag-5'>深度</b><b class='flag-5'>剖析</b><b class='flag-5'>ARM</b><b class='flag-5'>内核</b><b class='flag-5'>寄存器</b>及基本<b class='flag-5'>汇编语言</b>2

    单片机汇编语言的结构/数据类型/汇编指令

    开发汇编语言是为了为机器级代码指令提供助记符或符号,汇编语言程序由助记符组成,因此应将它们翻译成机器代码。负责这种转换的程序称为汇编程序。汇编语言通常被称为低级
    的头像 发表于 07-07 12:28 2900次阅读

    ARM汇编语言工具

    电子发烧友网站提供《ARM汇编语言工具.pdf》资料免费下载
    发表于 11-06 09:12 0次下载
    <b class='flag-5'>ARM</b><b class='flag-5'>汇编语言</b>工具