不确定我在这篇文章中选择了 uxtw 右键单击并在 Google 上搜索 UXTW
第一个命中是Arm 文档
SUB Wd|WSP, Wn|WSP, Wm{, extend {#amount}} ; 32-bit general registers
SUB Xd|SP, Xn|SP, Rm{, extend {#amount}} ; 64-bit general registers
extend
Is the extension to be applied to the second source operand:
32-bit general registers
Can be one of UXTB, UXTH, LSL|UXTW, UXTX, SXTB, SXTH, SXTW or SXTX.
If Rd or Rn is WSP then LSL is preferred rather than UXTW,
and can be omitted when amount is 0.
In all other cases extend is required and must be UXTW rather than LSL.
64-bit general registers
Can be one of UXTB, UXTH, UXTW, LSL|UXTX, SXTB, SXTH, SXTW or SXTX.
If Rd or Rn is SP then LSL is preferred rather than UXTX,
and can be omitted when amount is 0.
In all other cases extend is required and must be UXTX rather than LSL.
sxtw 是有符号扩展字 8000->ffff8000
uxtw 是无符号扩展字 8000->00008000
引用另一个相关的热门话题
扩展运算符
扩展运算符的主要目的是扩大在寄存器中找到的较窄的值以匹配操作的位数。扩展运算符的形式为 kxtw,其中 k 是我们想要加宽的整数类型,w 是窄值的宽度。对于前者,整数的种类可以是U(无符号)或S(有符号,即二进制补码)。对于后者,宽度可以是 B、H 或 W,分别表示字节(寄存器的最低 8 位有效位)、半字(寄存器的最低 16 位有效位)或字(寄存器的最低有效位 32 位)。
这意味着扩展运算符是 uxtb、sxtb、uxth、sxth、uxtw、sxtw。
这些运算符的存在是因为有时我们必须将源值的范围从较小的位宽提升到较大的位宽。在后面的章节中,我们将看到许多发生这种情况的情况。例如,我们可能需要在 64 位寄存器中添加一个 32 位寄存器。如果两个寄存器都表示二进制补码整数,则
添加 x0, x1, w2, sxtw // x0 ← x1 + ExtendSigned32To64(w2)
使用这些扩展运算符时必须考虑某种上下文。例如,下面的两个指令的含义略有不同:
添加 x0, x1, w2, sxtb // x0 ← x1 + ExtendSigned8To64(w2) 添加 w0, w1, w2, sxtb // w0 ← w1 + ExtendSigned8To32(w2)
在这两种情况下,w2 的最低有效 8 位都被扩展,但在第一种情况下,它们被扩展到 64 位,在第二种情况下被扩展到 32 位。延伸与转移
通过在扩展运算符之后指定一个数量,可以扩展一个值,然后将其左移 1、2、3 或 4 位。例如
mov x0, #0 // x0 ← 0 mov x1, #0x1234 // x0 ← 0x1234 add x2, x0, x1, sxtw #1 // x2 ← x0 + (ExtendSigned16To64(x1) << 1) // 这会设置 x2 to 0x2468 add x2, x0, x1, sxtw #2 // x2 ← x0 + (ExtendSigned16To64(x1) << 2) // 这将 x2 设置为 0x48d0 add x2, x0, x1, sxtw #3 // x2 ← x0 + (ExtendSigned16To64(x1) << 3) // 这将 x2 设置为 0x91a0 add x2, x0, x1, sxtw #4 // x2 ← x0 + (ExtendSigned16To64(x1) << 4) // 这将 x2 设置为 0x12340
这在这一点上可能看起来有点奇怪和随意,但在后面的章节中我们将看到这在许多情况下实际上很有用。
这就是今天的全部内容。
这是一个示例独角兽 python 仿真
#code modified from unicorn sample
from __future__ import print_function
from unicorn import *
from unicorn.arm64_const import *
print (
"Register X30 on start = 0x10\n"
"Register W0 on start = 0x02\n"
"Emulate 5 ARM64 instructions that follows\n"
"ADD X30, X30, W0,UXTW#0\n"
"ADD X30, X30, W0,UXTW#1\n"
"ADD X30, X30, W0,UXTW#2\n"
"ADD X30, X30, W0,UXTW#3\n"
"ADD X30, X30, W0,UXTW#4\n"
"Register X30 on end = 0x10+0x2+0x4+0x8+0x10+0x20 == 0x4e"
)
CODE = b"\xDE\x43\x20\x8B\xDE\x47\x20\x8B\xDE\x4b\x20\x8B\xDE\x4f\x20\x8B\xDE\x53\x20\x8B"
ADDRESS = 0x10000
def test_arm64():
try:
mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM)
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
mu.mem_write(ADDRESS, CODE)
mu.reg_write(UC_ARM64_REG_X30, 0x10)
mu.reg_write(UC_ARM64_REG_W0, 2)
for i in range (ADDRESS,ADDRESS + len(CODE),4):
mu.emu_start(i, i + 4)
x30 = mu.reg_read(UC_ARM64_REG_X30)
w0 = mu.reg_read(UC_ARM64_REG_W0)
print(">>> x30 = 0x%x w0 = 0x%x" %(x30,w0))
except UcError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_arm64()
仿真结果
:\>python uniaarch64.py
Register X30 on start = 0x10
Register W0 on start = 0x02
Emulate 5 ARM64 instructions that follows
ADD X30, X30, W0,UXTW#0
ADD X30, X30, W0,UXTW#1
ADD X30, X30, W0,UXTW#2
ADD X30, X30, W0,UXTW#3
ADD X30, X30, W0,UXTW#4
Register X30 on end = 0x10+0x2+0x4+0x8+0x10+0x20 == 0x4e
>>> x30 = 0x12 w0 = 0x2
>>> x30 = 0x16 w0 = 0x2
>>> x30 = 0x1e w0 = 0x2
>>> x30 = 0x2e w0 = 0x2
>>> x30 = 0x4e w0 = 0x2
当您在 W0 中以 -0x2 开头时,请查看扩展结果
>>> x30 = 0x10000000e w0 = 0xfffffffe
>>> x30 = 0x30000000a w0 = 0xfffffffe
>>> x30 = 0x700000002 w0 = 0xfffffffe
>>> x30 = 0xefffffff2 w0 = 0xfffffffe
>>> x30 = 0x1effffffd2 w0 = 0xfffffffe
SXTW 和 -2
>>> x30 = 0xe w0 = 0xfffffffe
>>> x30 = 0xa w0 = 0xfffffffe
>>> x30 = 0x2 w0 = 0xfffffffe
>>> x30 = 0xfffffffffffffff2 w0 = 0xfffffffe
>>> x30 = 0xfffffffffffffff0 w0 = 0xfffffffe
SXTW 和 2
>>> x30 = 0x12 w0 = 0x2
>>> x30 = 0x16 w0 = 0x2
>>> x30 = 0x1e w0 = 0x2
>>> x30 = 0x2e w0 = 0x2
>>> x30 = 0x30 w0 = 0x2