简体   繁体   English

通过移位、反转和加 +/- 1 构造十六进制数

[英]Constructing a hex number by shifting, inverting and adding +/- 1

I'm trying to save a number 0xFD00 in a register (MIC-1 architecture).我正在尝试将数字0xFD00保存在寄存器中(MIC-1 架构)。 There are registers:有寄存器:

  • 0 0
  • +1 +1
  • -1 -1
  • AMASK: 0x0FFF AMASK:0x0FFF
  • SMASK: 0x00FF面具:0x00FF

I can do left, right bit shifts and inverses.我可以进行左移、右移和反转。 It is also possible to add values like SMASK + SMASK or AMASK + (-1).也可以添加 SMASK + SMASK 或 AMASK + (-1) 等值。 I can get 0xF000 with inverse(AMASK), but I'm not sure how to get 0xFD00 without too many steps.我可以通过逆(AMASK)获得 0xF000,但我不确定如何在没有太多步骤的情况下获得 0xFD00。

0xFD is 0b11111101 . 0xFD 是0b11111101 So it has a bunch of contiguous bits, and one other stay set bit.所以它有一堆连续的位,还有一个保持设置位。 So one simple way would be所以一种简单的方法是

  • start with all-ones ( -1 , ~0 , or 0 - 1 )以全 1 开头( -1~00 - 1
  • left shift by 2 to get ...11111100左移 2 得到...11111100
  • add 1 to get ...11111101 (0x...FD)加 1 得到...11111101 (0x...FD)
  • shift to the top of the register, shifting in low 0s and shifting out the high 1s, leaving the 0xFD at the top, with 8 low zeros.移到寄存器的顶部,移入低 0 并移出高 1,将0xFD留在顶部,有 8 个低零。

I don't know MIC-1, but from your description it sounds like it can do those steps.我不知道 MIC-1,但从你的描述看来它可以完成这些步骤。 If it can only shift by 1 position at a time, it will take 2 + 8 total shift instructions.如果一次只能移位 1 个 position,则总共需要 2 + 8 个移位指令。 There might be other ways to construct this constant more efficiently, maybe with something I'm not thinking of, or maybe with some capability the machine has.可能还有其他方法可以更有效地构造这个常数,也许是我没有想到的东西,或者机器有一些能力。


Taking advantage of AMASK / SMASK and the way add / sub carry-propagation can flip a sequence of 1 / 0 bits respectively, along with Aki's observation that ~0xfd00 = 0x02ff , we can do the following:利用 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)

See https://catonmat.net/low-level-bit-hacks for a nice intro to the kinds of shenanigans you can get up to with bitwise operations.请参阅https://catonmat.net/low-level-bit-hacks以了解您可以使用按位运算处理的各种恶作剧。 (Although many of those also require AND, OR, or XOR. eg clearing the lowest set bit via x &= (x-1) ) (尽管其中许多还需要 AND、OR 或 XOR。例如,通过x &= (x-1)清除最低设置位)


(Related: What are the best instruction sequences to generate vector constants on the fly? for x86 SIMD vectors: similar problem, you can generate -1 on the fly cheaply without loading from memory, and feed it through various other instructions like left shift, (SSSE3) absolute value. But only worth doing for short sequences, otherwise just load from memory or mov-immediate to integer regsiters and movd xmm0, eax ) (相关:动态生成向量常量的最佳指令序列是什么?对于 x86 SIMD 向量:类似的问题,您可以在不从 memory 加载的情况下廉价地动态生成-1 ,并通过各种其他指令(如左移)输入它, (SSSE3)绝对值。但只值得为短序列做,否则只需从 memory 或 mov-immediate 加载到 integer regsiters 和movd xmm0, eax


Hex is just a way to represent numbers in text, eg ASCII.十六进制只是在文本中表示数字的一种方式,例如 ASCII。 You could call it a serialization format.您可以将其称为序列化格式。

0xFD00 is just another way to write 64768 (base 10) or 0b1111110100000000 (base 2). 0xFD00只是另一种写入64768 (基数 10)或0b1111110100000000 (基数 2)的方式。 So you're just constructing a number in a register out of shifts and inc/dec.因此,您只是在移位和 inc/dec 的寄存器中构造一个数字 Assuming your bit-shifts multiply / divide by 2, not 10 or 16, those are binary operations so this is a binary number.假设您的位移乘以/除以 2,而不是 10 或 16,这些是二进制操作,所以这是一个二进制数。 It's just convenient to express the desired binary number in a compact format like hex, but at no point to you actually need hex, like a string of base-16 ASCII digits.以像十六进制这样的紧凑格式表示所需的二进制数很方便,但在任何时候你都不需要十六进制,就像一串base-16 ASCII数字。

It's not a "hex number" when you construct it in a register, it's just a number.当您在寄存器中构造它时,它不是“十六进制数”,它只是一个数字。 If anything it's binary.如果有的话,它是二进制的。

The inverse of 0xFD00 == 0b00000010 11111111 = 0x02ff 0xFD00 的倒数 == 0b00000010 11111111 = 0x02ff

This can be achieved with the SMASK = 0x00FF * 3 + 2, or simply with SMASK |这可以通过 SMASK = 0x00FF * 3 + 2 或简单地使用 SMASK | 来实现。 (1 << 9), if that's available. (1 << 9),如果可用的话。

a = smask
b = smask << 1
a = a + b
a++
a++
return ~a

Assuming left shift just drops the bits shifted out of the 16-bit word:假设左移只是删除移出 16 位字的位:

t = ~SMASK    // 0xff00
return t + (t << 1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM