完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1. ARM的基本设定 1.1 ARM数据类型 1.1.1 基本数据类型 ① Byte:字节,8位 ② HalfWord:半字,16位(半字必须与2字节边界对齐) ③ Word:字,32位(字必须与4字节边界对齐) ④ DoubleWord(Cortex-A支持):双字,64位(双字必须与8字节对齐) 说明:关于地址对齐 ARMv6版本前的ARM处理器必须是地址对齐的,需要地址对齐的原因一般如下: ① 某些体系结构的CPU在访问未对齐的数据时会发生异常或产生不可预知的后果。 ② 有些CPU支持非对齐的数据访问,但会严重影响存取效率。 如果发生非对齐访问,可能有如下结果: ① 非对齐的指令预取操作 当执行ARM指令时,如果PC的值非对齐(低2位不是0),要么指令执行结果不可预知,要么地址值的低2位被忽略。 当执行Thumb指令时,如果PC的值非半字对齐(最低位不是0),要么指令执行结果不可预知,要么地址值的最低位被忽略。 ② 非对齐的数据访问操作 对于Load/Store操作,如果是非对齐的数据访问操作,系统定义了下面三种可能的结果: a. 执行结果不可预知 b. 忽略字单元地址的低2位,忽略半字单元地址的最低位。即访问地址为(address AND 0xFFFFFFFC)的字单元,或访问(addreee AND 0xFFFFFFFE)的半字单元 c. 忽略字单元地址的低2位,忽略半字单元地址的最低位。但这种忽略由存储系统实现,传递给存储系统时仍原封不动。 说明:具体行为可通过CP15协处理器配置 1.1.2 浮点数据类型 ① ARM硬件指令集中未定义浮点数据类型 ② 解决方法 a. 在协处理器指令空间定义浮点指令,通过未定义指令异常来进行软件模拟;部分浮点运算也可由浮点运算协处理器FPA10以硬件方式完成。 b. ARM公司提供了以C语音编写的浮点库作为ARM浮点指令集的替代方法。这种方法与软件仿真相比即快又紧凑,因为他避免了中断、译码和浮点指令仿真。 1.1.3 存储器大小端 ARM同时支持大端模式(Big-endian)和小端模式(Little-endian),默认使用小端模式。 特别注意1:大小端模式问题只存在于多字节整型数据中 特别注意2:数据和代码在存储器中的存储格式必须和处理器采用的端格式一致 补充:上图中给出的是ARM v6之后的大小端模式,在ARM v4/5体系结构中,str 指令存储到内存中的多字节整型均采用小端模式,在ldr取出时才根据配置转换为大端或小端模式。使用CPSR的E位 + CP15_c1可以控制load/store endian,具体设置方式可参考《ARM Architecture Reference Manual》A2.7 Endian support(P72) 1.2 支持的指令集 ① ARM指令集(32 bit) 效率高,但代码密度低 ② Thumb指令集(16 bit) 代码密度高,但某些操作(e.g. 异常处理)必须切换到ARM模式运行。所以代码需要适时切换指令集。 ARM & Thumb模式切换是有开销的,而且二者的编译方式也不一样,这就增加了软件开发管理的负担。 ③ Thumb2指令集(16 & 32big) 随ARM v7架构推出,在Thumb中加入部分32 bit指令,首次实现16 bit & 32 bit指令并存,避免了指令集的切换。目前主要应用在Cortex-M系列处理器中(e.g. Cortex-M3就只支持Thumb2指令集)。 当然,使用Thumb2指令集也意味着不向后兼容。 ④ Java bytecode Jazalle cores支持Java字节码 2. Cortex-A8编程模型 2.1 处理器工作模式
说明1:CPU为什么要设计多种工作模式? ① CPU是硬件,OS是软件。软件的设计要依赖硬件的特性,硬件的设计要考虑软件的需求,以便于实现软件特性。 ② 操作系统有安全级别要求,因此CPU设计多种模式是为了方便操作系统的多种安全等级需要。 说明2:除用户模式外的其他7 种处理器模式称为特权模式(Privilege Modes),在特权模式下程序可以访问所有系统资源,也可以任意地进行处理器模式切换。 说明3:FIQ、IRQ、Supervisor、Abort、Undefined 五种模式又被称为异常模式。 说明4:处理器模式可以通过软件控制进行切换,也可以通过外部中断或异常导致切换。 说明5:对user模式的限制 ① 只能通过产生异常(SWI异常)切换到其他模式(此处指主动要求切换模式) ② memory system和协处理器可以限制user mode对memory和协处理器的访问 不同模式的关键:操作权限与访问资源的不同!!! 2.2 寄存器组织 说明1:System模式使用和User模式相同的寄存器集,但System是特权模式 说明2:Cortex-A8处理器共有40个32位寄存器,其中 ① 32个通用寄存器 ② 7个状态寄存器,其中 1个CPSR(Current Program Status Register,当前程序状态寄存器) 6个SPSR(Saved Program Status Register,备份程序状态寄存器)。当特定异常/中断发生时,对应模式的SPSR负责存放CPSR的内容;当异常处理程序返回时,再将其内容恢复到CPSR中。 ③ 1个PC(Program Counter,程序计数器) 说明3:r13和r14的通常用法 r13:用作栈指针SP(Stack Pointer),指向不同模式的栈区。异常处理程序负责初始化自己的r13,使其指向该异常模式专用的栈区。在异常处理程序的入口会将用到的其他寄存器的值保存在栈区,返回时重新将这些值加载到寄存器中。通过这种保护程序现场的方法,通常不会破坏被中断的程序现场。 future point:根据《ARM architecture reference manual》A2.4 General-purpose registers,ARM v6之后推荐新的sp使用方法: 并非初始化所有banked sp register,而是预先规划好使用的栈,然后调用SRS指令使用栈(即可以规定不同的exception使用指定的栈) r14:用作链接寄存器LR(Link Register),该寄存器在ARM体系结构中有下面两种特殊用途: ① 每一种处理器模式用自己的r14存放当前子程序的返回地址。当通过BL或BLX指令调用子程序时,r14被设置成该子程序的返回地址。从子程序返回时,一般有如下两种场景: a. 仅返回子程序调用点(BX可附带切换指令集) MOV PC, LR --------------- BX LR b. 在子程序入口使用下面的指令将LR保存到栈中 STMFD SP!, { 在程序返回时使用相应的指令返回 LDMFD SP!, { ② 当异常/中断发生时,该异常模式的r14 被设置成该异常模式的返回地址。 特别注意:某些模式的r14 值可能与返回地址有一个常数的偏移量(这点将在中断处理部分说明)。 个人:产生这个偏移量的根源是异常发生的时机!!! 补充:嵌套中断(nested exception)对LR的影响 ① 当允许嵌套中断时,如果在IRQ handler中开中断,并且正好有中断发生。那么之前LR_irq中保存的中断返回地址会被覆盖 ② 解决方案 进入IRQ handler后切换到另一个模式(手册推荐System mode),然后再开中断 说明4:程序状态寄存器详解 A. 条件标志位 N(Negative)、Z(Zero)、C(Carry)、V(overFlow)为条件标志位,这些标志位会根据程序中的算术指令或逻辑指令的执行结果进行修改,而且这些标志位可作为指令条件执行的依据。 ① N位:设置为当前指令运行结果的bit[31]的值。当有符号数补码运算时,N=1 表示结果为负数,N=0 表示结果为正数或零。 ② Z位:Z=1 表示运算结果为0,Z=1 表示运算结果不为零。 ③ C位:设置方法有如下四种 a. 在加法指令中(包括比较指令CMN),当结果产生了进位,则C = 1,表示无符号数运算发生上溢出;其他情况C = 0。 b. 在减法指令中(包括比较指令CMP),当运算中发生借位,即无符号数运算发生下溢出,则C = 0;其他情况C = 1。 c. 对于在操作数中包括移位操作的运算指令(非加/减指令),C被设置成被移位寄存器最后移出去的位。 d. 其他非加/减运算指令,C的值通常不受影响。 ④V位:设置方法有如下两种 a. 对于加/减运算指令,当操作数和运算结果都是以二进制补码表示的带符号数,且运算结果超出了有符号数运算的范围时发生溢出。V=1 表示有符号数运算溢出。 b. 对于非加/减运算指令,通常不改变V 的值。 B. 控制位 ① 中断禁止位 I=1,IRQ被禁止 F=1,FIQ被禁止 ② 处理器状态控制位 T=0,处理器处于ARM状态(执行32位ARM指令) T=1,处理器处于Thumb状态(执行16位Thumb指令) 注1:T位仅在T系列ARM处理器上才有效,在非T系列中,T始终被置为0 注2:不能通过直接修改CPSR的T位来改变处理器的状态,因为直接修改CPSR的T位的结果不可预知,必须通过BX、BLX指令来修改。 ③模式控制位 3. GNU ARM汇编语法格式 GNU ARM汇编程序中,每行的语法格式如下: [ 说明1:如果语句太长,可以将一条语句分几行来书写,在行末用 表示换行(即下一行与本行为同一句), 后不能有任何字符,包括空格和制表符 说明2:同一行中,ARM指令、伪指令、伪操作、寄存器名称等要么大写、要么小写,不可以大小写混合 各字段详解如下: lable:为标号,可选。 ① 可以使用字母、数字、下划线,除了局部标号外,必须以字母或下划线开头。 ② 标号必须以:(冒号)结尾 ③ GNU ARM中对标号的大小写敏感 instruction | directive | pseudo-instruction:可选项,为指令、伪指令、伪操作三者之一。 instruction:ARM汇编指令,如mov r0, r1 pseudo-instruction:ARM伪指令,伪指令不是真正的ARM指令,汇编阶段汇编器会将其转化成一条或多条ARM指令,如ldr r0, =label directive:GNU ARM 伪操作,伪操作只在汇编阶段起作用,其不会被转换成ARM指令,只是用来控制汇编、链接器的动作。 @comment:可选项,GNU ARM 汇编语言注释语句,@为注释标识符 4. ARM指令的条件执行 ARM指令32位指令码的高4位为条件域 4位条件域有16种条件码,每个条件码根据CPSR中的条件标志位N、Z、C、V 来条件执行,具体条件码如下图: 说明1:无符号数使用higher/lower/same;有符号数使用greater/less/equal 说明2:用条件执行代替分支跳转可以大大提高程序效率,因为每次跳转都会清空流水线并重新装载指令。 5. ARM指令集概要 5.1 ARM指令集分类 ① 数据处理类指令:完成CPU内部的计算(仅涉及寄存器) ② Load/Store指令:完成CPU与内存/IO外设之间的数据传输 ③ 跳转指令:完成程序的跳转 ④ 程序状态寄存器处理指令:完成CPSR的管理 ⑤ 协处理器指令:完成CPU扩展功能的实现· ⑥ 异常产生指令:用户程序触发异常 说明:ARM汇编的寻址方式根据指令类型不同进行分类,即使是相同的寻址方式其编码方式也会有所不同(e.g. 允许的移位操作/立即数移位值的宽度),具体可查阅《ARM Architecture Reference Manual》A5. ARM Addressing Modes(P455) 5.2 分支跳转指令 ① B/BL/BX/BLX是一种相对跳转(即地址无关操作),以PC寄存器的值作为跳转指令的基地址值。在指令执行过程中,会从跳转的目标地址中减去跳转基地址,生成字节偏移量。 ② B/BL/BX/BLX 的跳转范围为±32MB 解释:在B/BL/BX/BLX 指令编码中有24位有符号数用于存储跳转地址,照理24位只能寻址16MB,但ARM指令为32位定长,按4字节对齐后两位为0,所以24位可以表示26位的范围,也即±32MB ③ BL/BLX 会将下一条指令的地址拷贝到r14寄存器中 小结:地址无关跳转更灵活,但跳转范围有限制;地址相关跳转可实现4GB跳转,但要求运行地址和链接地址一致。 补充:对于non-leaf 函数(非叶子函数),LR必须压栈保存 5.3 数据处理指令 ① 基本语法格式和寻址方式 关键是第二操作数(shifter_operand)的多种寻址方式 关于立即数的说明:每个立即数由一个8位的常数循环右移偶数位得到,其中循环右移的位数由4 位二进制数的两倍表示(即2、4、6 ... 30)。 ② MOVS/MVNS 如何影响CPSR? a. 如果指令中的目标寄存器 b. 如果指令中的目标寄存器 指令MOVS PC, LR 可以实现从某些异常/中断中返回。 注:其余数据操作指令(ADD、ADC等等)的S位均涉及上述用法(但比较和测试指令默认影响CPSR中的标志位),关键就是当目标寄存器 5.4 加载存储指令 5.4.1 3 种Load/Store指令 ① 单寄存器Load/Store指令(Single Register) 在ARM寄存器和存储器之间提供灵活的单数据项传送,数据项可以是字节、16位半字或32位字 ② 多寄存器Load/Store内存访问指令 这些指令的灵活性比单寄存器传送指令差(只能传递32位字),但可以使大量的数据有效传递。一般用于进程的进入和退出、保存和恢复工作寄存器以及拷贝存储器中的一块数据。 ③ 单寄存器交换指令(Single Register Swap) 这些指令允许寄存器和存储器中的数值进行交换,在一条指令中完成Load/Store操作,一般用于实现信号量(Semaphores)。 5.4.2 LDR Rd, lable label 为程序标号,lable必须在当前指令±4KB范围内 注意和伪指令 LDR Rd, =label 区别开来!!! 特别说明:ldr 指令、ldr 伪指令及adr 伪指令辨析 代码如下: 反汇编内容如下: 首先要明确的是,标号在汇编中表示一个地址(是一个32位无符号常数),所以标号也称为符号地址。特注特注!!! 标号表示的就是链接地址!!! ① ldr r0, _start:向r0中装载的是_start标号表达的地址中的内容,因为ldr 指令本质上用于将存储器中的值加载到寄存器中。 ②adr r0, _start:adr伪指令将标签所表示的地址加载到寄存器中,执行时将基于PC相对偏移的地址值读取到寄存器中。因为是基于PC的,所以ADR读取到的地址值为位置无关地址。 ③ldr r0, =_start:是伪指令,通过文本池向r0中装载的是_start表示的地址值,需要特别说明的是,此处装载的是链接地址(即0x2000800c)。这也说明对于这种地址相关操作,在哪里链接就要在哪里执行,否则会出错。比如即使将这部分代码加载到内存0x20000000处执行,ldr r0, =_start向r0中装载的仍为0x2000800c。 补充:经我在Keil上仿真实验,上述结论是正确滴~~~ 5.4.3 有符号的字节/半字数据传送指令仅适用于Load操作 有符号的字节/半字数据传送指令仅适用于Load操作,即只有LDRSB和LDRSH。因为只有读入字节或半字到寄存器时涉及零扩展还是符号扩展(因为寄存器都是32位),而写入内存时不存在这一问题。 5.4.4 单寄存器Load/Store寻址方式 说明:此处的移位值只能是立即数形式,这也就是我前面说的,即使是相同的shift operand产生类型,编码方式也可能不同。 5.4.5 多寄存器内存字数据传送指令(LDM/STM) ① 多寄存器传输时只能传输字,而不能是字节或半字 ② 传输数据的对应关系:编号低的寄存器对应于内存中的低地址单元,编号高的寄存器对应于内存中的高地址单元。 ③ ldmfd sp!, {r0-r7, pc}^ 若LDM指令在寄存器列表中包含PC且使用^ 后缀,那么除了正常的多寄存器传送外,还可将SPSR复制到CPSR,从而实现从异常处理中返回。 ^ 后缀不允许在用户模式和系统下使用,因为这两个模式没有SPSR寄存器。 补充:如果使用^ 后缀但寄存器列表中不包含PC,则表示加载/存储的是用户模式寄存器,而不是当前模式寄存器。(还没见过实例~~) ④ 注意多寄存器数据传送指令中寻址方式的配套使用(块数据传输、堆栈操作) 在操作堆栈时要尽量使用配对的堆栈操作地址模式,这样只要使用相同的栈类型即可。 5.4.6 交换指令(SWP/SWPB) 交换指令(SWP/SWPB)是Load/Store指令的一种特殊形式,该指令将一个存储器单元内容与指定的寄存器内容相交换。交换指令为进程间同步提供了一种方便的解决途径,该指令生产一对原子Load/Store操作,该操作发生在一个连续的总线操作中,在操作期间阻止其他任何指令对该存储单元的读写。 future point:ARM v7版本中不推荐使用swap指令实现信号量,而是推荐使用互斥的LDR/STR指令(load and store register exclusive),即LDREX/STREX指令。这2条指令在操作过程中不会锁住所有系统资源。 下面给出一段使用swap指令实现互斥的范例 EXPORT lock_mutex_swp lock_mutex_swp PROC ldr r2, =locked swap r1, r2, [r0] // swap r2 with location [r0], [r0] value placed in r1 cmp r1, r2 // check if memory value is 'locked' beq lock_mutex_swp // if so, retry immmediately bx lr // if not, lock successfully, return ENDP EXPORT unlock_mutex_swp unlock_mutex_swp PROC ldr r1, =unlocked str r1, [r0] // write value 'unlocked' to location [r0] bx lr ENDP 5.5 程序状态寄存器访问指令 5.5.1 状态寄存器的修改原则 ① 不修改和使用状态寄存器中未定义的位,因为后续体系结构的升级可能会使用这些位 ② 通常要遵循 读取---> 修改---> 写回 的原则,这样可以保证不影响其他未修改的位 5.5.2 MRS的使用场景 ① 当需要保存或修改当前模式下CPSR或SPSR的内容时,首先必须将这些内容传递到通用寄存器中,对选择的位进行修改,然后将数据写回到状态寄存器。 ② 当异常中断允许嵌套时,需要在进入异常处理程序之后,嵌套中断发生之前保存当前处理器模式的SPSR。这时需要先通过MRS指令读出SPSR的值,再用其他指令(如压栈指令)将SPSR的值保存起来。 ③ 在进程切换时也需要保存当前程序状态寄存器的值。 5.5.3 MSR指令总结 ① 只有在特权模式下才能修改状态寄存器 ② 语法格式: 说明1:可以将通用寄存器或立即数(此处立即数为8位,范围从0x00到0xff)传送到程序状态寄存器 说明2: C(控制):bit[0] ~ bit[7] X(扩展):bit[8] ~ bit[15] S(状态):bit[16] ~ bit[23] F(标志):bit[24] ~ bit[31] 5.6 异常产生指令 5.6.1 SWI指令功能 SWI 指令用于产生软中断,实现从用户模式切换到管理模式,CPSR保存到管理模式的SPSR,执行转移到SWI异常向量;在其他模式下使用SWI指令,处理器同样切换到管理模式。 5.6.2 SWI指令语法格式 ARM处理器对指令中的24位立即数不进行处理,其作用是提供给操作系统,从而判断用户程序请求的服务类型。 5.6.3 SWI指令参数传递方式 ① 指令中24位立即数指定了用户请求的类型,中断服务程序的参数通过寄存器传递 MOV R0,#34 @设置功能号为34 SWI 12 @产生软中断,中断号为12 ② 指令中的24位立即数被忽略,用户请求的服务类型由寄存器r0的值决定,参数通过其他寄存器传递 MOV R0,#12 @设置12号软中断 MOV R1,#34 @设置子功能号为34 SWI 0 5.6.4 SWI Handler ① 确定引起软中断的SWI 指令是ARM指令还是Thumb指令,这可以通过对SPSR的访问得到 ② 确定该SWI指令的地址,这可以通过访问LR寄存器得到 ③ 读出指令,分解立即数 5.7 协处理器指令 5.7.1 ARM协处理器概述 ① ARM协处理器具有自己专门的寄存器组,他们的状态由控制ARM状态指令的镜像指令来控制。 ② 程序的控制流指令由ARM处理器来处理,所有协处理器指令只能同数据处理和数据传送有关。按照RISC的Load/Store体系原则,数据的处理和传送指令是被严格分开的,因此他们有不同的指令格式。 ③ ARM处理器支持最多16个协处理器,在程序执行过程中,每个协处理器忽略ARM和其他协处理器的指令。当一个协处理器硬件不能执行属于他的协处理器指令时,将产生一个未定义指令异常中断,在该异常中断处理过程中,可以通过软件仿真该硬件操作。假设一个系统中不包含向量浮点运算器,则可以选择浮点运算软件包来支持向量浮点运算。 5.7.2 ARM协处理器指令分类 ① 协处理器数据操作指令 说明:协处理器数据操作完全在协处理器内部操作,他完成协处理器寄存器的状态改变。如浮点运算,在浮点协处理器中将两个寄存器相加,结果放在第三个寄存器中。 示例:CDP ② 协处理器数据传送指令 说明:这类指令可实现从存储器读取数据装入协处理器寄存器,或将协处理器寄存器的数据装入存储器。因为协处理器可以支持自己的数据类型,所以每个寄存器传送的字数与协处理器有关。因此存储器地址由ARM处理器产生,但传送的字节由协处理器控制。 示例:LDC、STC ③协处理器寄存器传送指令(最常用) 说明:这类指令可实现ARM处理器的寄存器与协处理器的寄存器之间的数据交换 示例:MCR、MRC 参考资料: https://blog.csdn.net/tabactivity/article/details/90476151 5.7.3 MCR/MRC指令格式 MCR/MRC{ 说明:具体的使用实例可参考对应的ARM核手册 6. ARM汇编伪指令 6.1 关于伪指令 ① 伪指令是为汇编器服务的,不同的汇编器有不同的伪指令 ② 伪指令分类 a. GNU 汇编器支持的ARM 伪指令 b. GNU 汇编器支持的平台无关伪指令(也叫伪操作) 6.2 GNU汇编器支持的ARM伪指令 6.2.1 概述 ARM伪指令在汇编阶段会被编译成ARM或者Thumb 指令(或指令序列) 6.2.2 ADR 伪指令 语法:ADR 功能:ADR 为小范围地址读取伪指令,ADR伪指令将基于PC 的相对偏移地址读取到寄存器中。当地址值字节对齐时,取值范围为-255~255;当地址值字对齐时,取值范围为-1020~1020;当地址值16字节对齐(即双字对齐)时,取值范围更大。 因为ADR伪指令中的地址是基于PC的,所以ADR读取到的地址为位置无关地址(取到的地址是基于运行地址的)。当ADR伪指令中的地址基于PC时,该地址与ADR伪指令必须在同一代码段中。 使用说明:ADR被汇编器汇编为一条指令,汇编器通常使用ADD 或SUB 指令来实现该伪指令的地址装在功能;如果不能用一条指令来实现ADR 伪指令的功能,汇编器将报告错误终止汇编。 示例: start:MOV R0,#10 ADR R4,start @本ADR伪指令将被汇编为SUB R4,PC,#0xc 6.2.3 ADRL 伪指令 语法:ADRL 功能:ADRL为中等范围地址读取伪指令,ADRL也是将基于PC的相对偏移地址读到寄存器中。他比ADR伪指令读取的范围更大,当地址值字节对齐时,取值范围为-64KB~64KB;当地址值字对齐时,取值范围为-256KB~256KB;当地址值双字对齐时,取值范围更大。 使用说明:在实现上,ADRL被汇编器汇编为两条指令,即使一条指令可以完成该操作,汇编器也将产生两条指令,其中一条为多余指令。如果汇编器不能再两条指令内完成操作,将报告错误终止汇编。 6.2.4 LDR 伪指令 语法:LDR register, =expr @expr为32位常量表达式 功能:LDR伪指令用于装载一个32位常数或一个地址到寄存器,使用LDR伪指令装载地址是一种位置相关操作(取到的地址是基于链接地址的)。 使用说明:汇编器根据expr的取值情况做如下处理: ① 当expr 表示的地址值没有超过MOV或MVN指令的地址取值范围时,汇编器用一条MOV和MVN指令代替LDR伪指令 ② 当expr 表示的地址值超过MOV或MVN指令的地址取值范围时,汇编器将常数放入数据缓存池,同时用一条基于PC的LDR装载指令读取该常数。 特别注意:缓存池所在地址与LDR伪指令处的PC值之间的偏移量是有限制的,ARM指令中为±4KB,Thumb指令中为0~1KB。(这些都是汇编器要处理的问题) 6.2.5 NOP伪指令 功能:NOP伪指令执行一条空操作,多用于延时。 使用说明:该指令一般被替换为MOV R0,R0 6.3 GNU汇编器支持的平台无关伪指令 6.3.1 简介 ① GNU 汇编器支持的平台无关伪指令没有对应的机器码,他是用于告诉汇编程序如何进行汇编的指令。他既不控制机器的操作,也不被汇编成机器代码,只能为汇编程序所识别并指导汇编如何进行。 ② 此处的汇编伪指令的名称都以"."开始,余下的是字母,通常是小写字母 6.3.2 符号定义伪指令 ① 全局标号定义伪指令 .global 和.globl(.globl 是为了兼容其他汇编器) 说明:.global 使得符号对链接器(ld)可见,变为整个工程可用的全局变量;由于将符号定义为全局变量,因此在整个工程范围内符号必须唯一。 语法:.global symbol 补充:.global 是定义一个全局标号,如果要声明一个外部符号,使用.extern label ② 局部标号定义伪指令 .local 说明:这个指令表示定义的符号名称作为一个局部的符号,这样他对外部就是不可见的,作用域在定义他的文件内(GNU汇编中标号默认具备局部属性)。 语法:.local symbol ③ 宏替换伪指令 .equ 说明:.equ 类似于C 语言中的宏定义,用于声明一个符号常量 关键:汇编器不为.equ 声明的符号常量分配内存空间,只是在汇编时将其替换(和C语言中不带参数宏定义相同) 语法:.equ symbol, expr 示例:.equ num, 0x40 mov r1, #num @注意此处仍然需要井号,因为num是一个符号常量,本质上仍是常量 补充:.set 与.equ 语法、作用一样 6.3.3 数据定义伪指令 注意:下面定义中的label是为方便程序员引用而设,即使没有也不影响内存单元的分配。(只是如果没有这个label,程序将很难访问分配的内存单元) 说明:数据定义伪指令一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。 伪指令列表: ① label: .byte expr 功能:在存储器中分配一个字节,并用指定的数据对存储单元进行初始化 expr 范围:-128 ~ 255,也可以是字符 ② label: .short expr 功能:在存储器中分配两个个字节,并用指定的数据对存储单元进行初始化 expr 范围:-32768 ~ 65535 ③ label: .word expr @.long 的功能与.word 相同 功能:在存储器中分配四个个字节,并用指定的数据对存储单元进行初始化 expr 范围:-2^31 ~ 2^32 ④ label: .quad expr 功能:在存储器中分配八个个字节,并用指定的数据对存储单元进行初始化 expr 范围:-2^63 ~ 2^64 ⑤ label: .float expr 功能:在存储器中分配四个字节,并用指定的浮点数据对存储单元进行初始化 expr 范围:4字节范围内的浮点数值 ⑥ label: .space size, expr label: .skip size, expr 功能:分配一片连续的存储区域并初始化为指定的值,如果后面的填充值省略则在后面填充为0。该伪指令类似于在C语言中定义数组。 示例:a: .space 8, 0x1 @相当于在C语言中定义char a[8],并将每个成员初始为为1 补充1:.zero size @分配size 个字节的数据空间,并用0 填充内存。 补充2:.fill .fill repeat {,size} {,value} repeat:重复填充的次数 size:每次填充的字节数,省略时默认为1 字节 value:对每次申请空间的填充值,省略时默认填充0 即每次分配repeat * size 个字节 示例:.fill 1024,2,0xffff 辨析:.space/.skip 都是以字节为单位分配内存,并可以初始化;而.fill 功能最强,可以指定每次分配的字节数;.zero 相当于.space/.skip 的简化版本,将申请的字节均初始化为0。 ⑦ 定义字符串伪指令.string、.ascii、.ascize 示例:lable: .string "str" 辨析:.ascii 伪操作定义的字符串需要自行添加结尾字符' |