assembly - GNU Arm 汇编器将 ORR 更改为 MOVW

标签 assembly arm gnu

我正在组装以下汇编器:

.syntax unified
.cpu cortex-m4
.thumb

.section  .text

orr r1, #12800
orr r1, #12801

本质上,只是两个 OR 指令。如果我用 objdump 查看结果,我得到:

bla.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   f441 5148   orr.w   r1, r1, #12800  ; 0x3200
   4:   f243 2101   movw    r1, #12801  ; 0x3201

第二个OR悄然变成了MOVW!汇编程序运行如下:arm-none-eabi-gcc -g -Wall -c bla.s并且它没有显示任何警告。

as的版本是 GNU assembler version 2.29.51 (arm-none-eabi) using BFD version (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 2.29.51.20171128 ,在 OSX 上运行。

知道为什么第二个 OR 变成了 MOV 吗?

最佳答案

.syntax unified
.cpu cortex-m4
.thumb

.section  .text

orr r1, #12800
orr r1, #12801

arm-none-eabi-as --version GNU 汇编器 (GNU Binutils) 2.29.1 版权所有 (C) 2017 自由软件基金会, Inc. 该程序是免费软件;您可以根据以下条款重新分发它 GNU 通用公共(public)许可证版本 3 或更高版本。 该程序绝对没有任何保证。 该汇编器配置为“arm-none-eabi”目标。

构建

arm-none-eabi-as so.s -o so.o
arm-none-eabi-objdump -D so.o

so.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   f441 5148   orr.w   r1, r1, #12800  ; 0x3200
   4:   f243 2101   movw    r1, #12801  ; 0x3201

Jester 在评论中给出了答案,你应该投票。

2.30 几天前刚刚发布。它也会产生相同的结果。

追溯起来,问题是从 2.27.1 到 2.28 之间开始的。该版本的 tc-arm.c 更改与添加了 armv8m 相关。 (Cortex-m23 和 cortex-m33)

这是气体中的错误

  /* MOV accepts both Thumb2 modified immediate (T2 encoding) and
 UINT16 (T3 encoding), MOVW only accepts UINT16.  When
 disassembling, MOV is preferred when there is no encoding
 overlap.
 NOTE: MOV is using ORR opcode under Thumb 2 mode.  */
  if (((newval >> T2_DATA_OP_SHIFT) & 0xf) == T2_OPCODE_ORR
  && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2_v8m)
  && !((newval >> T2_SBIT_SHIFT) & 0x1)
  && value >= 0 && value <=0xffff)
{
  /* Toggle bit[25] to change encoding from T2 to T3.  */
  newval ^= 1 << 25;
  /* Clear bits[19:16].  */
  newval &= 0xfff0ffff;
  /* Encoding high 4bits imm.  Code below will encode the
     remaining low 12bits.  */
  newval |= (value & 0x0000f000) << 4;
  newimm = value & 0x00000fff;
}

ARM 文档已有 10 多年的历史,没有人指出它在这些指令方面存在错误。

是的,有一个未使用的 ORR 编码用作 MOV 编码,这在指令集设计中很典型,并不罕见。无论如何,形状,或 这是否意味着 MOV 是 ORR。此外,一旦错误地认为 MOV 是 ORR,就会选择其他 MOV 编码。我无语。

更糟糕的是,这种情况在发布的 Gas 版本中已经存在了近一年了。这怎么可能?

之所以可能,部分原因在于 GCC 更清楚地将其编码为两个单独的指令。

orr r1,#0x3200
orr r1,#0x0001

因此,除了 gnu 世界中明显缺乏同行评审之外,要发现这一点,就需要人类尝试这一点。 ARM 立即编码规则比拇指规则更容易记住。人们总是在与立即数作斗争,这是 RISC 指令集的野兽本质。现在应该有人已经做到了这一点,现在已经有人做到了。

尝试硬件 cortex-m7

测试.s

.cpu cortex-m7
.syntax unified
.thumb

.thumb_func
.globl test1
test1:
    orr r0,#0x3200
    bx lr

.thumb_func
.globl test2
test2:
    orr r0,#0x3201
    bx lr

运行并打印结果

hexstring(test1(0x0000));
hexstring(test2(0x0000));
hexstring(test1(0x00FE));
hexstring(test2(0x00FE));

天然气

arm-none-eabi-as --version
GNU assembler (GNU Binutils) 2.30

结果

0800005c <test1>:
 800005c:   f440 5048   orr.w   r0, r0, #12800  ; 0x3200
 8000060:   4770        bx  lr

08000062 <test2>:
 8000062:   f243 2001   movw    r0, #12801  ; 0x3201
 8000066:   4770        bx  lr

输出

00003200 
00003201 
000032FE 
00003201

MOV 是 MOV,不是 ORR。

您在 gnu 汇编器中发现了一个非常令人讨厌的错误,我建议您归档此错误。尽管这个错误非常明显,但我很好奇会发生什么。我过去曾提交过其他错误,但他们只是找借口而不是修复,并将错误保留在原处。如果您选择提交此问题,请将票证链接作为评论发布,以便我们都可以看到他们对此做了什么。

bada43421274615d0d5f629a61a60b7daa71bc15 tc-arm.c:23596 是正确的提交和位置。

关于assembly - GNU Arm 汇编器将 ORR 更改为 MOVW,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48561243/

相关文章:

assembly - 将相同的字节移动到两个不同地址之间的每个地址?

assembly - 访问汇编中缓冲区的第一个字节?

c - 重新映射堆栈成功,但随后引发 SEGV

c - malloc 何时在裸机环境中返回 NULL?

linux - 无法通过 0x80 在 Linux 中打开文件

android - 任何带有 NEON 指令集的 Android 平板电脑?

debugging - 如何使用 OpenOCD 同时与两 block STM32 板通信?

PHP:在 GNU MP 中获取 "number of bits per limb"

java - 在java中读取.po文件时出错

c# - iTextSharp DLL 是否可以免费使用并与我的 Web 应用程序项目一起重新分发?