【问题标题】:Sign extend a register to 64-bit (set all bits = sign bit) in Thumb mode在 Thumb 模式下将寄存器符号扩展为 64 位(设置所有位 = 符号位)
【发布时间】:2021-09-13 01:04:27
【问题描述】:

我正在为 ARM7TDMI(ARMv4T 架构)使用汇编程序。我正在使用 Thumb 模式,因为 ROM 具有 16 位总线 (GBA)。我想对一个 32 位寄存器进行符号扩展,以获取另一个寄存器,其中所有位都设置为源寄存器第 31 位的副本。符号扩展的寄存器是高位寄存器,特别是 R9。

我目前正在使用这个:

        mov     r0,r9
        mvn     r0,r0           @ sign bit needs to be inverted due to
                                @ the silly ARM carry convention
        add     r0,r0           @ copy sign bit to carry
        sbc     r0,r0           @ sign-extend R9

但这需要 4 条指令。有没有更短的方法?

【问题讨论】:

  • 试试mov r1, r9; asrs r1, r1, #32
  • @fuz:请注意,您只需要移动#31,因此您可以在超出范围移位计数的工作方式与 ARM 不同的其他 ISA 上执行相同的操作。原来的符号位成为新的 LSB,其他 31 位是它的副本。
  • @fuz 哦,天哪,我完全错过了那个指令/变体。正如您可能知道的那样,我仍然习惯于 Thumb 指令集。我的印象是“每一位操作都需要一个寄存器”。顺便说一句,如果这是一个答案,我会同意的。是的,我更喜欢 31。
  • 您可以随时询问编译器,例如int64_t sext(int32_t x){ return x; }。 godbolt.org/z/EErn4sY5a 编译为 asrs r1, r0, #31 / bx lr

标签: assembly arm twos-complement sign-extension


【解决方案1】:

使用算术右移 31 或 32 将符号位作为 -1 或 0 复制到新寄存器中:

mov r1, r9       @ move to a low register to be usable as an operand
asrs r0, r1, #31 @ generate -1 or 0 in R0 depending on sign of R1

【讨论】:

  • 整体思路不错。 GNU 汇编器不接受asrs,只接受asr(我会说这是汇编器的一个陷阱,因为指令会更新标志)。我不需要浪费一个寄存器,所以我使用r0而不是r1。谢谢!
  • @PedroGimeno 使用.syntax unified 选择现代统一语法。我为asrs 选择了一个带有两个不同操作数的示例,以强调您不需要额外的指令即可在低位寄存器中同时获得 64 位值的高位和低位字。
  • 了解当您切换到统一语法时,您将需要更改您的其他汇编语言代码,否则它可能会中断。或者只是使用 asr 并完成它。硬件拇指指令设置标志它不是汇编程序。 15-20 年后,尽管 gnu 的人可以解决这个问题(或者我们中的一个人可以),这样对于不支持 thumb2 的目标的拇指来说,只允许 sub 或 subs、asr 或 asrs 等并完成它。
  • @old_timer 那么您希望代码根据选择的 CPU 类型产生不同的效果吗?我看不出这怎么会出错。
  • 非统一语法语言已经存在并且已经错了 20 年了?为什么在继续支持遗留支持的损坏的同时修复它会更糟?统一的语法是一个巨大的失败(就像我不尝试就可以想到的另外一两件事),并且使用gas肯定比不使用手写代码要糟糕得多。
猜你喜欢
  • 2017-04-14
  • 2021-07-21
  • 2015-11-06
  • 2011-01-17
  • 2015-06-24
  • 2023-03-14
  • 2023-03-11
  • 2011-10-26
  • 1970-01-01
相关资源
最近更新 更多