嵌入式linux核心课程 1.ARM裸机全集 1.2.ARM裸机第二部分-ARM体系结构与汇编指令
1.ARM裸机全集
- 1.2.ARM裸机第二部分-ARM体系结构与汇编指令
- 1.2.1. 可编程器件的编程原理
- 1.2.2.指令集对CPU的意义
- 1.2.3.RISC和CISC的区别
- 1.2.4.统一编址_独立编址_冯诺依曼结构_哈佛结构
- 1.2.5.软件编程控制硬件的关键-寄存器
- 1.2.7.S5PV210的内存映射详解
- 1.2.8.CPU和外部存储器的接口
- 1.2.9.S5PV210的启动过程详解
- 1.2.11.如何在开发板上选择不同启动方式
- 1.2.12.ARM的编程模式和7种模式
- 1.2.13.ARM的37个寄存器详解
- 1.2.14.ARM的异常处理方式简单介绍
- 1.2.15_16.ARM汇编指令集1_2
- 1.2.17.ARM汇编指令集3
- 1.2.18.ARM汇编指令集4
- 1.2.19.ARM汇编指令集5 ldm/stm与栈的处理
- 1.2.20.ARM汇编伪指令
1.2.ARM裸机第二部分-ARM体系结构与汇编指令
1.2.1. 可编程器件的编程原理
可编程器件的特点
- CPU在固定频率的时钟控制下节奏运行。
- CPU可以通过总线读取外部存储设备中的二进制指令集,然后解码执行。
- 这些可以被CPU解码执行的二进制指令集是CPU设计的时候确定的,是CPU的设计者(ARM公司)定义的,本质上是一串由1和0组成的数字。这就是CPU的汇编指令集。
整个编程及运行过程
- 程序员用汇编指令编程
–经汇编器汇编成二进制可执行程序文件–>二进制文件被CPU读取进去–>CPU内部电路对二进制文件解码–>解码通过则CPU执行指令、完成指令动作。 - 如果程序员用C语言等高级语言编程,则编译器先将C语言程序编译为汇编程序,再进行上面的后续部分。
从源代码到CPU执行过程
1.2.2.指令集对CPU的意义
汇编语言的本质
- 汇编的实质是机器指令(机器码)的助记符,是一种低级符号语言。
- 机器指令集是一款CPU的编程特征,是这款CPU的设计者制定的。CPU的内部电路设计就是为了实现这些指令集的功能。机器指令集就好象CPU的API接口一样。
编程语言的发展过程
- 纯机器码编程
- 汇编语言编程
- C语言编程
- C++语言编程
- Java C#等语言编程
- 脚本语言编程
总结
使用汇编编程可以充分发挥CPU的设计特点,所以汇编编程效率最高,因此在操作系统内核中效率极其重要处都需要用汇编处理。
1.2.3.RISC和CISC的区别
CISC
- complex instruction set computer复杂指令集CPU
- CISC体系的设计理念是用最少的指令来完成任务(譬如计算乘法只需要一条MUL指令即可),因此CISC的CPU本身设计复杂、工艺复杂,但好处是编译器好设计。CISC出现较早,至今Intel还一直采用CISC设计
RISC
- Reduced Instruction-Set Computer精简指令集CPU
- RISC的设计理念是让软件来完成具体的任务,CPU本身仅提供基本功能指令集。因此RISC
CPU的指令集中只有很少的指令,这种设计相对于CISC,CPU的设计和工艺简单了,但是编 7ff7 译器的设计变难了。
CPU设计方式发展
- 早期简单CPU,指令和功能都很有限
- CISC年代 —— CPU功能扩展依赖于指令集的扩展,实质是CPU内部组合逻辑电路的扩展。
- RISC年代 ——CPU仅提供基础功能指令(譬如内存与寄存器通信指令,基本运算与判断指令等),功能扩展由使用CPU的人利用基础架构来灵活实现。
RISC与CISC指令数对比
- 一般典型CISC CPU指令在300条左右
- ARM CPU常用指令30条左右
发展趋势
没有纯粹的RISC或CISC,发展方向是RISC与CISC结合,形成一种介于2者之间的CPU类型。
1.2.4.统一编址_独立编址_冯诺依曼结构_哈佛结构
内存的访问方式
- 内存通过CPU的地址总线来寻址定位,然后通过CPU数据总线来读写。
- CPU的地址总线的位数是CPU设计时确定的,因此一款CPU所能寻址的范围是一定的,而内存是需要占用CPU的寻址空间的。
- 内存与CPU的这种总线式连接方式是一种直接连接,优点是效率高访问快,缺点是资源有限,扩展性差。
IO的访问方式
- IO指的是与CPU连接的各种外设
- CPU访问各种外设有2种方式:
一种是类似于访问内存的方式
,即把外设的寄存器当作一个内存地址来读写,从而以访问内存相同的方式来操作外设,叫IO与内存统一编址方式
;
另一种是使用专用的CPU指令
来访问某种特定外设,叫IO与内存独立编址
。
对比
- 由于内存访问频率高,因此采用总线式连接,直接地址访问,效率最高。
- IO与内存统一编址方式,优势是IO当作内存来访问,编程简单;缺点是IO也需要占用一定的CPU地址空间,而CPU的地址空间是有限资源。
- IO与内存独立编织方式,优势是 不占用CPU地址空间,缺点是CPU设计变复杂了。
程序和数据
- 程序运行时两大核心元素:程序 + 数据
- 程序是我们写好的源代码经过编译、汇编之后得到的机器码,这些机器码可以拿给CPU去解码执行,CPU不会也不应该去修改程序,所以程序是只读的。
- 数据是程序运行过程中定义和产生的变量的值,是可以读写的,程序运行实际就是为了改变数据的值。
冯诺依曼结构与哈佛结构
- 程序和数据都放在内存中,且不彼此分离的结构称为冯诺依曼结构。譬如Intel的CPU均采用冯诺依曼结构。
- 程序和数据分开独立放在不同的内存块中,彼此完全分离的结构称为哈佛结构。譬如大部分的单片机(MCS51、ARM9等)均采用哈佛结构。
优劣对比
- 冯诺依曼结构中程序和数据不区分的放在一起,因此安全和稳定性是个问题,好处是处理起来简单。
- 哈佛结构中程序(一般放在ROM、flash中)和数据(一般放在RAM中)独立分开存放,因此好处是安全和稳定性高,缺点是软件处理复杂一些(需要统一规划链接地址等)
1.2.5.软件编程控制硬件的关键-寄存器
两类寄存器
SoC中有2类寄存器:通用寄存器和SFR
- 通用寄存器(ARM中有37个)是CPU的组成部分,CPU的很多活动都需要通用寄存器的支持和参与。
- SFR(special function register,特殊功能寄存器)
不在CPU中
,而存在于CPU的外设中
,我们通过访问外设的SFR来编程操控这个外设,这就是硬件编程控制的方法。
1.2.7.S5PV210的内存映射详解
一些专业术语1
- ROM:read only memory 只读存储器
- RAM:ramdom access memory 随机访问存储器
- IROM:internal rom 内部ROM,指的是集成到SoC内部的ROM
- IRAM:internal ram 内部RAM,指的是集成到SoC内部的RAM
- DRAM:dynamic ram 动态RAM
- SRAM:static ram 静态RAM
S5PV210 datasheet中内存映射位置
1.2.8.CPU和外部存储器的接口
内存
- 内部存储器 用来运行程序的 RAM
- 举例(DRAM SRAM DDR)
外存
- 外部存储器 用来存储东西的 ROM
- 举例(硬盘 Flash(Nand iNand···· U盘、SSD) 光盘)
CPU连接内存和外存的连接方式不同
- 内存需要直接地址访问,所以是通过地址总线&数据总线的总线式访问方式连接的(好处是直接访问,随机访问;坏处是占用CPU的地址空间,大小受限);
- 外存是通过CPU的外存接口来连接的(好处是不占用CPU的地址空间,坏处是访问速度没有总线式快,访问时序较复杂)
SoC常用外存
- NorFlash:总线式访问,接到
SROM bank
,优点是可以直接总线访问
,一般用来启动
。 - NandFlash: 分为SLC和MLC
- eMMC/iNand/moviNand:eMMC(
embeded MMC
) iNand是SanDisk公司出产的eMMC,moviNand是三星公司出产的eMMC - oneNAND:oneNand是三星公司出的一种Nand
- SD卡/TF卡/MMC卡
- eSSD
- SATA硬盘(机械式访问、磁存储原理、SATA是接口)
X210开发板支持的外部存储器
- X210有2个版本,Nand版和iNand版,分别使用Nandflash和iNand为外部存储器。我们使用的是iNand版本,板载4GB iNand
- S5PV210共支持4个SD/MMC通道,其中通道0和2依次用作启动。X210开发板中SD/MMC0通道用于连接板载MMC,因此外部启动时只能使用SD/MMC2通道(注意通道3不能启动)。见《S5PV210_iROM_ApplicationNote_Preliminary_20091126.pdf》中P6
1.2.9.S5PV210的启动过程详解
S5PV210启动过程概述
- 1、210内部有iROM和iRAM,因此启动时分两个阶段:内部启动阶段和外部启动阶段。对于内部启动阶段各种S5PV210的开发板都是相同的,对于外部启动阶段,不同开发板会有不同。
- 启动过程主要参考《S5PV210_iROM_ApplicationNote_Preliminary_20091126.pdf》
iROM和iRAM
- S5PV210出厂时内置了64KB iROM和96KB iRAM。iROM中预先内置烧录了一些代码(称为iROM代码),iRAM属于SRAM(不需软件初始化,上电即可使用)。210启动时首先在内部运行iROM代码,然后由iROM代码开启外部启动流程。
- 为什么需要设计iROM和iRAM?答案是为了支持多种外部设备启动。
内存:
SRAM 静态内存特点就是容量小、价格高,优点是不需要软件初始化直接上电就能用
DRAM 动态内存特点就是容量大、价格低,缺点就是上电后不能直接使用,需要软件初始化后才可以使用。
实际中
单片机中:内存需求量小,而且希望开发尽量简单,适合全部用SRAM
嵌入式系统:内存需求量大,而且没有NorFlash等可启动介质
PC机: 内存需求量大,而且软件复杂,不在乎DRAM的初始化开销,适合全部用DRAM
外存:
NorFlash:特点是容量小,价格高,优点是可以和CPU直接总线式相连,CPU上电后可以直接读取,所以一般用作启动介质。
NandFlash(跟硬盘一样):特点是容量大,价格低,缺点是不能总线式访问,也就是说不能上电CPU直接读取,需要CPU先运行一些初始化软件,然后通过时序接口读写。
实际中
所以
一般PC机都是:很小容量的BIOS(NorFlash)+ 很大容量的硬盘(类似于NandFlash)+ 大容量的DRAM
一般的
单片机:很小容量的NorFlash + 很小容量的SRAM
嵌入式系统:因为NorFlash很贵,随意现在很多嵌入式系统倾向于不用NorFlash,直接用:外接的大容量Nand + 外接大容量DRAM + SoC内置SRAM
S5PV210使用的启动方式是:
外接的大容量Nand + 外接大容量DRAM + SoC内置SRAM
实际上210的启动还要更好玩一些,210内置了一块96KB大小的SRAM(叫iRAM),同时还有一块内置的64KB大小的
NorFlash(叫iROM)。
210的启动过程大致是:
- 第一步:CPU上电后先从内部IROM中读取预先设置的代码(BL0),执行。这一段IROM代码首先做了一些基本的初始化(CPU时钟、关看门狗···)(这一段IROM代码是三星出厂前设置的,三星也不知道我们板子上将来接的是什么样的DRAM,因此这一段IROM是不能负责初始化外接的DRAM的,因此这一段代码只能初始化SoC内部的东西);然后这一段代码会判断我们选择的启动模式(我们通过硬件跳线可以更改板子的启动模式),然后从相应的外部存储器去读取第一部分启动代码(BL1,大小为16KB)到内部SRAM。
- 第二步:从IRAM去运行刚上一步读取来的BL1(16KB),然后执行。BL1负责初始化NandFlash,然后将BL2读取到IRAM(剩余的80KB)然后运行
- 第三步:从IRAM运行BL2,BL2初始化DRAM,然后将OS读取到DRAM中,然后启动OS,启动过程结束。
思路:因为启动代码的大小是不定的,有些公司可能96kb就够了,有些公司可能1MB都不够。所以刚才说的2步的启动方式不合适。三星的解决方案是:把启动代码分为2半(BL1和BL2),这两部分协同工作来完成启动。
BL0做了什么?
- 关看门狗
- 初始化指令cache
- 初始化栈
- 初始化堆
- 初始化块设备复制函数device copy function
- 设置SoC时钟系统
- 复制BL1到内部IRAM(16KB)
- 检查BL1的校验和
- 跳转到BL1去执行
S5PV210的所有启动
- 先1st启动,通过OMpin选择启动介质
- 再2nd启动,从SD2
- 再Uart启动
- 再USB启动
1.2.11.如何在开发板上选择不同启动方式
SoC通过OMpin来识别外部启动介质
从SD2启动
可以使用外置SD卡从SD2通道启动,但这需要先破坏板载的eMMC中的android镜像。破坏方法见九鼎官方的裸机教程文档《x210v3开发板裸机教程.pdf》中2.5.2节(P19)
小结
- 拨码开关设置我们只需动OM5即可,其他几个根本不需要碰。需要SD启动时OM5打到GND,需要USB启动时OM5打到VCC
- 可以先不销毁eMMC中的android,而使用USB启动来做裸机调试。之后课程中我们会使用USB启动和SD卡启动两种方式共同来完成实验,让大家对比学习。
1.2.12.ARM的编程模式和7种模式
ARM的基本设定
-
ARM 采用的是32位架构.
-
ARM 约定:
Byte : 8 bits
Halfword :16 bits (2 byte)
Word : 32 bits (4 byte) -
大部分ARM core 提供:
ARM 指令集(32-bit)
Thumb 指令集(16-bit )
Thumb2指令集(16 & 32bit)
Jazelle cores 支持 Java bytecode
ARM处理器工作模式
ARM 有7个基本工作模式:
- User : 非特权模式,大部分任务执行在这种模式
- FIQ : 当一个高优先级(fast) 中断产生时将会进入这种模式
- IRQ : 当一个低优先级(normal) 中断产生时将会进入这种模式
- Supervisor :当复位或软中断指令执行时将会进入这种模式
- Abort : 当存取异常时将会进入这种模式
- Undef : 当执行未定义指令时会进入这种模式
- System : 使用和User模式相同寄存器集的特权模式
注意
- 除User(用户模式)是Normal(普通模式)外,其他6种都是Privilege(特权模式)。
- Privilege中除Sys模式外,其余5种为异常模式。
- 各种模式的切换,可以是程序员通过代码主动切换(通过写CPSR寄存器);也可以是CPU在某些情况下自动切换。
- 各种模式下权限和可以访问的寄存器不同。
CPU为什么设计这些模式?
- CPU是硬件,OS是软件,软件的设计要依赖硬件的特性,硬件的设计要考虑软件需要,便于实现软件特性。
- 操作系统有安全级别要求,因此CPU设计多种模式是为了方便操作系统的多种角色安全等级需要。
1.2.13.ARM的37个寄存器详解
ARM 寄存器
总结
- ARM共有37个寄存器,都是32位长度
- 37个寄存器中30个为“通用”型,1个固定用作PC,一个固定用作CPSR,5个固定用作5种异常模式下的SPSR。
CPSR程序状态寄存器
- 条件位:
N = Negative result from ALU
Z = Zero result from ALU
C = ALU operation Carried out
V = ALU operation oVerflowed - Q 位:
仅ARM 5TE/J架构支持
指示饱和状态 - J 位
仅ARM 5TE/J架构支持
J = 1: 处理器处于Jazelle状态
中断禁止位:
I = 1: 禁止 IRQ.
F = 1: 禁止 FIQ. - T Bit
仅ARM xT架构支持
T = 0: 处理器处于 ARM 状态
T = 1: 处理器处于 Thumb 状态 - Mode位:
处理器模式位
注意
- CPSR中各个bit位表明了CPU的某些状态信息,这些信息非常重要,和后面学到的汇编指令息息相关(譬如BLE指令中的E就和CPSR中的Z标志位有关)
- CPSR中的I、F位和开中断、关中断有关
- CPSR中的mode位(bit4~bit0共5位)决定了CPU的工作模式,在uboot代码中会使用汇编进行设置。
PC(r15)程序控制寄存器
- PC(Program control
register)为程序指针,PC指向哪里,CPU就会执行哪条指令(所以程序跳转时就是把目标地址代码放到PC中) - 整个CPU中只有一个PC(CPSR也只有一个,但SPSR有5个)。
1.2.14.ARM的异常处理方式简单介绍
什么是异常
- 正常工作之外的流程都叫异常
- 异常会打断正在执行的工作,并且一般我们希望异常处理完成后继续回来执行原来的工作
- 中断是异常的一种
异常向量表
- 所有的CPU都有异常向量表,这是CPU设计时就设定好的,是硬件决定的。
- 当异常发生时,CPU会自动动作(PC跳转到异常向量处处理异常,有时伴有一些辅助动作)
- 异常向量表是硬件向软件提供的处理异常的支持。
ARM的异常处理机制
-
当异常产生时, ARM core:
拷贝 CPSR 到 SPSR_<mode>
设置适当的 CPSR 位:
改变处理器状态进入 ARM 态
改变处理器模式进入相应的异常模式
设置中断禁止位禁止相应中断 (如果需要)
保存返回地址到 LR_<mode>
设置 PC 为相应的异常向量 -
返回时, 异常处理需要:
从 SPSR_恢复CPSR
从LR_恢复PC
Note:这些操作只能在 ARM 态执行.
总结
- 异常处理中有一些是硬件自动做的,有一些是程序员需要自己做的。需要搞清楚哪些是需要自己做的,才知道如何写代码。
- 以上说的是CPU设计时提供的异常向量表,一般成为一级向量表。有些CPU为了支持多个中断,还会提供二级中断向量表,处理思路类似于这里说的一级中断向量表。
1.2.15_16.ARM汇编指令集1_2
两个概念:指令与伪指令
- (汇编)指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以由CPU读取执行。
- (汇编)伪指令本质上不是指令(只是和指令一起写在代码中),它是编译器环境提供的,目的是用来指导编译过程,经过编译后伪指令最终不会生成机器码。
两种不同风格的ARM指令
- ARM官方的ARM汇编风格:指令一般用大写、Windows中IDE开发环境(如ADS、MDK等)常用。如: LDR R0, [R1]
- GNU风格的ARM汇编:指令一般用小写字母、linux中常用。如:ldr r0, [r1]
ARM汇编特点1:LDR/STR架构
- ARM采用RISC架构,CPU本身不能直接读取内存,而需要先将内存中内容加载入CPU中通用寄存器中才能被CPU处理
-ldr(load register)
指令将内存内容加载入通用寄存器。
-str(store register)
指令将寄存器内容存入内存空间中。
-ldr/str组合
用来实现ARM CPU和内存数据交换
ARM汇编特点2:8种寻址方式
- 寄存器寻址 mov r1, r2
- 立即寻址 mov r0, r1, lsl #3
- 寄存器间接寻址 ldr r1, [r2]
- 基址变址寻址 ldr r1, [r2, #4]
- 多寄存器寻址 ldmia r1!, {r2-r7, r12}
- 堆栈寻址 stmfd sp!, {r2-r7, lr}
- 相对寻址 beq flag
ARM汇编特点3:指令后缀
- 同一指令经常附带不同后缀,变成不同的指令。经常使用的后缀有:
- B(byte)功能不变,操作长度变为8位
- H(half word)功能不变,长度变为16位
- S(signed)功能不变,操作数变为有符号
- 如 ldr ldrb ldrh ldrsb ldrsh
- S(S标志)功能不变,影响CPSR标志位
- 如 mov和movs movs r0, #0
ARM汇编特点4:条件执行后缀
ARM汇编特点5:多级指令流水线
为增加处理器指令流的速度,ARM使用多级流水线。(S5PV210使用13级流水线,ARM11为8级)允许多个操作同时处理,而非顺序执行。
PC指向正被取指的指令,而非正在执行的指令
1.2.17.ARM汇编指令集3
常用ARM指令1:数据处理指令
- 数据传输指令 mov mvn
- 算术指令 add sub rsb adc sbc rsc
- 逻辑指令 and orr eor bic
- 比较指令 cmp cmn tst teq
- 乘法指令 mvl mla umull umlal smull smlal
- 前导零计数 clz
常用ARM指令2:cpsr访问指令
- mrs & msr
- mrs用来读psr,msr用来写psr
- CPSR寄存器比较特殊,需要专门的指令访问,这就是mrs和msr。
常用ARM指令3:跳转(分支)指令
- b & bl & bx
- b 直接跳转(就没打开算返回)
- bl branch and link,跳转前把返回地址放入lr中,以便返回,以便用于函数调用
- bx跳转同时切换到ARM模式,一般用于异常处理的跳转。
常用ARM指令4:访存指令
- ldr/str & ldm/stm & swp
- 单个字/半字/字节访问 ldr/str
- 多字批量访问 ldm/stm
- swp r1, r2, [r0]
- swp r1, r1, [r0]
ARM汇编中的立即数
- 合法立即数与非法立即数
- ARM指令都是32位,除了指令标记和操作标记外,本身只能附带很少位数的立即数。因此立即数有合法和非法之分。
合法立即数:经过任意位数的移位后非零部分可以用8位表示的即为合法立即数
常用ARM指令5:软中断指令
- swi(software interrupt)
- 软中断指令用来实现操作系统中系统调用
1.2.18.ARM汇编指令集4
协处理器cp15操作指令
- mcr & mrc
- mrc用于读取CP15中的寄存器
- mcr用于写入CP15中的寄存器
什么是协处理器
- SoC内部另一处理核心,协助主CPU实现某些功能,被主CPU调用执行一定任务。
- ARM设计上支持多达16个协处理器,但是一般SoC只实现其中的CP15.(cp:coprocessor)
- 协处理器和MMU、cache、TLB等处理有关,功能上和操作系统的虚拟地址映射、cache管理等有关。
MRC & MCR的使用方法
- mcr{} p15, <opcode_1>, , , , {<opcode_2>}
- opcode_1:对于cp15永远为0、
- Rd:ARM的普通寄存器
- Crn:cp15的寄存器,合法值是c0~c15
- Crm:cp15的寄存器,一般均设为c0
- opcode_2:一般省略或为0
协处理器学习要点
- 不必深究,将uboot中和kernel中起始代码中的一般操作搞明白即可。
- 只看一般用法,不详细区分参数细节,否则会陷入很多复杂未知中。
- 关键在于理解,而不在于记住。
1.2.19.ARM汇编指令集5 ldm/stm与栈的处理
为什么需要多寄存器访问指令
- ldr/str每周期只能访问4字节内存,如果需要批量读取、写入内存时太慢,解决方案是stm/ldm
- ldm(load register mutiple)
- stm(store register mutiple)
8种后缀
- ia(increase after)先传输,再地址+4ib(increase before)先地址+4,再传输
- da(decrease after)先传输,再地址-4
- db(decrease before)先地址-4,再传输
- fd(full decrease)满递减堆栈
- ed(empty decrease)空递减堆栈
- fa(·······) 满递增堆栈
- ea(·······)空递增堆栈
四种栈
- 空栈:栈指针指向空位,每次存入时可以直接存入然后栈指针移动一格;而取出时需要先移动一格才能取出
- 满栈:栈指针指向栈中最后一格数据,每次存入时需要先移动栈指针一格再存入;取出时可以直接取出,然后再移动栈指针
- 增栈:栈指针移动时向地址增加的方向移动的栈
- 减栈:栈指针移动时向地址减小的方向移动的栈
!的作用
- ldmia r0, {r2 - r3}
- ldmia r0!, {r2 - r3}
- 感叹号的作用就是r0的值在ldm过程中发生的增加或者减少
最后写回到r0去
,也就是说ldm时会改变r0的值。
^的作用
- ldmfd sp!, {r0 - r6, pc}
- ldmfd sp!, {r0 - r6, pc}^
- ^的作用:在目标寄存器中有pc时,会同时
将spsr写入到cpsr
,一般用于从异常模式返回
。
总结
- 批量读取或写入内存时要用ldm/stm指令
- 各种后缀以理解为主,不需记忆,最常见的是stmi和stmfd
- 谨记:操a作栈时使用相同的后缀就不会出错,不管是满栈还是空栈、增栈还是减栈
1.2.20.ARM汇编伪指令
伪指令的意义
- 伪指令不是指令,伪指令和指令的根本区别是经过编译后会不会生成机器码。
- 伪指令的意义在于指导编译过程。
- 伪指令是和具体的编译器相关的,我们使用gnu工具链,因此学习gnu环境下的汇编伪指令。
gnu汇编中的一些符号
- @ 用来做注释。可以在行首也可以在代码后面同一行直接跟,和C语言中//类似
- # 做注释,一般放在行首,表示这一行都是注释而不是代码。
- :以冒号结尾的是标号
- . 点号在gnu汇编中表示当前指令的地址
- # 立即数前面要加#或$,表示这是个立即数
常用gnu伪指令
- .global _start @ 给_start外部链接属性
- .section .text @ 指定当前段为代码段
- .ascii .byte .short .long .word .quad .float .string @ 定义数据
- .align 4 @ 以16字节对齐
- .balignl 16 0xabcdefgh @ 16字节对齐填充\
- .equ @ 类似于C中宏定义
偶尔会用到的gnu伪指令
- .end @标识文件结束
- .include @ 头文件包含
- .arm / .code32 @声明以下为arm指令
- .thumb / .code16 @声明以下为thubm指令
最重要的几个伪指令
- ldr 大范围的地址加载指令
- adr 小范围的地址加载指令
- adrl 中等范围的地址加载指令
- nop 空操作
ARM中有一个ldr指令,还有一个ldr伪指令, 一般都使用ldr伪指令而不用ldr指令
adr与ldr
- adr编译时会被1条sub或add指令替代,而ldr编译时会被一条mov指令替代或者文字池方式处理;
- adr总是以PC为基准来表示地址,因此指令本身和运行地址有关,可以用来检测程序当前的运行地址在哪里
- ldr加载的地址和链接时给定的地址有关,由链接脚本决定。
注:文章来源于《朱老师物联网大讲堂-----嵌入式linux核心课程》
注:文章来源于《朱老师物联网大讲堂-----嵌入式linux核心课程》
注:文章来源于《朱老师物联网大讲堂-----嵌入式linux核心课程》
- 1.2.ARM裸机第二部分-ARM体系结构与汇编指令
- 嵌入式linux核心课程 1.ARM裸机全集 1.7.ARM裸机第七部分-串口通信详解
- 嵌入式linux核心课程 1.ARM裸机全集 1.8.ARM裸机第八部分-按键和CPU的中断系统
- 嵌入式linux核心课程 1.ARM裸机全集 1.16.ARM裸机第十六部分-shell原理和问答机制引入
- 嵌入式linux核心课程 1.ARM裸机全集 1.12.ARM裸机第十二部分-I2C通信详解
- 嵌入式linux核心课程 1.ARM裸机全集 1.14.ARM裸机第十四部分-LCD显示器
- 嵌入式linux核心课程 1.ARM裸机全集 1.10.ARM裸机第十部分-SD卡启动详解
- 嵌入式Linux ARM汇编(五)——ARM体系结构过程调用标准
- 嵌入式Linux ARM汇编(五)——ARM体系结构过程调用标准
- 嵌入式linux核心课程 2.uboot和系统移植 2.1.uboot和系统移植第1部分-uboot学习前传
- 嵌入式Linux ARM汇编(三)——ARM汇编指令(三)
- ARM Linux启动流程分析——start_kernel前启动阶段(汇编部分)
- ARM嵌入式linux培训班视频 全集
- 嵌入式linux面试题解析(一)——ARM部分一
- 嵌入式Linux ARM汇编(四)——ARM汇编程序设计
- 嵌入式Linux ARM汇编(三)——ARM汇编指令(四)
- 嵌入式Linux ARM汇编(六)——GNU ARM汇编编程
- 嵌入式Linux ARM汇编(四)——ARM汇编程序设计
- 嵌入式Linux ARM汇编(七)——C语言与ARM汇编混合编程
- 嵌入式Linux ARM汇编(四)——ARM汇编程序设计