首页 > 编程语言 >ARM-GUN汇编简介

ARM-GUN汇编简介

时间:2024-03-30 18:55:05浏览次数:21  
标签:标号 汇编器 定义 r3 简介 伪指令 mov GUN ARM

目录

​ 人们利用助记符代替机器指令的操作码,用标号代替指令及操作数的地址,这就形成了汇编语言( Assembly Language)。 它是介于机器语言与高级语言之间的计算机语言,被人们称为第二代计算机语言。

​ 用汇编语言写成的程序不能直接放入计算机内部的存储器中去执行,必须先转为机器语言。把用汇编语言写成的源程序“翻译”成机器语言的工具称为汇编程序或汇编器( Assembler),以下统称作汇编器。

​ 汇编语言源程序可以用通用的文本编辑软件编辑,以文本形式存盘。不同的汇编器中的汇编语言源程序的格式有所区别。同时,汇编器除了识别计算机指令系统外,为了能够正确地产生目标代码以及方便汇编语言的编写,还提供了一些在汇编时使用的命令和操作符号。在编写汇编程序时,也必须正确使用它们。由于汇编器提供的指令仅是对把汇编语言源程序“翻译”成机器码工作的辅助,并不产生运行阶段执行的机器码,因此这些指令被称为伪指令( Pseudo Instruction)。

一、GUN 汇编书写格式

汇编语言源程序以行为单位进行设计,每一行最多可以包含以下 4 部分。

标号: 操作码 操作数 注释

1. 标号(Label)

​ 标号表示地址位置,是可选的。有些指令的前面可能会有标号,通过这个标号可以得到指令的地址,如在跳转语句转移的位置前就应该加标号。标号也可以用于表示数据地址,如在字符串前可以放一个标号来表示该字符串的首地址,这个标号有点类似 C 语言中的数组名。

对于标号有下列要求及说明。

  1. 如果一个语句有标号,则标号必须书写在汇编语句的开头部分;标号后必须带冒号 “:”;标号是区别字母大小写的,但指令不区分字母大小写;一个标号在一个文件(程序)中只能定义一次,否则其会被视为重复定义,不能通过汇编;一行语句只能有一个标号,代表当前指令的存储地址。
  2. 可以组成标号的字符有英文大小写字母、数字 0~9、下划线 “_”、美元符号 “$”,但第一个符号不能为数字或 $。
  3. 标号长度基本上不受限制,但实际使用时最好不要超过 20 个字符。若希望标号能被更多的汇编器识别,建议标号(或变量名)的长度小于 8 个字符。

2. 操作码(Opcodes)

​ 操作码可以是指令和伪指令, 其中伪指令是指 Arm-GUN 汇编器可以识别的伪指令。对于有标号的行,必须用至少一个空格或制表符(即 TAB 键)将标号与操作码隔开。对于没有标号的行,不能从第一列开始写指令码,应以空格或制表符开头。汇编器不区分操作码中字母的大小写

3. 操作数(Operands)

​ 操作数可以是地址、标号或指令码定义的常数,也可以是伪运算符构成的表达式。若一条指令或伪指令有操作数,则操作数与操作码之间必须用空格隔开书写。操作数多于一个时,操作数之间用英文逗号 “,” 分隔。操作数中一般都有一个存放结果的寄存器,这个寄存器位于操作数的最前面。

Arm-GUN 汇编器识别的伪运算符

运算符 功能 类型 实例
+ 加法 二元 mov r3,#30+40 等价于 mov r3,#70
- 减法 二元 mov r3,#40-30 等价于 mov r3,#10
* 乘法 二元 mov r3,#5*4 等价于 mov r3,#20
/ 除法 二元 mov r3,#20/4 等价于 mov r3,#5
% 取模 二元 mov r3,#20%7 等价于 mov r3,#6
|| 逻辑或 二元 `mov r3,#1
&& 逻辑与 二元 mov r3,#1&&0 等价于 mov r3,#0
<< 左移 二元 mov r3,#4<<2 等价于 mov r3,#16
>> 右移 二元 mov r3,#4>>2 等价于 mov r3,#1
^ 按位异或 二元 mov r3,#4^6 等价于 mov r3,#2
& 按位与 二元 mov r3,#4^2 等价于 mov r3,#0
| 按位或 二元 `mov r3,#4
== 等于 二元 mov r3,#1==0 等价于 mov r3,#0
!= 不等于 二元 mov r3,#1!=0 等价于 mov r3,#1
<= 小于等于 二元 mov r3,#1<=0 等价于 mov r3,#0
>= 大于等于 二元 mov r3,#1>=0 等价于 mov r3,#1
+ 正号 一元 mov r3,#+1 等价于 mov r3,#1
- 负号 一元 ldr r3,= -325 等价于 ldr r3,=0xfffffebb
~ 取反运算 一元 ldr r3,=~325 等价于 ldr r3,= 0xfffffeba
> 大于 一元 mov r3,#1>0 等价于 mov r3,#1
< 小于 一元 mov r3,#1<0 等价于 mov r3,#0

关于操作数,有以下几点补充说明。

  1. 圆点 “.” 的用法。若圆点 “.” 单独出现在语句的操作码之后的操作数位置上,则代表当前程序计数器的值被放置在圆点的位置。例如:b . 指令代表转向本身,相当于永久循环,在调试时若希望程序停留在某个地方,则可以添加这种语句,调试之后应删除。
  2. 操作数中常数的进制表示:十进制(默认不需要前缀标识)、十六进制(前缀标识 0x)、二进制(前缀标识 0b)。
  3. 立即数的表示方法:常数前添加 “#” 时表示一个立即数,不加 “#” 时表示一个地址;当立即数大于或等于 256 时, 若使用 LDR 指令, 则立即数前应加 “=”。需要注意的是,初学时常常会将立即数前的 “#” 遗漏,汇编器识别不到这种错误,且只有在只能使用立即数的指令时,汇编器才会提示错误。
mov r3, 1 //给寄存器 r3 赋值为 1(这个语句是错误的)

汇编时会提示 “immediate expression requires a # prefix – ' mov r3,1'”,故其应该改为:

mov r3,#1 //寄存器 r3 赋值为 1(这个语句是正确的)

4. 注释(Comments)

​ 注释即说明文字,是对汇编指令的作用和功能进行解释,有助于对指令的理解,可以采用单行边注释和整行注释,建议使用 “//” 引导。以 “/*” 开始和 “*/” 结束的注释用于保留调试时屏蔽语句行。

二、GUN 汇编常用伪指令

​ 不同集成开发环境下的伪指令不同。 伪指令书写格式与所使用的汇编器有关,读者可参照具体的工程样例“照葫芦画瓢”。

​ 伪指令主要有常量、宏的定义、条件判断、文件包含等,在 Arm-GUN 下,所有的伪指令都是以 “.” 开头的。

1. 系统预定义的段

.data 	//已初始化的数据段
.bss	//未初始化的数据段
.text	//代码段

​ 汇编语言程序在经过汇编和链接之后,最终生成可执行文件。.elf 可执行文件是以段为单位来组织文件的,通常划分为 .text.data.bss 等段。 其中,.text 是只读的代码段,是程序存放的地方,实际代码存储在 flash 区;.data可读可写的数据段,而 .bss 则是可读可写且没有初始化的数据段,启动时会清零,两者都是用来存放变量的,实际数据存储在 RAM 区。这些段分别从哪个地址开始,这在链接文件中会指明。

2. 常量的定义

.equ(或.set) 常量名,表达式

​ 在汇编程序中使用常量定义,能够提高程序代码的可读性,并且可使代码维护更加简单。常量的定义可以使用 .equ.set 伪指令。

下面是 GNU 汇编器的一个常量定义的例子。

.equ _NVIC_ICER,0xE000E180	//定义常量名_NVIC_ICER=0xE000E180
LDR R0,=_NVIC_ICER 			//将常量名_NVIC_ICER的值0xE000E180放R0中
.set ROM_size,128*102 		//定义常量 ROM_size

3. 数据定义

数据定义伪指令

数据类型 长度 举例 备注
.word 字(4 字节) .word 0x12345678 定义多个数据时,数据间用 “,” 隔开
.hword 半字(2 字节) .hword 0x1234 定义多个数据时,数据间用 “,” 隔开
.byte 字节(1 字节) .byte 0x12 定义多个数据时,数据间用 “,” 隔开
.ascii 字符串 .ascii “hello\n\0” 定义的字符串不以 “\0” 结尾,要自行添加 “\0”
.asciz.string 字符串 .asciz “hello\n” 定义的字符串以 “\0” 结尾

在定义一个数据类型之前,一般会给一个标号(相当于 C 语言中的变量名或数组名),该标号表示这个数据的起始地址,然后利用这个标号通过直接寻址方式就可以访问到这个数据,具体用法如下。

LDR R3,=NUMNER 			//得到 NUMNER 的存储地址
LDR R4,[R3] 			//将 0x123456789 读到 R4 中
	……
	LDR R0,=HELLO_TEXT 	//得到 HELLO_TEXT 的起始地址
	BL PrintText 		//调用 PrintText 函数以显示字符串
	……
	ALIGN 4
NUMNER:
	.word 0x123456789
HELLO_TEXT:
	.asciz "hello\n" 	//以'\0'结束的字符

4. 条件伪指令

.ifdef 表达式 	  //当表达式为真时,执行代码 1
	代码 1
.else 			//否则,表示表达式为假,执行代码 2
	代码 2
.endif

.if 条件伪指令后面紧跟着一个恒定的表达式(即该表达式的值为真),并且最后要以 .endif 结尾。中间如果有其他条件,可以用 .else 填写汇编语句。

5. 文件包含伪指令

.include "filename"

​ 其中,filename 是一个文件名(以 .s 或 .inc 为扩展名),可以包含文件的绝对路径或相对路径,建议同一工程的相关文件统一放到同一个文件夹中,更多的时候使用相对路径。

​ 类似高级语言中的文件包含一样,在汇编语言中也可以使用 “.include” 进行文件包含。 .include 是一个附加文件的链接指示命令,利用它可以把另一个源文件插入当前的源文件一起汇编,成为一个完整的源程序。

6. 其他常用伪指令

除了上述的伪指令外,GNU 汇编还有其他常用的伪指令。

  1. .section 伪指令:用户可以通过 .section 伪指令来自定义一个段

    • 格式:.section <段名>{,"<标志>"}

    其中,标志可选 a(允许段)、 w(可写段)和 x(执行段)。

    .section .isr_vector,"a" 	//定义一个.isr_vector 段,"a"表示允许段
    
  2. .global 伪指令:可以用来定义一个全局符号

    • 格式:.global symbol
    .global main 	//定义一个全局符号main
    
  3. .extern 伪指令:声明一个外部函数,调用的时候可以遍访所有文件以找到该函数,并且使用它。

    • 格式:.extern symbol
    .extern main 	//声明 main 为外部函数
    bl main 		//调用 main 函数
    
  4. .align 伪指令:可以通过添加填充字节,使当前位置满足一定的对齐方式

    • 格式:.align [exp[,fill]]

    其中,exp 的取值必须是 2 的幂指数,20~231 都是合法的, 表示下一条指令或数据对齐至 exp 个字节地址。若未指定,则将当前位置对齐到下一个字的位置,fill 指出为对齐而填充的字节值,其可省略,默认为 0x00。

    .align 2 	//确保下一条指令或数据对齐到2字节地址
    
  5. .end 伪指令:声明汇编文件的结束

标签:标号,汇编器,定义,r3,简介,伪指令,mov,GUN,ARM
From: https://www.cnblogs.com/YZXE/p/18105872

相关文章

  • 【Clang+LLVM+honggfuzz学习】(一)LLVM简介、安装和第一个Hello Pass
    本文结构,PS:根据需要选择观看哦1.前言参考2.简介传统编译器架构LLVM架构3.LLVM安装版本准备官网源码下载git下载安装过程4.写一个LLVMPass旧HelloPass实现(legacyPMversion)新HelloPass实现(UsingtheNewPassManager)1.前言漏洞检测做毕设,还有一年。半......
  • 鸿蒙HarmonyOS实战-ArkUI组件(Grid/GridItem)
    ......
  • 多视图三维重建-SFM简介
    背景掌握传统的多视图三维重建基本流程总体流程多视图三维重建的Pipieline如下图,总共分为四个步骤:拍摄场景多视角的图像建立这些图像之间的联系(DataAssociation)SFM稀疏重建MVS稠密重建DataAssociation建立图像之间的联系主要包含以下4个步骤:1)特征提取;2)特征匹配;3)基......
  • Visual Studio Code & Python教程1简介
    1简介VisualStudioCode是一款开源代码编辑器,可免费使用,完全支持Python编程语言的开发。它具有一些有用的功能,例如与世界各地的其他程序员进行实时协作。本章旨在介绍VSCode,帮助您了解其开发过程及其不同组件。我们将讨论为什么它可能是最受欢迎的代码编辑器,了解它的功能,并讨......
  • 桌面/WEB端3D开发工具HOOPS SDK简介
    TechSoft3D在长达25年的时间内,一直通过卓越的3D技术帮助全球超过600家客户推动创新,这些客户包括HEXAGON、SolidWorks、SIEMENS、Aras、ANSYS、AVEVA等各个行业的领军者。TechSoft3D旗下拥有4款原生产品,分别是:HOOPSExchange、HOOPSCommunicator、HOOPSVisualize以及......
  • 八臂迷宫实验(Eight-arm Maze Test,RMT)——KT-0854
    八臂迷宫实验是一种常用的行为学测试方法,用于评估动物的空间学习和记忆能力。该实验装置由八个相同的臂组成,这些臂从中心点平台放射出来,形成一个放射迷宫结构。动物在迷宫内接受训练,通过食物的驱使来探究各臂,进而记住食物在迷宫中的空间位置。这种方法不仅可以评估动物的工作记......
  • ARM 指令 LDR、STR等详解
    前言    本期和大家主要分享的ARM汇编指令集中的内存操作类指令,涉及到内存操作,不得不说CPSR,SP,LR,PC是非常重要的几个寄存器,所以接下来就来具体观察一下其内存窗口的具体变化!一、跳转指令1.1相对跳转相对跳转:bfun基于当前pc前后32M范围寻找标号,跳转到标号处执行代......
  • ARM 寄存器——CPSR/SPSR介绍
    CPSR简介:全称:程序状态寄存器(currentprogramstatusregister)用户级编程时用于存储条件码任何处理器模式下被访问两种运行状态:ARM状态(32位)、Thumb状态(16位),两种状态之间可任意切换七种运行模式:usr(用户)、fiq(快速中断)、irq(外部中断)、svc(管理)、sys(系统)、abt(数据访问中止)、und(......
  • systemd简介(一)
    文章目录写在前面systemd是什么?Systemd提供:官方网站介绍:目前使用systemd的Linux发行版有哪些?linux开机流程(系统初始化)是什么,systemd在其中的作用是什么systemd架构图systemd的一些特点systemd的发展史,起源,以及为什么有这个?起源:存在原因:发展历程:systemd在现在有什么问题......
  • 【Linux系列-1】-- 必会的 ARM 汇编指令
    原创:lvy嵌入式学习规划学习Linux系统启动流程,必须熟悉几个汇编指令这里不是最全的,只列出一些最常用的汇编指令。一.数据处理指令1.数据传送指令【MOV指令】把一个寄存器的值(立即数)赋给另一个寄存器,或者将一个常量赋给寄存器。MOV指令的格式为:MOV目的寄存器,源操作数M......