首页 > 系统相关 >内存管理-15-Arm64汇编

内存管理-15-Arm64汇编

时间:2024-07-10 09:19:06浏览次数:13  
标签:x1 15 r1 指令 Arm64 寄存器 x0 加载 内存


1. Arm64汇编 lsr 指令

LSR是ARM架构的位移动指令,用于逻辑右移操作。它将第一个操作数的位向右移动指定位数,并根据需要将符号位(在有符号数操作中)扩展到空出来的位。

语法:

LSR{条件}{S} 移位量,寄存器

条件是可选的,指定为如 EQ、NE 等,用来指明只有在特定条件下才能执行指令。
S 是可选的,指定为 S 表示指令应该影响 CPSR 中的条件标志位,不指定则不影响条件标志位。
移位量是一个立即数,用来指定位移动的位数,范围通常是0到31。
寄存器是一个通用寄存器,包含要移位的值。

实例代码:

LSR R0, R0, #5 ; 将寄存器R0中的值逻辑右移5位

这条指令将寄存器R0中的值移动5位右边的位进入CPSR中,左边空出的位用0填充,符号位扩展也遵循这个规则。


2. Arm64汇编 add 指令

ADD 用于执行加法操作。它可以用于两个通用寄存器、一个通用寄存器和一个寄存器的内存地址、或者一个寄存器和一个立即数之间的加法。

以下是一些使用 ADD 指令的例子:

两个通用寄存器之间的加法:

ADD w0, w1, w2 ; 将 w1 和 w2 的内容相加,结果存储在 w0 中

通用寄存器与内存地址之间的加法:

ADD w0, w1, [x2] ; 将 w1 和内存地址 x2 指向的值相加,结果存储在 w0 中

通用寄存器与立即数之间的加法:

ADD w0, w1, #10 ; 将 w1 和立即数 10 相加,结果存储在 w0 中

请注意,ADD 指令可以有条件执行,例如,ADD 指令可以跟有条件后缀,如 EQ、NE、HS 等,这样只有在特定条件满足时才会执行加法操作。

 

3. Arm64汇编 orr 指令

orr 是 ARM 汇编语言中的一个逻辑指令,用于执行两个值的按位或操作。orr 指令可以对两个寄存器或寄存器和立即数进行操作。

语法格式如下:

orr {<cond>} <rd>, <rn>, <operand2>

<cond> 是可选的条件代码。
<rd> 是目标寄存器,用于保存结果。
<rn> 是第一个源寄存器,其内容将被操作。
<operand2> 是第二个源操作数,可以是一个寄存器或立即数值。

实例代码:

orr r0, r1, #0xF ; 将寄存器 r1 的值与立即数 0xF 进行按位或操作,结果存储在 r0 中
orr r2, r3, r4 ; 将寄存器 r3 的值与寄存器 r4 的值进行按位或操作,结果存储在 r2 中

在这个例子中,r0 将会是 r1 或上 0xF 的结果,r2 将会是 r3 或 r4 的结果。


4. arm64汇编 str 指令

str 是 ARM 汇编语言中的一个指令,用于将数据从寄存器传送到内存地址。####在 ARM 架构中,有多种不同的 str 指令,用于处理不同的数据类型和操作模式。

以下是一些使用 str 指令的示例:

(1) 将一个32位的寄存器值存储到内存中:

str r1, [r2]

这条指令会将寄存器 r1 的值存储到 r2 寄存器值指定的内存地址中。

(2) 将一个64位的寄存器值存储到内存中:

str r1, [r2]
str r1, [r2, #8]!

第一条指令会将 r1 的低64位存储到内存地址中。第二条指令会将 r1 的高64位存储到内存地址中,并且更新 r2 的值(使用后续的内存地址)。

(3) 将一个32位的寄存器值存储到带有偏移的内存地址中:

str r1, [r2, #16]

这条指令会将 r1 的值存储到 r2 的值加上16后得到的内存地址中。

(4) 将一个32位的寄存器值存储到带有索引的内存地址中:

str r1, [r2, lr]

这条指令会将 r1 的值存储到 r2 的值加上 lr 寄存器值得到的内存地址中。

(5) 将一个32位的常数存储到内存中:

str w3, [sp, #-4]!

这条指令会将常数w3存储到栈上,并更新 sp 寄存器的值(向下增长)。

(6) 将一个16位的寄存器值存储到内存中:

strh r1, [r2]

这条指令会将 r1 的低16位存储到内存地址中。

(7) 将一个8位的寄存器值存储到内存中:

strb r1, [r2]

这条指令会将 r1 的低8位存储到内存地址中。

(8) 使用 str 指令复制数据:

str r1, [r2]

这条指令会将 r1 寄存器中的值复制到 r2 寄存器指定的内存地址中。

注意:在使用 str 指令时,确保目标地址是可写的,否则会产生异常。

补充:这里给出不同指令下进行数据操作的位数:
ldrb/strb 8位操作
ldrh/strh 16位操作
ldr/str 32位操作
ldrd/strd 64位操作


5. Arm64汇编 .macro 指令

.macro 是 ARM 汇编语言中用于定义宏的指令。宏是一段可以重复使用的汇编代码,类似于 C 语言中的宏。使用 .macro 指令定义宏,使用 .endm 指令结束宏定义。

下面是一个简单的 .macro 使用例子:

.macro BLK_MOV_ALIGNED_I4 inptr, outptr, len, incr
mov x0, \inptr
mov x1, \outptr
mov x2, \len
mov x3, \incr
blk_mov_aligned_i4 x0, x1, x2, x3
.endm

在这个例子中,BLK_MOV_ALIGNED_I4 是宏的名称。宏接受四个参数:inptr, outptr, len, 和 incr。这些参数在宏的代码中通过 \param 的方式使用,其中 \inptr 代表输入指针参数,\outptr 代表输出指针参数,依此类推。

当宏被调用时,例如通过 BLK_MOV_ALIGNED_I4 x0, x1, x2, x3,它将把 x0, x1, x2, x3 分别赋值给 \inptr, \outptr, \len, \incr,然后执行 blk_mov_aligned_i4 x0, x1, x2, x3 指令。

注意:这只是一个假设的 blk_mov_aligned_i4 实现的宏例子,实际的 blk_mov_aligned_i4 是内核提供的一个函数,宏用于封装函数调用的参数。


6. Arm64汇编 mov 指令

在ARM架构中,mov 指令用于数据传送。在ARMv8 (arm64) 汇编中,mov 指令可以用于不同的数据类型,包括通用寄存器,寄存器的特定位,或者是寄存器和内存之间的数据传送。

以下是一些使用 mov 指令的例子:

(1) 将一个常数加载到寄存器中:

mov x0, #0x12345678 // 将常数0x12345678加载到x0寄存器中

(2) 将一个寄存器的值复制到另一个寄存器:

mov x1, x0 // 将x0寄存器中的值复制到x1寄存器中

(3) 将内存地址中的值加载到寄存器中:

mov x2, [x1] // 将x1寄存器指向的内存地址中的值加载到x2寄存器中

(4) 将一个特定的位从一个寄存器复制到另一个寄存器:

movk x0, #0x12, lsl #16 // 将0x12左移16位后,加载到x0寄存器的高16位中

(5) 将一个寄存器的值复制到另一个特定的寄存器(例如,将程序计数器的值复制到x0寄存器):

mov x0, pc // 将程序计数器的值复制到x0寄存器中

(6) 将一个寄存器的值复制到另一个特定的寄存器(例如,将链接寄存器x30的值复制到x0寄存器):

mov x0, x30 // 将链接寄存器的值复制到x0寄存器中

注意:在使用 mov 指令时,确保目标寄存器和源操作数的大小是兼容的,例如,不能直接将一个32位的值移动到一个64位的寄存器中,除非使用适当的扩展指令(如 movw 或 movn)。


7. Arm64汇编 b.ls 指令

b.ls 是一条条件分支指令,在 ARM 64 位汇编中,用于“less than and equal”的条件分支,即当比较的两个值中一个小于或等于另一个时,程序会跳转到指定的位置执行。

这条指令的全称是 "Branch Less Than or Equal",其语法格式如下:

b.ls <target_address>

其中 <target_address> 是你想要跳转到的地址。这条指令需要和状态寄存器中的条件标志一起工作,比如之前的一个比较指令 cmp 或者 ccmp 等可以设置条件标志的指令。

下面是一个使用 b.ls 的简单例子:

cmp x0, x1 // 比较寄存器x0和x1
b.ls label // 如果x0小于或等于x1,则跳转到label处执行

在这个例子中,cmp 指令用于比较寄存器 x0 和 x1,然后 b.ls 指令会检查比较的结果,如果 x0 小于或等于 x1,则程序会跳转到标签 label 指定的位置执行。

注意:b.ls 是 ARM 汇编的一个示例,具体的汇编语言和指令集可能会根据不同的处理器架构有所不同。


8. Arm64汇编 adrp 指令

adrp 是 ARM 64 位汇编语言中的一个地址相关的指令(Address Related Pointer),用于加载一个30位有符号的位移量到目标寄存器,用于支持大型内存页的访问。

adrp 指令不直接支持绝对地址计算,它通常与另一个指令 add 或 ldr 配合使用。adrp 指令生成一个31位有符号的位移量,通常用于加载大型内存页的基地址,然后通过 add 或 ldr 指令与一个32位的偏移量组合成最终的有效地址。

下面是一个使用 adrp 和 add 指令的例子:

adrp x0, my_data@PAGE // 加载数据段的基地址
add x0, x0, my_data@PAGEOFF // 加上偏移量得到具体地址
在这个例子中,my_data 是一个数据段的标签,汇编器会将它转换成一个32位的偏移量和一个使用 adrp 的基地址。这样,通过 adrp 指令我们得到了数据段的基地址,然后通过 add 指令我们加上偏移量得到了数据段中特定位置的实际有效虚拟地址。

提示:AI自动生成,仅供参考

 

9. arm64汇编 ldr指令

LDR 是 ARM 汇编中的一个 load register 指令,用于将数据从内存中加载到寄存器中。对于 ARM64 汇编,LDR 指令有多种变体,用于处理不同的数据加载和地址计算需求。

以下是一些使用 ARM64 汇编语言中 LDR 指令的示例:

将一个常量加载到寄存器中:

ldr x0, [0x12345678] // 将内存地址 0x12345678 处的值加载到寄存器 x0 中
将一个地址处的值加载到寄存器中,该地址是另一个寄存器的偏移量:

ldr x0, [x1, #0x10] // 将内存地址为 x1 寄存器值加上 0x10 的地址处的值加载到 x0 寄存器中
将一个符号地址处的值加载到寄存器中:

ldr x0, LABEL // 将标签 LABEL 表示的地址处的值加载到 x0 寄存器中
// ...
LABEL:
.quad 0x12345678 // 一些数据
将一个地址处的值加载到寄存器中,该地址是另一个寄存器的值与一个常数的和:

ldr x0, [x1, #0x10]! // 将内存地址为 x1 寄存器值加上 0x10 的地址处的值加载到 x0 寄存器中,同时将新地址写回到 x1 寄存器
使用 LDR 指令加载一个函数指针到寄存器中:

ldr x16, .LPIC0 // 加载一个 PIC (Position Independent Code) 偏移量到 x16 寄存器
// ...
.LPIC0:
.quad LPIC-.-
在使用 LDR 指令时,确保你的操作数和操作对应的寄存器是兼容的,并且考虑到 ARM64 寄存器的命名规则。此外,还需要注意指令的字节序和对齐问题。


10. arm64汇编 bl 指令

bl 是 ARM 汇编语言中的一个跳转指令,用于调用子程序。bl 指令在跳转之前会将下一条指令的地址保存在链接寄存器(LR)中,这样子程序在返回时可以正确继续执行。

bl 指令的格式如下:

bl <target_label>
其中 <target_label> 是你想要跳转到的子程序的标签。

例如,假设你有一个名为 subroutine 的子程序,你可以使用 bl 指令来调用它:

bl subroutine
在 subroutine 子程序的结尾,它应该使用 bx 或 b 指令来返回到保存在 LR 中的地址:

bx lr
或者

b *lr
这样,执行 bl subroutine 后,当 subroutine 子程序执行完毕后,执行流会回到 bl 指令之后的指令继续执行。


11. arm64汇编 stp 指令

stp 是 ARM 汇编语言中的一个指令,用于将一组寄存器的值存储到内存中。stp 是 "Store Registers in Pair" 的缩写。

语法:

stp { xn | sp }, { xn | sp }, [r], {#imm}

参数:

{ xn | sp } 是一个寄存器,可以是 x30(通常是 lr 或链接寄存器)或 sp(堆栈指针)。
{ xn | sp } 是另一个寄存器,用于与第一个寄存器配对。
[r] 是目标内存地址的基地址寄存器。
{#imm} 是一个可选的偏移量,用于指定存储位置的具体偏移量。

示例代码:

stp x29, x30, [sp, -16]! // 将 x29 和 x30 压栈,并更新 sp 的值

在这个例子中,stp 指令将寄存器 x29 和 x30 的值存储到当前堆栈顶部,然后将堆栈顶部向下移动 16 字节,并更新堆栈指针 sp。后缀 ! 表示对寄存器 sp 进行修改。######


12. arm64汇编 b.ne 指令

b.ne 是 ARM 汇编语言中的一个条件分支指令,它的全称是 "Branch if Not Equal",也就是当两个操作数不相等时才会跳转。

这个指令通常用于比较两个寄存器或者寄存器和立即数的值,然后根据比较结果是否相等来决定是否跳转到另一个标签(Label)或者指定的地址。

下面是一个使用 b.ne 指令的简单例子:

cmp x0, x1 // 比较寄存器x0和x1的值
b.ne label // 如果不相等,跳转到标签label处执行

在这个例子中,cmp 指令用于设置条件标志位,根据 x0 和 x1 的值进行比较。b.ne 指令检查不相等(NE)标志位,如果该标志被设置(表示x0不等于x1),则执行跳转到标签 label。

需要注意的是,b.ne 是一个短跳转指令,它的跳转范围是有限的,通常在当前指令的后面或者前面128MB范围内。#######如果需要更远的跳转,你应该使用 b 指令或其他分支指令。


13. arm64汇编 cmp 指令

CMP 是 ARM 汇编语言中的一个指令,用于比较两个操作数。当两个操作数作减法时,如果 Minuend(被减数)大于 Subtrahend(减数),则结果为正;如果 Minuend(被减数)小于 Subtrahend(减数),则结果为负;如果两者相等,结果为零。

CMP 指令不会改变操作数本身,只会设置一些特殊的程序状态寄存器(PSR)的标志位,这些标志位可以用来决定接下来应该执行什么样的代码分支。

下面是一些使用 CMP 指令的例子:

(1) 基本的比较操作:

cmp r0, r1 @ 将寄存器 r0 的值和 r1 的值进行比较

(2) 比较立即数:

cmp r0, #0 @ 将寄存器 r0 的值和立即数 0 进行比较

(3) 比较并根据结果决定是否跳转:

cmp r0, r1
beq next @ 如果 r0 等于 r1,则跳转到标签 next 的指令

(4) 比较数组中的元素:

ldr r2, [r0], #4 @ 加载数组的下一个元素到 r2
cmp r2, r1 @ 将 r2 和 r1 进行比较
bne difference @ 如果 r2 和 r1 不相等,则跳转到标签 difference 的指令

注意:CMP 指令不会改变操作数本身,只会改变状态寄存器的标志位。如果你需要保留操作数用于其他目的,你应该在执行 CMP 指令后将操作数拷贝到另一个寄存器。


14. Arm64汇编 dc 指令

在ARM架构中,DC是一个用于数据复制的指令,通常用于初始化数据。DC指令是ARM汇编器的扩展,用于在ELF (Executable and Linkable Format) 文件中生成一个专用的 .data.rel.ro 节。

DC指令的语法如下:

DC <constant> ; 复制一个常量到寄存器
DC { <constant_expression> } ; 复制一个常量表达式到寄存器
DC { <symbol> } ; 复制一个符号的地址到寄存器
DC { :<alignment> } ; 设置下一个数据标签的对齐
DC { ^ } ; 结束数据标签的定义
例如,以下是一个使用DC指令的简单ARM64汇编代码片段:

.data
.align 3
my_data:
DC 42 ; 将常量42初始化到一个字
DC 23 ; 将常量23初始化到下一个字
DC {my_symbol} ; 将符号my_symbol的地址初始化到一个字
DC {^} ; 结束数据初始化

在这个例子中,my_data 被初始化为包含四个字,分别是42, 23, my_symbol的地址,和一个结束标记。这种初始化方法通常用于初始化数组或者其他数据结构。


15. Arm64汇编 adr_l 指令

ADR_P 是 ARM 汇编器的一个指令,用于生成相对于 PC 的地址。它是 ADR 指令的一个变种,用于处理大于 4KB 的加载。

ADR_P 指令的语法如下:

ADR_P <register>, <expression>

其中 <register> 是目标寄存器,<expression> 是目标地址。

这个指令会尝试生成一个有效的地址,但是如果目标地址超出了 ADR_P 指令的有效范围(即,目标地址与当前 PC 的偏移量超过了 2^12 - 1 字节),那么这个指令将失败。

例如,如果你有一个标签 .label 在 4KB 之后,你可以使用 ADR_P 来加载它的地址:

adrp x0, .label
add x0, x0, :lo12:.label

这里,adrp 用于获取 .label 的高 32 位地址,add 用于获取低 12 位的偏移量。

注意:ADR_P 是在 ARMv8-A 架构中引入的,因此它不能在不支持此功能的旧架构中使用。


16. Arm64汇编 mov_q 指令

movq 是一个用于64位操作数的指令,用于将数据从一个位置移动到另一个位置。


17. arm64汇编 ret 指令

在ARM架构中,ret 指令用于从子程序返回到调用者。在ARMv8-A (arm64) 汇编中,ret 指令可以用于从子程序返回并恢复程序状态。

ret 指令的基本语法如下:

ret{cond}

其中 {cond} 是可选的条件代码。如果不指定,则默认条件代码为 al (即所有条件码)。

下面是一个简单的例子,展示了如何在ARM64汇编中使用 ret 指令:

sub sp, sp, #0x20 // 分配栈空间
stp x29, x30, [sp, #0x10]! // 保存调用者的链接寄存器和程序计数器
// ...子程序代码 ...
ldp x29, x30, [sp], #0x20 // 恢复调用者的链接寄存器和程序计数器
ret // 返回到调用者

在这个例子中,我们在调用子程序前保存了链接寄存器 x29 (fp) 和程序计数器 x30 (lr),在子程序结束前恢复它们,并使用 ret 指令返回到调用者。


18. Arm64汇编 ldp 指令

ldp 是 ARM 汇编语言中用于从寄存器组或栈中加载双精度浮点寄存器(FP Double-precision)的指令。它用于从内存地址加载 128 位的数据到两个浮点寄存器(通常是单独的浮点寄存器,但也可以是一个的高 64 位和另一个的低 64 位)。

语法如下:

LDP <Wt1>, <Wt2>, [<Xn|SP>], #<imm>
LDP <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]!
LDP <Xt1>, <Xt2>, [<Xn|SP>], #<imm>
LDP <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]!

这里 <Wt1> 和 <Wt2> 是目标浮点寄存器,<Xn|SP> 是基址寄存器,<imm> 是一个常量偏移量。

例子:

ldp x29, x30, [sp], #0x20 // 将栈上偏移为 sp 的 32 字节处的数据加载到 x29 和 x30,然后 sp 增加 0x20

在这个例子中,ldp 指令用于从当前的栈指针 sp 所指向的位置加载两个 64 位的值到浮点寄存器 x29 和 x30,然后更新栈指针 sp 增加 0x20 字节。

 

标签:x1,15,r1,指令,Arm64,寄存器,x0,加载,内存
From: https://www.cnblogs.com/hellokitty2/p/18293178

相关文章

  • 关于力扣150题目——逆波兰表达式求值Java实现的三种解法
    题目介绍逆波兰表达式是一种后缀表达式,其运算符位于操作数之后。力扣150题目要求我们实现一个函数,计算给定逆波兰表达式的值。本文将介绍三种不同的Java实现方法来解决这个问题。解法一:使用栈这是最直观和常见的解法,使用栈来存储操作数,并在遇到运算符时从栈中弹出操作数......
  • 15、 Django-多表操作-多个模块的关联-多对多的增删改查- models.manytomany()
    针对多对多的关系django会自动创建第三张表、也可以通过through参数指定第三张表 models.pyfromdjango.dbimportmodels#Createyourmodelshere.#多对多#用户表:电影=N:M#一个用户可以收藏多部电影#一部电影可以被不同的用户收藏#电影classMovie(models.M......
  • 代码随想录刷题day 7 | 哈希表part02 454.四数相加II 383. 赎金信 15. 三数之和
    454.四数相加II//这道题使用哈希就可解决,使用一个map存储前两个数组中,所有组合产生的sum的频率;对于后两个数组中所有的组合,每出现一个和的相反数出现在map中,则代表出现了这个相反数频率个组合可以满足四数相加为0classSolution{publicintfourSumCount(int[]nums1,......
  • 结构体内存对齐
    计算结构体所占用的内存是在学习C语言时需要学习的内容,学习结构体内存对齐是计算结构体所占空间必不可少的知识点。那么什么是结构体内存对齐呢?相信学完这篇文章后,你会对结构体有更加深入的理解。对齐规则1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址......
  • 电脑清理c盘内存空间怎么清理免费 怎么清理c盘的垃圾文件又不删除有用文件
    在计算机使用过程中,随着时间的推移,C盘空间可能会被各种临时文件、缓存和无用的注册表项占用。这不仅会导致C盘空间不足,还可能影响计算机的性能。那么怎么样清理C盘内存空间,怎么样清理C盘的垃圾避开系统文件呢?一、怎么样清理C盘内存空间通常我们会在电脑中进行各种操作,比如会......
  • [深入理解Java虚拟机]Java内存模型
    Java内存模型概述多任务处理在现代计算机操作系统中几乎已是一项必备的功能了。在许多场景下,让计算机同时去做几件事情,不仅是因为计算机的运算能力强大了,还有一个很重要的原因是计算机的运算速度与它的存储和通信子系统的速度差距太大,大量的时间都花费在磁盘I/O、网络通信或者数......
  • Python是如何进行内存管理的以及引用计数和垃圾回收机制的定义
    Python中的内存管理是一个自动且高效的过程,主要依赖于两种机制:引用计数(ReferenceCounting)和垃圾回收(GarbageCollection,GC)。这些机制共同工作以确保不再被使用的内存能够被及时释放,从而避免内存泄漏。引用计数引用计数是Python中最主要的内存管理机制。Python中的每个对象都......
  • LeetCode 1546. 和为目标值且不重叠的非空子数组的最大数目
    1546.和为目标值且不重叠的非空子数组的最大数目给你一个数组 nums 和一个整数 target 。请你返回 非空不重叠 子数组的最大数目,且每个子数组中数字和都为 target 。示例1:输入:nums=[1,1,1,1,1],target=2输出:2解释:总共有2个不重叠子数组(加粗数字表示)[1,......
  • k8s 关闭 enableServiceLink-Pod-CPU-内存占用过高
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<特性说明:enableServiceLinks特性,是k8s提供给pod发现和访问svc的两种方案之一(另一种是DNS)。该特性在pod启动时,kubelet会将activesvc通过env {SVCNAME}_SERVICE_HOST、......
  • 基于SpringBoot的酒店订房系统+82159(免费领源码)可做计算机毕业设计JAVA、PHP、爬虫、A
    springboot酒店订房系统摘 要随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,酒店订房系统当然也不能排除在外。酒店订房系统是以实际运用为开发背景,运用软件工程开发方法,采用springboot技术构建的一个管理系统......