arm movw指令如何映射到机器代码?

时间:2012-01-29 12:31:23

标签: assembly arm disassembly

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

该库提供如下代码(来自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 个答案:

答案 0 :(得分:2)

对于arm,ARM ARM,ARM架构参考手册中描述了这些指令。转到http://infocenter.arm.com,然后沿左边找到架构,然后找到你感兴趣的架构。这是一个thumb2指令,所以你想要armv7-m。

这看起来是编码T2

11110i00010S11110... 

我和S在你的指令中为零。 imm3是12到14位,imm8是7到0位。

0 111 0001 11110000

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

然后你看一下拇指指令部分

中修改后的立即常量

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

所以你在桌子上看一下,你在右侧移动了imm8 1

00000000 00000000 00000001 bcdefgh0
00000000 00000000 00000001 11100000

,即0x000001E0

Arm比大多数人更能记录他们的指令。

答案 1 :(得分:1)

这是 MOV T2编码(来自 ARM体系结构参考手册

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 ‘01’
            if imm12<7:0> == ‘00000000’ then UNPREDICTABLE;
            imm32 = ‘00000000’ : imm12<7:0> : ‘00000000’ : imm12<7:0>;
        when ‘10’
            if imm12<7:0> == ‘00000000’ then UNPREDICTABLE;
            imm32 = imm12<7:0> : ‘00000000’ : imm12<7:0> : ‘00000000’;
        when ‘11’
            if 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&lt; 6:0&gt;,32)表示您必须将'1'添加到[6..0]位。因此,该值变为1:1110000 = 11110000(a)
ROR_C(unrotated_value,UInt(imm12&lt; 11:7&gt;))确实向右旋转[11:7] = 11111 = 31,即same as rotate left by 1。 (b)

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