• ARM64汇编05 - MOV系列指令


    MOV(wide immediate)

    MOV 可以将一个立即数移动到寄存器中。

    .text:0000000000000834 80 46 82 D2                   MOV             X0, #0x1234             ; Keypatch modified this from:
    

    MOV X0, #0x1234 对应的汇编代码为:80 46 82 D2

    看手册可知,0x1234 的值储存在 5 - 20 位里面。

    汇编指令对应的二进制为:

    1. 80 46 82 D2 ->
    2. D2 82 46 80 ->
    3. 11010010 10000010 01000110 10000000 ->
    4. 1 10 100101 00 0001 0010 0011 0100 00000

    其中最低5为都是0,所以寄存器是 X0 寄存器。

    5-20 位的值分别是 4 3 2 1,刚好就是 0x1234。

    这种 mov 指令还是比较常见的,但是由于指令的限制,它只能描述16位的立即数。

    看另外的一个例子:

    .text:0000000000000834 00 00 B0 D2                   MOV             X0, #0x80000000
    

    MOV X0, #0x80000000 这条指令的立即数显然已经超过了16位,这又是咋回事呢?

    这是 MOV 指令的另一种形式,由于 #0x80000000 这样的立即数实际的有效位数很少,所以ARM指令集对其表示做了优化。

    手册里面有说到,MOV 实际上等同于 MOVZ:

    而 MOVZ 是支持 shift 写法的:

    MOVZ <Xd>, #<imm>{, LSL #<shift>}
    

    所以上面的汇编实际上等同于:

    MOVZ X0, #0x8000, LSL #16
    

    汇编指令对应的二进制为:

    1. 00 00 B0 D2 ->
    2. D2 B0 00 00 ->
    3. 11010010 10110000 00000000 00000000 ->
    4. 1 10 100101 01 1000 0000 0000 0000 00000

    看其 hw 对应的位是 01,所以需要将 0x8000左移 1*16 位,得到 0x80000000。

    hw 表示的是左移的位数,为 16 * (0~3)。

    MOV (register)

    MOV 可以将寄存器的值赋值给另一个寄存器。

    Rm 与 Rd 都占据了5位,刚好可以描述所有的寄存器,MOV ,

    shift 有2位,这里固定是零值。imm6 与 Rn 也都是固定的值。

    MOV 有个别名指令,ORR,它可以用到 shift,imm6,Rn的值。

    看一个指令,MOV X0, X1

    E0 03 01 AA                   MOV             X0, X1
    

    汇编指令对应的二进制为:

    1. E0 03 01 AA ->
    2. AA 01 03 E0 ->
    3. 10101010 00000001 00000011 11100000 ->
    4. 1 01 01010 00 0 00001 000000 11111 00000

    所以,Rd 的值是 0,表示 X0 寄存器,Rm 的值是1,表示 X1 寄存器。

    顺便说一下 ORR 指令:

    是将寄存器中值按位做“或”操作。

    ORR , , {, #}

    Xm还可以做移位操作,具体移动多少位由 imm6 决定,怎么移动由 shift 决定。

    MOVK

    由于ARM64指令集是定长的4字节指令,这就决定了它无法在指令里面描述一个任意的数字,比如:0x123456789,这个就无法在指令中表示。

    那么,当我们在程序中使用到这个数字的时候,arm64指令集是如何处理的呢?

    我们写一个例子看看:

    1. uint64_t num = 0x123456789abc;
    2. printf("num = %llx\n", num);

    查看汇编代码:

    1. .text:00000000000008AC 81 57 93 D2 MOV X1, #0x9ABC
    2. .text:00000000000008B0 00 00 00 90 ADRP X0, #aNumLlx@PAGE ; "num = %llx\n"
    3. .text:00000000000008B4 01 CF AA F2 MOVK X1, #0x5678,LSL#16
    4. .text:00000000000008B8 00 00 24 91 ADD X0, X0, #aNumLlx@PAGEOFF ; "num = %llx\n"
    5. .text:00000000000008BC 81 46 C2 F2 MOVK X1, #0x1234,LSL#32

    我们只看 X1 相关的指令,它分为3个步骤:

    1. MOV X1, #0x9ABC
    2. MOVK X1, #0x5678,LSL#16
    3. MOVK X1, #0x1234,LSL#32

    通过数据的拼接来达成目标,非常的合理。

  • 相关阅读:
    044Node.js后端mysql、sqlite数据库和file文件数据读写封装方案
    为你的网站加上和风天气插件
    这么回答【循环依赖】助力轻松拿下阿里P6
    性能测试-如何进行监控设计
    MyBatis处理表字段和实体类属性名不一致的情况及多对一映射关系的处理
    C语言:初始指针(1)
    826. 单链表
    Html第4集:对象定义、typeof、instanceof、undefine
    什么是 XML?使用IntelliJ IDEA 创建一个简单的 xml 文件
    Jmeter进阶使用指南-使用断言
  • 原文地址:https://blog.csdn.net/a5right/article/details/136649147