常见汇编指令

您所在的位置:网站首页 汇编指令lsl 常见汇编指令

常见汇编指令

2023-09-06 06:26| 来源: 网络整理| 查看: 265

# 常见汇编指令 # 0x0. 引言

好记性不如烂笔头,本文旨在记录一些日常工作中经常会遇到的汇编指令,并会不断更新。目前只包含ARM和AT&T两种格式,以ARM64为主。

# 0x1. ARM64 # mov

传送指令:将立即数传送到寄存器/内存单元,或互传内存单元和寄存器两者中的数据。

例如:mov x0, #0x1 / mov $0x1, %rdi 将立即数0x1移动到寄存器x0/rdi中

# mvn

该指令与mov唯一不同的是:需要对操作数进行按位取反。

# str

store register. 将寄存器中的数据存到内存单元中。

例如:str x0, [sp, #0x28] 将寄存器x0中的数据存到地址sp+0x28处

# stp

store pair of registers.

例如:stp x29, x30, [sp, #0x70] 先将x29存到地址sp+0x70处,再将x30存到sp+0x78处 (Tip1)。

Tip1: 64位下,寄存器大小为8bytes

# ldr

load register. 从内存中读取数据,存到寄存器中。

例如:ldr x1, [sp, #0x30] 将内存地址sp+0x30处的数据加载到x1中。

# ldp

load pair of registers.

例如:ldp x29, x30, [sp, #0x70] 将内存地址sp+0x70处的数据加载到x29中,再将sp+0x78(Tip1)处的数据加载到x30中。

# b

branch. 无条件跳转。

例如:b 0x1b6b79cf8 跳转到0x1b6b79cf8处继续执行。

# bl

branch with link. 将下一条指令地址copy到lr中,然后跳转。由于保存了下一条指令地址(相对于pc),所以可实现子程序的返回,而b只能单纯的实现跳转,不能实现子程序返回。

例如:

0x102b7d8a4 : bl 0x102bda450 ; symbol stub for: objc_msgSend -> 0x102b7d8a8 : adrp x0, 107 12

当程序执行完bl指令时,lr中的内容应该是是bl下一条指令的地址,即0x102b7d8a8。通过控制台查看lr中的内容如下:

fp = 0x000000016d2853c0 lr = 0x0000000102b7d8a8 `-[AppDelegate application:didFinishLaunchingWithOptions:] + 164 at AppDelegate.m:41:5 sp = 0x000000016d285350 123# cbz

compare and branch on zero. 比较操作数是否为0,若为0则跳转。

例如:cbz w24, 0x1b6b798f4 若w24 (x24寄存器低32位) 中的数据为0,则跳转到0x1b6b798f4处执行 (Note1)。

Note1: 跳转地址需要在cbz/cbnz指令之后的4~130字节内。

# cbnz

compare and branch on non-zero. 操作数不为0,则跳转。

例如:cbnz w27, 0x1b73c9e2c 若w27中的数据不为0,则跳转到0x1b73c9e2c处执行 (Note1)。

# lsl

logical shift left. 左移位。

例如:str x0, [x1, x2, lsl #2] 将x2中的值左移两位,再加上x1中的值,得到的结果为一个内存地址,最后将x0中的数据存到该内存中。

# lsr

logical shift right. 右移位。

# cmp

compare. 比较两个数是否相等,首先将两个数相减,若差为0,则ZF (Tip2) 为1,即两者相等。

cmp w8, #0x3 通过判断w8中的值与0x3的差值是否为0,即ZF (Tip2) 是否为1,来比较两者是否相等。

Tip2: ZF是零标志位寄存器。它记录相关指令执行后,其结果是否为0。若结果为0,则ZF=1;若结果为1,则ZF=0。

# adrp

form pc-relative address to 4KB page. 先将操作数左移12位,再将pc的低12位清零 (即3个十六进制位清零,得到一个页对齐地址),最后两者相加,赋值给寄存器。

例如:

0x1b703f074 : adrp x20, 270332 -> 0x1b703f078 : ldr x0, [x20, #0x7a0] 12

执行adrp时,先将操作数270332 (十六进制为0x41ffc) 左移12位得到0x41ffc000,再将pc (0x1b703f074) 低12清零得到 0x1b703f000,最后两者相加得到0x1f903b000赋值给x20。通过控制台查看x20中的内容:

x19 = 0x000000016ef25fb0 x20 = 0x00000001f903b000 x21 = 0x0000000281454380 123# adr

load a program-relative or register-relative address into a register. 是一条伪指令,遇到该指令时汇编器会生成一条add或sub指令,来计算pc和操作数的和或者差,最后将得到的结果,放在寄存器中。

例如:

; 生成加法指令,即x0 = 0x1022c3b08 + 0x2fc48 = 0x1022f3750 0x1022c3b08 : adr x0, #0x2fc48 ; _MergedGlobals + 16 -> 0x1022c3b0c : nop ; 生成减法指令,即x2 = 0x1022c3b10 - 0x390 = 0x1022c3780 0x1022c3b10 : adr x2, #-0x390 ; initializeAvailabilityCheck -> 0x1022c3b14 : nop 1234567# brk

breakpoint instruction. 用于生成断点指令异常。

# tbz

test branch zero. 测试位为0,则跳转。

tbz w24, #0x6, 0x19307005c ; 即w24第6位,若为0,则跳转到0x19307005c执行 1

w24 二级制数为:0b00000111000000000000100000000110

# tbnz

test branch no zero. 测试位不为0,则跳转。

tbnz w24, #0x6, 0x19307005c ; 即w24第6位,若不为0,则跳转到0x19307005c执行 1

w24 二级制数为:0b00000111000000000000100000000110

# 0x2. AT&T # test

将指令后的两个数进行按位与操作,其结果影响ZF。通常用来判断某个数是否为0/nil。

例如:

testq %rax, %rax ; 若%rax中的值为0,则ZF=1;反之,ZF=0,q表示四字长 1# sete

取ZF中的值,放入目标寄存器中。

例如:

testq %rax, %rax ; 两个寄存器中的值按位与,结果影响ZF sete %r12 ; 若%rax和%rbx相等,即ZF=1,则将%r12设为1,反之设为0 12# setne

取ZF中的值,然后取反,再放入目标寄存器中。

例如:setne %rax 若ZF=1,则%rax设为0;反之设为1

# je / jz

je 和 jz这两条指令虽然名字不同,但做的事情都是一样的。即ZF=1,则跳转。

例如:

libobjc.A.dylib`objc_retain: 0x7fff50bad350 : testq %rdi, %rdi ; 判断%rdi中的值(第一个参数)是否为nil 0x7fff50bad353 : je 0x7fff50bad371 ; 若%rdi为nil,则跳转到0x7fff50bad371执行 0x7fff50bad355 : js 0x7fff50bad373 ; -> 0x7fff50bad357 : movq (%rdi), %rax 12345# jne / jnz

jne 和 jnz这两条指令做的事情也都是一样的。即ZF=0,则跳转。

# js

jump if sign. 若结果为负数,即SF=1,则进行跳转。

SF: 符号标志位

它记录相关指令执行后,其结果是否为负。若结果为负,则SF=1;若为非负,则SF=0。

# nop

no operation. 不执行任何操作。是一条单字节指令。 Opcode 90

# ud2

undefined instruction. 该指令用于生成一个无效操作码。当CPU试图执行无效或未定义的操作码时,将发生无效的操作码异常 。UD2指令除了引发无效的操作码异常外,与NOP指令相同。

这里的异常是指CPU在发生“错误”时生成的。大多数情况下,有些异常并不是真正的错误,而是中断的一种类型。比如: Page Fault。异常分类如下:

Faults (错误):这些错误可以被纠正,程序可以像什么都没有发生一样继续运行。 Traps (陷阱):陷阱指令执行后会立即被报告。 Aborts (终止):一些严重的不可恢复的错误。 # ret

该指令用于子程序的返回。将栈顶数据(返回地址)弹出,赋值给 ip 寄存器,此时 sp 会增加一个内存单元大小,来释放栈空间。

栈底 [ ... | ... , parameters, return address | previous frame pointer, %rbp ] 栈顶

pop %rbp 👇 栈底 [ ... | ... , parameters, return address ] 栈顶

ret 👇 栈底 [ ... | ... , parameters ] 栈顶

caller release parameters 👇 栈底 [ ... | ... ] 栈顶

最后更新: 4/9/2020, 3:11:50 PM

← 汇编入门必备



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3