学 Linux 必会的 ARM 汇编指令

2023-12-17

学习 Linux 系统启动流程,必须熟悉几个汇编指令,总结给大家。

这里不是最全的,只列出一些最常用的汇编指令。

一.数据处理指令

1.数据传送指令

【MOV指令】

把一个寄存器的值(立即数)赋给另一个寄存器,或者将一个常量赋给寄存器。

MOV指令的格式为:

MOV 目的寄存器,源操作数
MOV R1,R0   ;将寄存器R0的值传送到寄存器R1

2.算术运算指令

(1)【加法指令】:ADD

ADD 目的寄存器,操作数1,操作数2

ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。

ADD  R0,R1,R2   ;R0 = R1 + R2
ADD  R0,R1,#256   ;R0 = R1 + 256

(2)【带进位的加法指令】:ADC

ADC 目的寄存器,操作数1,操作数2

ADC指令用于把两个操作数相加,再加上CPSR中的C条件标志位的值,并将结果存放到目的寄存器中。

(3)【减法指令】:SUB

SUB 目的寄存器,操作数1,操作数2

把操作数1减去操作数2,并将结果存放到目的寄存器中。

SUB  R0,R1,R2  ;R0 = R1 - R2
SUB  R0,R1,#256  ;R0 = R1 - 256

3.比较指令

(1)【直接比较指令】:CMP

CMP  操作数1,操作数2
CMP R1,R0;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
CMP R1,#100;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位

4.逻辑运算指令

(1)【逻辑与指令】:AND

AND  目的寄存器,操作数1,操作数2

AND 指令用于在两个操作数上进行逻辑与运算,并把结果放置到目的寄存器中。

AND  R0,R0,#3 ; 该指令保持R0的0、1位,其余位清零。

(2)【逻辑或指令】:ORR

ORR 目的寄存器,操作数1,操作数2

ORR 指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。

ORR  R0,R0,#3 ; 该指令设置R0的0、1位,其余位保持不变。

二.转移指令

【跳转指令】

B   跳转指令
BL  带返回的跳转指令
BLX 带返回和状态切换的跳转指令
BX  带状态切换的跳转指令

三.程序状态寄存器访问指令

1、【MRS指令】

MRS 通用寄存器,程序状态寄存器(CPSR或SPSR)
MRS R0,CPSR   ;传送CPSR的内容到R0
MRS R0,SPSR   ;传送SPSR的内容到R0

2、【MSR指令】

MSR 程序状态寄存器(CPSR或SPSR)_<域>,操作数
MSR CPSR,R0   ;传送R0的内容到CPSR
MSR SPSR,R0   ;传送R0的内容到SPSR

四.加载/存储指令

ARM 微处理器支持加载/存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。

1、【LDR指令】

LDR 目的寄存器,<存储器地址>

LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。

LDR  R0,[R1]  ;将存储器地址为R1的字数据读入寄存器R0。
LDR  R0,[R1,R2]  ;将存储器地址为R1+R2的字数据读入寄存器R0。
LDR  R0,[R1,#8]  ;将存储器地址为R1+8的字数据读入寄存器R0。
LDR  R0,[R1,R2] ! ;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
LDR  R0,[R1,#8] ! ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。

LDRB 和 LDRH 指令大家可以百度。

2、【STR指令】

STR 源寄存器,<存储器地址>

STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。

STR R0,[R1],#8 ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
STR R0,[R1,#8] ;将R0中的字数据写入以R1+8为地址的存储器中。

STRB 和 STRH指令大家可以百度。

五.异常产生指令

1、【SWI指令】

SWI 24位的立即数

SWI指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。

SWI  0x02 ;该指令调用操作系统编号位02的系统例程。

2、【BKPT指令】

BKPT   16位的立即数

BKPT指令产生软件断点中断,可用于程序的调试。

六.伪代码

1.【AREA】

一个汇编程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段,因此在汇编程序的开头,我们一般的语句会用到AREA。

AREA 段名 属性 1 ,属性 2 ,....  
AREA Init ,CODE ,READONLY ;定义一个代码段,段名为 Init ,属性为只读。 

2、【ALIGN】

ALIGN { 表达式 { ,偏移量 }} 

ALIGN 伪指令可通过添加填充字节的方式,使当前位置满足一定的对其方式。其中,表达式的值用于指定对齐方式,可能的取值为2的幂,如 1 、2 、4 、8 、16 等。eg : xxx = ALIGN(4)

3、【CODE16、CODE32】

CODE16 (或 CODE32 )

CODE16 伪指令通知编译器,其后的指令序列为 16 位的 Thumb 指令。

CODE32 伪指令通知编译器,其后的指令序列为 32 位的 ARM 指令。

4、【ENTRY】

ENTRY      
ENTRY(stext)

很常见!!!ENTRY 伪指令用于指定汇编程序的入口点。在一个完整的汇编程序中至少要有一个 ENTRY (也可以有多个,当有多个 ENTRY 时,程序的真正入口点由链接器指定),但在一个源文件里最多只能有一个 ENTRY (可以没有)。

5、【END】

END    

END 伪指令用于通知编译器已经到了源程序的结尾。

·················· END ··················

原文作者:Jasonangel

原文地址: 学 Linux 必会的 ARM 汇编指令-腾讯云开发者社区-腾讯云 (版权归原文作者所有,侵权联系删除)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

学 Linux 必会的 ARM 汇编指令 的相关文章

  • 将数组传递给函数名称冲突

    Specs GNU bash 版本 3 1 17 无法升级 Premise 我一直在摆弄数组 我想知道是否有任何方法可以让函数的本地变量与所述函数外部的数组同名 Example 在下面的示例中 我将尝试显示该问题 Working bin b
  • 如何获取 linux 实用程序 tail 的源代码?

    这个命令确实非常有用 但是我可以在哪里获取源代码以查看内部发生的情况 thanks tail 实用程序是 Linux 上 coreutils 的一部分 源压缩包 ftp ftp gnu org gnu coreutils coreutils
  • 构建 makefile 依赖/继承树

    如果我解释得不好或者问了一些明显的问题 我很抱歉 但我是 Linux 内核的新手 而且有点深入 我们有一个嵌入式 Linux 系统 它附带一个 文档非常糟糕的 SDK 其中包含数百个文件夹stuff 大多数文件夹包含rules make m
  • 为什么在 Linux 上字符串文字的内存地址与其他字符串文字的内存地址如此不同?

    我注意到字符串文字在内存中的地址与其他常量和变量 Linux 操作系统 非常不同 它们有许多前导零 未打印 Example const char h Hi int i 1 printf p n void h printf p n void
  • 无法执行'x86_64-conda_cos6-linux-gnu-gcc':没有这样的文件或目录(pysam安装)

    我正在尝试安装 pysam 执行后 python path to pysam master setup py build 这个错误的产生是 unable to execute x86 64 conda cos6 linux gnu gcc
  • 为 Qt 应用程序创建 Linux 安装

    我刚刚用 Qt Creator 制作了一个很棒的程序 我对自己很满意 如何将其从台式机移至笔记本电脑 那么 最好的方法是安装程序 对吗 对于 Ubuntu 这是一个 Debian 软件包 对吗 我怎么做 有人这样做过吗 他们可以分享 QT
  • 每个进程每个线程的时间量

    我有一个关于 Windows 和 Linux 中进程和线程的时间量子的问题 我知道操作系统通常为每个线程提供固定的时间量 我知道时间量根据前台或后台线程而变化 也可能根据进程的优先级而变化 每个进程有固定的时间量吗 例如 如果操作系统为每个
  • Linux shell 脚本:十六进制数字到二进制字符串

    我正在 shell 脚本中寻找一些简单的方法来将十六进制数字转换为 0 和 1 字符的序列 Example 5F gt 01011111 是否有任何命令或简单的方法来完成它 或者我应该为其编写一些开关 echo ibase 16 obase
  • linux x86 汇编语言 sys_read 调用的第一个参数应为 0 (stdin)

    我正在编写一个简单的汇编程序来从标准输入读取 如 scanf 这是我的代码 section bss num resb 5 section txt global start start mov eax 3 sys read mov ebx 0
  • 如何在特定 systemd 服务重新启动时触发自定义脚本运行

    我想知道如何安排自定义脚本在重新启动服务时运行 我的用例是 每当重新启动 Tomcat 服务时 我都必须运行多个命令 我想知道是否有一种方法可以编写脚本并安排它在重新启动 Tomcat 服务时运行 我已将 tomcat 脚本设置为 syst
  • 如何查找连接到 AF_INET 套接字的客户端的 UID?

    有什么方法或类似的东西ucred for AF UNIX如果是AF INET插座 TCP在我的例子中 找出连接到我的套接字的客户端的UID 还有 proc net tcp但它显示了UID of the creator插座的而不是连接的cli
  • Linux shell 脚本中的 while 循环超时

    这工作正常 无限循环 while TRUE do printf done 我在尝试着timeout this while loop与timeout命令 所有这些都不起作用 timeout 5 while TRUE do printf don
  • PHP 致命错误:未找到“MongoClient”类

    我有一个使用 Apache 的网站 代码如下 当我尝试访问它时 我在 error log 中收到错误 PHP Fatal Error Class MongoClient not found 以下是可能错误的设置 但我认为没有错误 php i
  • .NET Core 中的跨平台文件名处理

    如何处理文件名System IO以跨平台方式运行类以使其在 Windows 和 Linux 上运行 例如 我编写的代码在 Windows 上完美运行 但它不会在 Ubuntu Linux 上创建文件 var tempFilename Dat
  • 嵌入式Linux poll()不断返回

    我有一个特别的问题 当我知道没有什么可读时 民意调查不断返回 因此设置如下 我有 2 个文件描述符 它们构成fd设置民意调查监视 一种用于引脚从高到低的变化 GPIO 另一个用于代理输入 代理输入出现问题 处理的顺序是 启动main函数 然
  • 为什么我收到的数据包数据大小大于mss?

    我在两台 PC 上使用 ifconfig ethX mtu 300 修改了 MTU 并使用 netperf 测试网络 我用 WireShark 嗅探了 SYN 数据包中的 MSS 260 但我得到了一些大于 260 的数据包 为什么 嗅探器
  • 使用 find - 删除除任何一个之外的所有文件/目录(在 Linux 中)

    如果我们想删除我们使用的所有文件和目录 rm rf 但是 如果我希望一次性删除除一个特定文件之外的所有文件和目录怎么办 有什么命令可以做到这一点吗 rm rf 可以轻松地一次性删除 甚至可以删除我最喜欢的文件 目录 提前致谢 find ht
  • 从 PL/SQL 调用 shell 脚本,但 shell 以 grid 用户而非 oracle 身份执行

    我正在尝试使用 Runtime getRuntime exec 从 Oracle 数据库内部执行 shell 脚本 在 Red Hat 5 5 上运行的 Oracle 11 2 0 4 EE CREATE OR REPLACE proced
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • 创建 jar 文件 - 保留文件权限

    我想知道如何创建一个保留其内容的文件权限的 jar 文件 我将源代码和可执行文件打包在一个 jar 文件中 该文件将在使用前提取 人们应该能够通过运行批处理 shell 脚本文件立即运行示例和演示 然后他们应该能够修改源代码并重新编译所有内

随机推荐