如何用手臂编码立即值?

时间:2013-07-20 15:07:04

标签: assembly arm

假设有一个这样的inst:

add  ip, ip, #0x5000

机器代码是

  

05 CA 8C E2

E2 8C CA 05 = 11100010100011001100 1010 00000101
imm = rotate_right(101B, 1010B*2) = 0x5000

但如果我们知道0x5000,我们怎么能得到101000000101?这是反向转换一对一的对应吗?感谢。

1 个答案:

答案 0 :(得分:7)

来自ARM ARM:

  

ADD添加了两个值。第一个值来自寄存器。第二个值可以是立即值或寄存器中的值,也可以在加法之前移位。

你所看到的直接价值正在转移。指令的第11:0位是移位器操作数 - 在您的情况下:0xA05

稍后在文档中,描述了寻址模式:

  

<shifter_operand>值是通过将8位立即值旋转(向右)到32位字中的任何偶数位位置而形成的。

因此,您的特定移位器操作数意味着0x05向右旋转(2 * 10)位。

如果你正在进行指令编码,你有几个选择。例如:

0xA05 // rotate 0x05 right by 20
0xB14 // rotate 0x14 right by 22
0xC50 // rotate 0x50 right by 24

我把它们编码为反汇编:

$ xxd -r > example
00 05 CA 8C E2 14 CB 8C E2 50 CC 8C E2
$ arm-none-eabi-objdump -m arm -b binary -D example

example:     file format binary


Disassembly of section .data:

00000000 <.data>:
   0:   e28cca05    add ip, ip, #20480  ; 0x5000
   4:   e28ccb14    add ip, ip, #20480  ; 0x5000
   8:   e28ccc50    add ip, ip, #20480  ; 0x5000

这是一个可以找到编码的简单程序:

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

int main(int argc, char **argv)
{
    uint32_t encode = strtoul(argv[1], NULL, 0);
    int rotate;

    for (rotate = 0; rotate < 32; rotate += 2)
    {
        // print an encoding if the only significant bits 
        // fit into an 8-bit immediate
        if (!(encode & ~0xffU))
        {
            printf("0x%X%02X\n", rotate/2, encode);
        }

        // rotate left by two
        encode = (encode << 2) | (encode >> 30);
    }
    return 0;
}

为您的案例运行示例:

$ ./example 0x5000
0xA05
0xB14
0xC50