我正在尝试将数字0xFD00保存在寄存器中(MIC-1 架构)。有寄存器:
- 0
- +1
- -1
- AMASK:0x0FFF
- 面具:0x00FF
我可以进行左移、右移和反转。也可以添加 SMASK + SMASK 或 AMASK + (-1) 等值。我可以通过逆(AMASK)获得 0xF000,但我不确定如何在没有太多步骤的情况下获得 0xFD00。
我正在尝试将数字0xFD00保存在寄存器中(MIC-1 架构)。有寄存器:
我可以进行左移、右移和反转。也可以添加 SMASK + SMASK 或 AMASK + (-1) 等值。我可以通过逆(AMASK)获得 0xF000,但我不确定如何在没有太多步骤的情况下获得 0xFD00。
迄今为止最有效的序列是@Falk Hüffner 的回答,3 次操作。(尽管它涉及的 a+
不添加 +1 或 -1 或自身的值)。
该答案显示了一种方法,该方法采用问题标题中明确提到的 4 种操作。
0xFD 是0b11111101
. 所以它有一堆连续的位,还有一个杂散设置位。一种简单的方法是
-1
、、~0
或0 - 1
)开头...11111100
...11111101
(0x...FD)0xFD
8 个低零留在顶部。我不知道 MIC-1,但从你的描述看来它可以完成这些步骤。如果一次只能移位 1 个位置,则总共需要 2 + 8 个移位指令。可能还有其他方法可以更有效地构造这个常数,也许是我没有想到的东西,或者机器有一些能力。
利用 AMASK / SMASK 和 add / sub carry-propagation 的方式可以分别翻转 1 / 0 位的序列,连同 Aki 的观察~0xfd00
= 0x02ff
,我们可以执行以下操作:
initial AMASK = 0x00FF
AMASK += 1 (0x0100)
AMASK += AMASK (0x0200) (left shift)
AMASK += SMASM (0x02FF)
NOT AMASK (0xFD00)
请参阅https://catonmat.net/low-level-bit-hacks,了解您可以使用按位运算处理的各种恶作剧。(尽管其中许多还需要 AND、OR 或 XOR。例如,通过 清除最低设置位x &= (x-1)
)
(相关:动态生成向量常量的最佳指令序列是什么?对于 x86 SIMD 向量:类似的问题,您可以-1
在不从内存加载的情况下廉价生成动态,并通过各种其他指令(如左移)提供它,(SSSE3 ) 绝对值。但只值得为短序列做,否则只需从内存或 mov-immediate 加载到整数寄存器和movd xmm0, eax
)
十六进制只是在文本中表示数字的一种方式,例如 ASCII。 您可以将其称为序列化格式。
0xFD00
只是另一种写法64768
(base 10)或0b1111110100000000
(base 2)。因此,您只是在移位和 inc/dec 的寄存器中构造一个数字。假设您的位移乘以/除以 2,而不是 10 或 16,这些是二进制操作,所以这是一个二进制数。以像十六进制这样的紧凑格式表示所需的二进制数很方便,但在任何时候你都不需要十六进制,就像一串 base-16 ASCII 数字。
当您在寄存器中构造它时,它不是“十六进制数”,它只是一个数字。 如果有的话,它是二进制的。
假设可以使用两个寄存器进行加法,而不仅仅是一个常数,并且左移只会删除从 16 位字中移出的位:
t = ~SMASK // 0xff00
return t + (t << 1)
如果可以通过任意常数而不只是 1 进行移位,则另一种选择是
t = SMASK
t += -1
t += -1
t <<= 8
0xFD00 的倒数 == 0b00000010 11111111 = 0x02ff
这可以通过 SMASK = 0x00FF * 3 + 2 或简单地使用 SMASK | 来实现。(1 << 9),如果可用的话。
a = smask
b = smask << 1
a = a + b
a++
a++
return ~a