Allbet欧博官网

九江英才网:GNU ARM 汇编基础

admin 2020年03月25日 科技 129 0

ARM GNU汇编基础

0 前言

全文弥补提醒:

笔者在阅读ARM官方文档及查阅现实的u-boot源码中的汇编代码后,发现了一些差别于ARM官方文档中的汇编语法,查阅相关资料后,才发现主要由于汇编器的差别,有两种差别的汇编语法:

  • ARM尺度汇编

    • 汇编程序:arma ***
  • GNU ARM汇编

    • 汇编程序:as

两者在语法上主要的区别在于伪操作的差别,其他相关的指令基本上是一致的,以是这一区别并不会对我们下文的学习造成太大的影响,为了利便,笔者通篇的示例均以GNU ARM汇编语法为尺度,使用的汇编程序为arm-linux-gnueabihf-as.读者如需学习ARM尺度汇编相关知识,需自行参考ARM官方文档 ARM Software Development Toolkit User Guide

第二次弥补提醒:

全文没有过多的去关注和先容所有的ARM指令,更多的关注点均在基础语法和相关知识

全文内容大部门参考ARM官方文档 ARM Software Development Toolkit User Guide第五章以及GNU文档Using as,主要先容了编写ARM和Thumb汇编程序的通用准则。主要包含了以下章节:

  • ARM架构概述
  • 汇编语言的模块结构
  • 数据处理指令
  • 内存接见指令
  • 条件执行
  • 宏的使用

​ 在更先之前,希望读者能够搭建好响应的开发环境(编译工具链和运行环境),在此,笔者使用的是arm-linux-gnueabihf-交织编译工具链,为了能够运行ARM程序,笔者使用的是QEMU,相关工具的下载和安装在此不再详述。

​ 由于计算机最终只能识别机械码,也就是二进制序列,以是汇编语言同其他语言一样,需要响应的工具将其转换成机械语言,这就需要前面提的编译工具链,由于笔者的平台是X86架构,而编写的是ARM架构上的程序,因此需要一个能够执行ARM指令的装备,在这里笔者使用的即前文提及的QEMU工具,由于笔者编译的平台是X86架构,而目的机械是ARM架构,以是需要的是交织编译工具链,不清楚这一知识的读者可自行弥补交织编译相关知识。

​ 当你有一个写好的汇编代码文件( .s 后缀)后,你需要使用as工具举行汇编,天生机械语言,再使用ld工具举行链接

$ arm-linux-gnueabihf-as sum10.s -o sum10.o -g
$ arm-linux-gnueabihf-ld sum10.o -o sum10
/*
	-g:带有debug信息
	-o:指定输出文件名
*/

Note:

​ c语言编译历程中,中途会先举行编译天生汇编代码,然后再举行汇编和链接,最终天生可执行文件

1 ARM架构概述

本章主要简朴先容下后文中所需要的一些ARM架构相关知识,读者如遇见不清楚的地方,可自行去阅读ARM Architectural Reference Manual

ARM是一个典型的RISC(精简指令集)处理器,只有加载和存储指令可以接见内存,数据操作相关指令只能操作寄存器。这也就意味着程序更新一次内存中数据,至少需要三步:

  • 从内存中将数据读取到寄存器中
  • 对寄存器中的数据举行更新
  • 将更新后的数据放回内存中

1.1 ARM 架构版本

ARM family ARM架构版本
ARM7 ARM v4
ARM9 ARM v5
ARM11 ARM v6
Cortex-A ARM v7-A
Cortex-R ARM v7-R
Cortex-M ARM v7-M

1.2 ARM & Thumb state

在ARM v4T和v4TxM架构中,界说了一种长度为16bits的指令集,并称之为Thumb指令集,这一指令集是ARM指令集的一个子集。这一指令集同ARM指令集主要有以下区别:

  • 在寄存器的接见上受一定的限制
  • 只能通过分支指令实现条件执行
  • 不允许接见桶式移位器(barrel shifter)

ARM处理器执行ARM指令时被称为处于ARM状态,执行Thumb指令时,被称为Thumb状态。

Note:后面会详细急先容以上三点区别,读者不清楚,不用着急

ARM处理器最更先总是处于ARM状态,可通过BX指令转换至Thumb状态。

1.3 地址空间

在ARM v3架构之后,所有的的处理器均有32bit的寻址局限

1.4 处理器模式

ARM拥有以下7种基本操作模式:

  • User
  • FIQ
  • IRQ
  • Supervisor(svc)
  • Abort
  • Undefined
  • System

以上其中模式中,大部门的程序都运行与User模式下,其他的六种均为特权模式

1.5 寄存器

ARM处理器一共提供了37个寄存器。寄存器排布在部门重叠的存储区域。每种模式下均有差别的寄存器组。

User mode IRQ FIQ Undef Abort SVC
r0-r7
r8 r8
r9 r9
r10 r10
r11 r11
r12 r12
r13 (sp) r13 (sp) r13 (sp) r13 (sp) r13 (sp) r13 (sp)
r14 (lr) r14 (lr) r14 (lr) r14 (lr) r14 (lr) r14 (lr)
r15 (pc)
cpsr
spsr spsr spsr spsr spsr

30个32位通用寄存器,凭据当前处理器的模式,可以随时看到其中的15个寄存器,划分是:r0,r1...r14。

通常情况下,r13会被用作栈指针(stack pointer),r14会被用作链接寄存器(link register),用于存储挪用子程序时存储返回地址。r15是程序计数器,用于存放下一条需要执行的指令的位置,以是可以通过将程序需要跳转的地址放入PC来实现程序跳转。

CPSR寄存器(Current Program Status Register)主要持有了以下信息:

  • ALU的状态标志信息(C/V/N/Z)
  • 当前处理器的模式
  • 中止Disable标志
  • ARM State or Thumb State (若是该处理器支持Thumb)

SPSR寄存器(Saved Program Status Register)用于异常发生时存储CPSR。

CPSR寄存器:

N Z C V J GE E A I F T M
31 30 29 28 24 19-16 9 8 7 6 5 4-0

M:处理器模式

T:ARM || Thumb 状态

N:负数标志

Z:效果为0

C:进位标志

V:溢出标志

1.6 ARM指令集概述

所有的ARM指令长度均为32bits。由于指令在内存中按字对齐存储,故地址更低2个bits应该为0。因此除了分支交流BX指令外,所有具有地址操作数的ARM指令都将忽略这两个bit,而BX正是通过这个bit来确定进入Thumb状态照样ARM状态。

ARM指令可大致分为以下积累几类:

  • 分支指令
  • 数据处理指令
  • 状态寄存器接见指令
  • 单一寄存器加载/存储指令
  • 多寄存器加载/存储指令
  • 信号量指令
  • 协处理器指令

指令功效:

  • 条件执行
  • 寄存器接见
  • 接见桶式移位器

1.7 Thumb指令集概述

所有的Thumb指令长度为16bits,且存储为半字对齐,故地址更低bit应该为0。因此除了分支交流BX指令外,所有具有地址操作数的指令都将忽略这个bit,而BX正是通过这个bit来确定进入Thumb状态照样ARM状态。

下面是Thumb指令与ARM指令的差别之处:

  • 分支指令

    • 相对于ARM指令,在局限上拥有更多的限制,而且仅支持无条件跳转
  • 数据处理指令

    • 受一定限制访的问r8-r15
    • 一直会更新CPSR中的CVNZ位(ARM指令需添加S后缀),除了接见r8-r15
  • 状态寄存器接见指令

    • 没有相关的接见指令
  • 单一寄存器加载/存储指令

    • 不能接见r8-r15
  • 多寄存器加载/存储指令

    • 内存到寄存器的接见局限被限制在了r0-r7
    • 此外,PUSH 和 POP可以划分使用r13和r14
  • 信号量指令()

  • 协处理器指令()

Thumb指令的功效

  • 条件执行
    • 只能通过分支指令来实现条件执行
  • 接见寄存器
    • 大部门情况下只能呢个接见r0-r7
    • r8-r15接见受限,但也可以使用,好比作为快速暂且存储
  • 接见桶式移位器
    • 只能通过特定的指令去接见,LSL、LSR、ASR、ROR

2 汇编语言结构

汇编语言在这里指的是允许通过ARM汇编程序剖析和汇编天生目的代码的语言,它们可以是:

  • ARM汇编语言
  • Thumb汇编语言
  • 以上两者的夹杂

2.1 汇编语言源文件的结构

汇编源文件中的的代码行的通常的形式如下:

GNU ARM 汇编花样:

{label:}{instruction | directive | pseudo-instruction} {@comment}

ARM 尺度汇编花样:

{label} {instruction | directive | pseudo-instruction} {;comment}

{标签} {指令|伪操作|伪指令} {注释}

在这里需要注重的是,instruction | directive | pseudo-instruction 前面必须要有空格或者TAB

以上的三个部门均是可选的,也就是你完全可以用空行去支解你的代码,使其更具可读性

  • 巨细写规则

    • 所有的指令助记符可以是大写或者小写,然则不能夹杂
    • Directive必须大写
    • 寄存器符号可以大写或者小写,然则不能夹杂
  • 单行代码长度

    • 为了使代码具有可读性,可允许使用‘\’字符来支解换行
  • label 标签

    • 在汇编语言中,标签是代表地址的一个符号,这个地址将在汇编时代被计算出来
    • 在GNU汇编中,任何一个以冒号末端的标识符都市被认为是一个标签,而纷歧定要在行首
  • 局部标签 local labels

  • 注释

    • ARM 尺度汇编的注释以 ; 更先
    • GNU尺度汇编的注释以@ 更先,同时也可以使用C语言中的 /* */
  • 常量

    • 数字
    • 字符串
      • 字符串常量用双引号“ ”括起来
    • 布尔型
      • {TRUE}
      • {FALSE}
    • 字符
      • 使用单引号‘ ’
  • 布尔型

2.2 ARM汇编的示例

2.2.1 example的汇编和链接

		AREA ARMexample, CODE, READONLE
		ENTRY
start	mov r0, #10
		mov r1, #3
		add r0, r0, r1
stop	mov r0, #0x18
		ldr r1, =0x20026
		swi 0x123456
		end

;ARM 尺度汇编语法,不做详细注释,读者可自行参考相关资料

GNU 汇编语法

.section .text

.global _start
_start:
        MOV r0, #10
        MOV r1, #3
        ADD r0, r0, r1
stop:
        MOV r0, #0x18
        LDR r1, =0x20026
        SWI 0x123456

将该文件保留为gnuAssembly.S,并使用as举行汇编,然后用ld举行链接天生可执行文件

arm-linux-gnueabihf-as -g gnuAsExample.S -o gnuAsExample.o
arm-linux-gnueabihf-ld gnuAsExample.o -o gnuAsExample

说明:

-g: 带有debug信息

-o:指定输出文件名

2.2.2 GDB和QEMU 调试

汇编链接天生gnuAsExample可执行文件之后,我们可以使用qemu-arm仿真工具执行该文件。

/*首先使用qemu-arm 加载并执行该可执行文件*/
qemu-arm -g 1234 gnuAsExample

/*另外开一个shell窗口,使用GDB工具举行联调*/
arm-linux-gnueabihf-gdb ./gnuAsExample

/*进入GDB模式后,执行如下下令*/
(gdb) target remote 127.0.0.1:1234
/*乐成后,可瞥见如下信息*/
(gdb) target remote 127.0.0.1:1234 
Remote debugging using 127.0.0.1:1234
_start () at gnuAsExample.S:5
5		MOV r0, #10

说明:GDB工具毗邻的端口号需和使用qemu-arm中设置的端口号一致,在这里均为1234。详细的GDB下令在此不再详述,读者可自行查阅相关资料

2.2.3 示例详解

.section .text 		@声明text段

.global _start 		@声明全局变量
_start:				@界说_start标签
        MOV r0, #10	@立刻数10赋值给r0
        MOV r1, #3	@将立刻数3赋值给r0
        ADD r0, r0, r1 @将r0寄存器和r1寄存器的值相加,并将效果存放至r0
stop:
        MOV r0, #0x18	@将0x18放入r0
        LDR r1, =0x20026 @将0x20026放入r1
        SWI 0x123456	@执行软中止下令

说明:stop标签后的三条指令是一个退出程序的指令序列,首先是设置r0和r1的值,然后再触发软件中止,这里面会用到者两个寄存器的值,详细这些值的寄义读者可自行查阅相关资料,在此不举行说明,读者在这里也可以完全忽略详细的值,只需要对汇编的写法有个整体上的认知

在GNU ARM汇编中_start标签是默认的程序起始地址,且由于程序是通过加载器来加载的,因此必须将 _start符号声明为全局的,这样加载器才气找到。

2.3 Thumb 汇编示例

.section .text

.global _start

_start:
	.code 32
	adr r2, thumb+1
	/*在前面我们有说到,由于ARM指令按字对齐,而Thumb指令按半字对齐,
	因此有更低的一个bit或两个bit为0,而在这里我们通过加1,使其不为0,
	下一条bx指令正是通过这一位判断是否需要举行ARM到Thumb状态的转换*/
	bx r2

thumb:
	.code 16
	mov r0, #10
	mov r1, #3
	add r0, r0, r1
	bkpt

下面是汇编链接调试历程,共读者参考

窗口 1

log@log:~$ arm-linux-gnueabihf-as -g gnuAsThumbEx.S  -o gnuAsThumbEx.o
log@log:~$ arm-linux-gnueabihf-ld gnuAsThumbEx.o -o gnuAsThumbEx
log@log:~$ qemu-arm -g 1234 gnuAsThumbEx

窗口 2

log@log:~$ arm-linux-gnueabihf-gdb gnuAsThumbEx
GNU gdb (Linaro_GDB-2017.08) 8.0.0.20170823-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=arm-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gnuAsThumbEx...done.
(gdb) target remote 127.0.0.1:1234
Remote debugging using 127.0.0.1:1234
_start () at gnuAsThumbEx.S:7
7		adr r2, thumb+1
(gdb) info registers r2
r2             0x0	0
(gdb) n
8		bx r2
(gdb) info registers r2
r2             0x1005d	65629
(gdb) l
3	.global _start
4	
5	_start:
6		.code 32
7		adr r2, thumb+1
8		bx r2
9	
10	thumb:
11		.code 16
12		mov r0, #10
(gdb) n
thumb () at gnuAsThumbEx.S:12
12		mov r0, #10
(gdb) n
13		mov r1, #3
(gdb) info registers r2
r2             0x1005d	65629
(gdb) info registers r0
r0             0xa	10
(gdb) info registers r1
r1             0xf6fff66b	-150997397
(gdb) n
14		add r0, r0, r1
(gdb) info registers r0 r1
r0             0xa	10
r1             0x3	3
(gdb) n
15		bkpt
(gdb) info registers r0 r1
r0             0xd	13
r1             0x3	3
(gdb) n

3 数据处理指令

ARM指令通常有一个或两个操作数,形如:

助记符{s}{条件} {rd} , 操作数1,操作数2

说明:

  • {s}:指令加了s后缀后,意味着将会更新CPSR中的CVZN标志
  • {条件}:可以决议该指令是否执行
  • {rd}: 通常用于存储效果
  • 操作数1:第一个操作数,可以是寄存器或立刻数
  • 操作数2:第二个操作数,可以是立刻数或者是一个对寄存器举行移位操作

常见的表达式:

  • 1 立刻数

  • rx 寄存器x,r1、r2...

  • rx, asr n 算术右移n位

  • rx,lsl n 逻辑左移n位

  • rx,lsr n 逻辑右移n位

  • rx,ror n 循环右移n位

  • rx,rrx 循环右移1位

3.1 数据传输指令

  • mov:用于两个寄存器之间或者立刻数和寄存器之间通报数据

  • mvn:和mov用法一致,区别在于会将第二个操作数举行按位取反后再举行通报

说明:

在这里稀奇需要说明的是使用mov和mvn在寄存器中和立刻数中通报数据,这里的立刻数是局限是有一定的限制的。

由于ARM指令编码花样长度微32位,抛去条件码、操作码、目的寄存器等,留给立刻数的位数只剩下12位,因此它是没有办法去示意所有的32位的数的,若是按通例操作,它只能示意0x000-0xfff,然则在ARM中,并没有按通例操作去示意这些数据,而是将其中的低8位作为基数,高4位作为右移位数(x2):

例如:0x101代表的是:0x01 循环右移1×2位,酿成:0x40000000

通过这种方式,使得12位的数可以示意对照大的数据,然则它依旧不愿呢个示意所有的数据,因此立刻数是有一定的限制的,在编程时,如使用了非法立刻数,汇编历程中会讲述一个错误。

3.2 算数运算指令

  • add:加法运算
  • sub:减法运算
  • r *** :反减运算
  • adc:带进位的加法
  • *** c:带进位的减法
  • rsc:带进位的反减

3.3 逻辑运算指令

  • and:与
  • orr:或
  • eor:异或
  • bic:位消灭操作

3.4 对照指令

  • cmp:对照巨细
  • cmn:取反运算
  • tst:按位与运算
  • teq:按位异或运算

3.5 乘法指令

mvl、mla、umull、umlal、 *** ull、 *** lal

3.6 CPSR接见指令

用于接见CPSR寄存器

  • mrc:用于读出cpsr和spsr寄存器
  • msr:用于写入cpsr和spsr寄存器

说明:CPSR是程序状态寄存器,只有一个,而SPSR寄存器在五种异常模式下各有一个,用于保留通俗模式下的CPSR寄存器的值

4 内存接见指令

在ARM指令集中,只有特定的加载和存储指令允许接见内存,以是在对一个数据举行操作之前,都必须将该数加载到寄存器当中去,然后举行操作,操作完成后,再更新回内存中。

4.1 单一寄存器加载和存储

  • ldr:可用于加载一个地址中的内容到寄存器中,也可以加载一个32bit长度的常量存储在寄存器中
  • str:主要用与将寄存器中的值写入内存中

ldr是ARM中的一个指令,也同时是一个伪指令,其主要有两种用法:

  1. 加载一个常量到寄存器中

    例如:ldr r1,=42

    在这里,ldr是一个伪指令,汇编程序会凭据需加载常量的差别,而翻译成差别的指令,详细规则是:

    若是该常量能够使用mvn或mov指令举行操作,则直接将该指令翻译成mvn或mov

    若是该常量并不能够直接被mvn或mov指令举行操作,则汇编器首先会在四周的文字池(literal pool)中存放这么一个常量,然后在使用ldr指令举行读取

    literal pool: a portion of memory embedded in the code to hold constant value

    在这里需要注重的是,编程者必须确保在LDR能够接见的局限内存在文字池,若是不存在,在举行汇编的历程中,会讲述一个错误,这时编程者可通过 LTORG 指令放置一个文字池,详细信息见下文

    放置文字池

    通常来说,汇编程序会在每个area的末尾放置一个文字池,然则若是该area过大的话,可能会超出部门LDR指令能够接见的局限。

    在ARM状态,从PC到常量的偏移量不能超过4KB

    在Thumb状态,该偏移量不能超过1KB

    .section .text
    .global _start
    
    _start:
            ldr r0, =3
            ldr r1, =0x55555555
    largeTable:
    .space 4200 
    .end
    
    arm-linux-gnueabihf-as -g gnuAsLiteralPool.S -o gnuAsLiteralPool.o
    gnuAsLiteralPool.S: Assembler messages:
    gnuAsLiteralPool.S:6: 错误: invalid literal constant: pool needs to be closer
    

    如上代码,在用as汇编时,会发生一个error,由于在ldr r1 , =0x55555555语句中,不能直接用mov或mvn加载,只能通过在文字池中存放该常量,然后使用ldr指令举行加载,然而在该示例中,由于后买你有一个4200字节的空间,使得文字池的局限超出了ldr指令可以接见的局限,因此需要我们手动在适合的位置放置一个文字池。如下:

    .section .text
    .global _start
    
    _start:
            ldr r0, =3
            ldr r1, =0x55555555
    .ltorg
    largeTable:
    .space 4200
    .end
    

    在这里我们对汇编天生后的文件举行反汇编,效果如下:

    log@log:~$ arm-linux-gnueabihf-objdump gnuAsLiteralPool.o -S
    
    gnuAsLiteralPool.o:     文件花样 elf32-littlearm
    
    
    Disassembly of section .text:
    
    00000000 <_start>:
    .section .text
    .global _start
    
    _start:
    	ldr r0, =3
           0:	e3a00003 	mov	r0, #3
    	ldr r1, =0x55555555
           4:	e51f1004 	ldr	r1, [pc, #-4]	; 8 <_start+0x8>
           8:	55555555 	.word	0x55555555
    
    0000000c <largeTable>:
    	...
    

    在这里可以瞥见,ldr r0,=3指令被翻译成了mov r0, #3;而ldr r1, =0x55555555,则被翻译成了两条指令,一个是在.word 0x55555555,一个是ldr r1, [pc, #-4] ; 8 <_start+0x8>。

  2. 加载一个地址

    除了上一种用法,ldr更多的功效则是将某个特定地址中的内容加载进寄存器中,主要有以下用法

    ldr r0,[r1] @将地址r1中的字数据加载进r0中
    ldr r0,[r1,r2] @将存储器地址为r1+r2的字数据加载进r0中
    ldr r0,[r1,#8] @将地址为r1+8的字数据加载进r0中
    ldr r0,[r1],r2 @将r1地址中的字数据加载进r0中,并把r1+r2的值赋值给r1
    ldr r0,[r1],#8 @将r1地址中的字数据加载进r0中,并把r1+8的值赋值给r1
    ldr r0,[r1,r2]! @将存储器地址为r1+r2的字数据加载进r0中,同时把r1+r2赋值给r1
    
    ldr r0,label @将label作为地址加载
    ldr r0,=label @将label作为一个常量数举行加载
    

说明

除了上述ldr指令能够加载一个地址,同样也可以使用adr伪指令举行地址加载,这一伪指令是小局限的地址地址加载,主要通过相对于寄存器或当前PC的偏移量举行加载,且偏移量的局限是255字节(若是没有按字对齐)或者1020字节(若是地址按字对齐)

4.2 多寄存器加载和存储

ldm:用于从内存中读取延续的多个字存放进寄存器中

stm:用于将多个寄存器中的值存储到内存中去

ldm r0,{r4-r5} @将r0地址中的两个字内容划分加载到r4,r5
stm r1,{r4-r5} @将r4-r5两个寄存器的值写入r1地址中
后缀说明:
ia:每次传送后地址加4,其中的寄存器从左到右执行
ib:每次传送前地址加4,同上
da:每次传送后地址减4,其中的寄存器从右到左执行
db:每次传动前地址减4,同上
!:用最后的地址更新基地址

5 条件执行

在ARM状态,每个数据操作指令都可以通过添加‘s’后缀,凭据操作效果去设置CPSR的ALU状态标志,也就是CPSR的N、C、V、Z位

在Thumb状态,没有s后缀,由于所有的指令都市自动去设置这一标志,除了通过mov和mvn指令去操作高位寄存器(r8-r15)

注重:在Thumb状态下,只能通过分支指令实现条件执行,以是下述通过添加指令后缀实现条件执行,都是处于ARM状态

5.1 ALU状态标志

CPSR寄存器包含了ALU以下状态标志:

  • N:当操作效果为负数时,被置1
  • Z:当操作效果为0时,被置1
  • C:当操作效果泛起进完位时,被置1
  • V:当操作导致溢出时,被置1

当加减效果大于或即是2的32次方,或者由于一定而导致仅为,则C置1

当加减效果大于或即是2的31次方,或者少于-2的31次方,则发生溢出

不要将s后缀与cmp\cmn\tst\teq一起使用,由于这些指令默认都是会去更新这一标志的。

5.2 执行条件

后缀 标志 意义
eq Z = 1 相等
ne Z = 0 不想等
cs/hs C = 1 unsigned >=
cc/lo C = 0 unsigned <
mi N = 1 负数
pl N = 0 0 或 正数
vs V = 1 溢出
vc V = 0 没有溢出
hi c=1&&z=0 unsigned >
ls c =0&&z=1 unsigned <=
ge n = v signed >=
lt n != v signed <
gt z=0,n=v signed >
le z=1,n!=v signed <=

6 宏的使用

在GNU汇编中的宏界说花样如下:

.macro 宏名 参数列表
宏体
.endm

example:
.macro FUN_ADD a,b
	add \a, \a, \b
.endm

7 GNU ARM汇编常见伪操作

7.1 .section 伪操作

.section 伪操作花样如下:

.section section_name [,"flags" [, %type [, flag_specific_arguments]]]

在汇编中预置的一些段:

.text @代码段

.data@初始化数据段

.bss@未初始化数据段

.sdata

. *** ss

.bss段应该在.text段之前

8 参考链接

ARM汇编基数:https://azeria-labs.com/writing-arm-assembly-part-1/

ARM官方文档:http://infocenter.arm.com/help/index.jsp

,

诚信在线

诚信在线(www.dongfangculture.com )现已开放诚信在线手机版下载。游戏公平、公开、公正,用实力赢取信誉。

发布评论

分享到:

usdt交易平台(www.caibao.it):关注黄金赛道,投资国民大康健,郑磊新基延续热销中
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。