跳转至

2.4 ARM汇编语言程序设计

🟠 中频考点,重点是程序结构和伪指令

汇编语言程序结构

    AREA  MyCode, CODE, READONLY   ; 定义代码段
    ENTRY                           ; 程序入口

Start
    MOV R0, #10
    MOV R1, #20
    ADD R2, R0, R1

    ; 调用子程序
    BL MySubroutine

    ; 程序结束
    MOV R0, #0x18     ; angel_SWIreason_ReportException
    LDR R1, =0x20026
    SWI 0x123456

MySubroutine
    STMFD SP!, {R0-R12, LR}    ; 压栈保护寄存器
    ; ... 子程序代码 ...
    LDMFD SP!, {R0-R12, PC}    ; 出栈并返回(PC=LR)

    END                         ; 文件结束

常用伪指令

伪指令 功能
AREA 定义代码段或数据段
ENTRY 标记程序入口点
END 标记文件结束
EQU 定义常量(类似C的#define)
DCD 分配并初始化32位数据
DCB 分配并初始化8位数据
ALIGN 字节对齐
EXPORT 声明全局符号(让其他文件可以引用)
IMPORT 引用外部符号

ARM汇编与C语言混合编程

现代嵌入式开发通常用C写主要逻辑,只在需要高性能或直接操作硬件时用汇编。

在C中调用汇编函数

汇编文件(asm_func.s)

    AREA FuncArea, CODE, READONLY
    EXPORT MyAsmFunc           ; 导出给C文件使用

MyAsmFunc
    ; 函数参数通过R0-R3传入
    ADD R0, R0, R1             ; 返回值在R0
    MOV PC, LR                 ; 返回
    END

C文件

extern int MyAsmFunc(int a, int b);  // 声明

int result = MyAsmFunc(3, 5);  // 调用,result=8

在汇编中调用C函数

    IMPORT printf              ; 引用C的printf函数

    LDR R0, =format_string
    BL printf                  ; 调用C函数

内嵌汇编(在C中写汇编代码)

// 使用__asm关键字
void __asm enable_irq(void) {
    MRS R0, CPSR
    BIC R0, R0, #0x80      // 清除I位,允许IRQ
    MSR CPSR_c, R0
    MOV PC, LR
}

嵌入式系统硬件基础知识

时钟与复位

了解即可

  • 内部时钟:处理器内置振荡器,无需外部时钟
  • 外部时钟:大多数嵌入式处理器同时支持内部和外部时钟
  • nRESET引脚:前面的n表示低电平有效(active low)
  • 所有基于ARM内核的芯片都有JTAG调试接口

选择题

错误说法:"大部分嵌入式处理器只能使用内部时钟,不能使用外部时钟" → 错误! 大多数处理器两种都支持。答:B


真题演练

以下是NCRE三级嵌入式真题中与本节相关的典型考题:

1. 以下对伪指令的解释错误的是( )。

  • A)DCB 0x56;在内存区域分配一个字节的内存空间并初始化为0x56
  • B)CODE32;伪指令通知编译器,其后的指令序列为32位的Thumb指令
  • C)MyTest EQU 15000;定义一个常量MyTest值为15000,最大数为32位
  • D)EXPORT伪指令用于在程序中声明一个全局的标号,该标号可在其它的文件中引用
答案解析

答:B CODE32通知编译器其后的指令序列为32位的ARM指令,而不是"32位的Thumb指令"。Thumb指令是16位的,对应的伪指令是CODE16。注意区分:CODE16 → Thumb指令(16位),CODE32 → ARM指令(32位)。


2. 在ARM汇编语言伪指令中,通过编译器在当前文件中声明要引用的一个标号main,但它不在本文件定义中,在其它源文件中定义,则本文件中使用的伪指令是( )。

  • A)IMPORT main
  • B)EXPORT main
  • C)ENTRY main
  • D)COMMON main
答案解析

答:A IMPORT用于引用在其他源文件中定义的外部标号,相当于告诉编译器"这个符号不在本文件中,去别的文件找"。EXPORT则相反,用于将本文件的标号导出,使其他文件可以引用。ENTRY标记程序入口点,COMMON不是ARM汇编标准伪指令。


3. GCC是针对Linux操作系统环境下应用程序的编译工具,下面叙述中错误的是( )。

  • A)GCC将源文件生成可执行文件的过程是由:编译、汇编、连接等3个阶段组成
  • B)GCC能将C语言、C++语言、汇编语言编写的源程序生成执行文件
  • C)设计者若要对源程序进行调试,需要在GCC命令中加入-g参数来编译该源程序
  • D)用GCC把源文件仅编译成目标文件,那么,C语言编写的应用程序中可以不要main函数
答案解析

答:A GCC从源文件生成可执行文件的过程由四个阶段组成:预处理、编译、汇编、连接。A项遗漏了预处理阶段,因此错误。B、C、D三项叙述均正确。


4. 【填空题】由于Bootloader的实现依赖于CPU的体系结构,因此大多数Bootloader都分为stage1和stage2两大部分。依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在stage1中,且使用_语言来实现。而stage2则通常用C语言来实现,这样代码会具有更好的可读性和_性。

答案

答:汇编;可移植 Bootloader的stage1使用汇编语言编写,因为需要直接操作硬件且追求精简高效(短小精悍)。stage2用C语言编写,因为C语言具有更好的可读性和可移植性,便于实现更复杂的功能。


5. 【填空题】GNU开发工具套件中的C语言编译器,其英文简称是_。针对于ARM体系结构的目标机而言,其Linux环境下的C语言编译器命令书写格式中,其带前缀的命令是_。

答案

答:GCC;arm_linux_gcc GCC(GNU Compiler Collection)是GNU开发工具套件中的核心编译工具。当目标机为ARM体系结构时,交叉编译器的命令格式带有平台前缀,即arm_linux_gcc。

章节测验

进入 第二章测验 检验学习效果。