ARM的movw指令是如何映射到机器码的?

3

我目前正在尝试了解ARM上的movw指令是如何工作的,以便能够十六进制编辑库并更改使用该指令设置的值。

该库呈现的代码如下(来自objdump的输出):

[...]
29c4:   f44f 71f0   mov.w   r1, #480    ; 0x1e0
[...]

我想做的就是弄清楚"f44f 71f0"中0x1e0 / 480是如何表示的。我已经查阅了网络上的相关资料,包括http://blogs.arm.com/software-enablement/251-how-to-load-constants-in-assembly-for-arm-architecture/,我认为我理解了movw如何工作以及它的限制;但我仍然不明白指令地图上显示的值是如何映射到实际的二进制代码的。如果您能提供任何有关此问题的文档或见解,将不胜感激 :)
2个回答

2

对于ARM,指令的描述在ARM ARM,ARM体系结构参考手册中。请访问http://infocenter.arm.com,然后在左侧找到“architecture”,再选择所需的架构。这是一个Thumb2指令,因此您需要armv7-m。

看起来这是T2编码。

11110i00010S11110... 

你的指令中i和S都是零。imm3是12到14位,imm8是7到0位。

0 111 0001 11110000

所以你的imm3是0b111,imm8是0b11110000

然后你看一下thumb指令部分中的修改立即数

i ... imm3 ... abcdefgh 其中abcdefgh是imm8位,你的i:imm3:a位,5位是0b11111

所以你在表格中查找,得到右侧的imm8左移1位

00000000 00000000 00000001 bcdefgh0
00000000 00000000 00000001 11100000

这是0x000001E0。

Arm对其指令的文档记录比大多数公司都要好。


非常感谢!通过您的解释以及对架构参考手册的一些阅读,我已经理解了它,并且能够编辑我所需要的内容 :) - user1176415

2
这是来自ARM架构参考手册的MOV T2编码
11110 i 0 0010 S 1111 0 imm3 rd imm8

d = UInt(Rd); 
setflags = (S == ‘1’); 
(imm32, carry) = ThumbExpandImm_C(i:imm3:imm8, APSR.C);
if d IN {13,15} then UNPREDICTABLE;

因为你的模式是

      i        S        imm3  rd   imm8
11110 1 0 0010 0 1111 0 111   0001 11110000

你有 i=1, S=0, imm3=111, imm8=11110000



通过检查 ThumbExpandImm_C() 所做的事情,您将了解这些值如何变为 0x1e0

// ThumbExpandImm_C()
// ==================
(bits(32), bit) ThumbExpandImm_C(bits(12) imm12, bit carry_in)
if imm12<11:10> == ‘00’ then
    case imm12<9:8> of
        when ‘00’
            imm32 = ZeroExtend(imm12<7:0>, 32);
        when ‘01if imm12<7:0> == ‘00000000’ then UNPREDICTABLE;
            imm32 = ‘00000000’ : imm12<7:0> : ‘00000000’ : imm12<7:0>;
        when ‘10if imm12<7:0> == ‘00000000’ then UNPREDICTABLE;
            imm32 = imm12<7:0> : ‘00000000’ : imm12<7:0> : ‘00000000’;
        when ‘11if imm12<7:0> == ‘00000000’ then UNPREDICTABLE;
            imm32 = imm12<7:0> : imm12<7:0> : imm12<7:0> : imm12<7:0>;
            carry_out = carry_in;
else
    unrotated_value = ZeroExtend(‘1’:imm12<6:0>, 32);                 <--- a
    (imm32, carry_out) = ROR_C(unrotated_value, UInt(imm12<11:7>));   <--- b
return (imm32, carry_out);



我们的imm12 = i:imm3:imm8 (1:111:11110000) = 1111 1111 0000
我们的值将通过行(a)和(b),因为最高的2位[11,10]是'11'

ZeroExtend(‘1’:imm12<6:0>, 32)表示您必须在[6..0]位之前添加'1'。所以该值变成了1:1110000 = 11110000 (a)
ROR_C(unrotated_value, UInt(imm12<11:7>))右旋转[11:7]=11111=31,这与左旋转1相同。(b)

因此,结果值为1 1110 0000 (a shifted by b) = 0x1e0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接