【发布时间】:2014-12-21 23:28:32
【问题描述】:
我正在为一个类项目使用 Javascript(特别是 Typescript)编写客户端 Python 字节码解释器。解析字节码一直很好,直到我尝试了一个负数。
在 Python 中,marshal.dumps(2) 给出 'i\x02\x00\x00\x00',marshal.dumps(-2) 给出 'i\xfe\xff\xff\xff'。这是有道理的,因为 Python 使用至少 32 位精度的二进制补码来表示整数。
在我的 Typescript 代码中,我使用等效于 Node.js 的 Buffer 类(通过名为 BrowserFS 的库,而不是 ArrayBuffers 等)来读取数据。当我看到字符“i”(即buffer.readUInt8(offset) == 105,表示接下来是一个int)时,我在下一个偏移量上调用readInt32LE 以读取一个little-endian 有符号长(4 个字节)。这适用于正数,但不适用于负数:对于 1,我得到“1”,但对于“-1”,我得到类似“-272777233”的东西。
我猜 Javascript 表示 64 位的数字(浮点数?)。因此,似乎以下应该可以工作:
var longval = buffer.readInt32LE(offset); // reads a 4-byte long, gives -272777233
var low32Bits = longval & 0xffff0000; //take the little endian 'most significant' 32 bits
var newval = ~low32Bits + 1; //invert the bits and add 1 to negate the original value
//but now newval = 272826368 instead of -2
我尝试了很多不同的方法,但我已经坚持了好几天。我不知道如何使用 Javascript/Typescript 从二进制编组字符串中恢复 Python 整数的原始值。此外,我认为我深深误解了位的工作原理。任何想法都会在这里受到赞赏。
一些更具体的问题可能是:
- 为什么
buffer.readInt32LE可以用于正整数而不是负整数? - 我是否使用正确的方法来获取“最重要”或“最低”的 32 位(即
& 0xffff0000是否按照我的想法工作?) - 独立但相关:在一个实际的“长”数字中(即比“-2”长),我认为有一个符号位和一个幅度,我认为这个信息存储在“最高”2位数字(即
number & 0x000000ff?)——这是正确的思考方式吗?
【问题讨论】:
-
BrowserFS 代码的真正简化版本适用于负值。您可以发布四次调用
readUInt8的输出以验证您正在阅读预期的序列FE FF FF FF吗? -
这是问题的很大一部分——我没有得到预期的序列。相反,对于 -2 我得到: ef bf bd ef
-
似乎您只是在读取流的错误部分,或者 Python 没有使用您认为的数字格式。我认为没有任何合理的按位运算序列可以将
EF BF BD EF变成-2。 -
问题是,我正在使用
a = 2, b = -2的编译字节码进行测试,以此类推几个数字。正数是正确的,以及整个“代码对象”结构。唯一不正确的是负数值。所以我不知道如何在不搞乱其他所有内容的情况下更改我在流中阅读的位置。
标签: javascript python typescript bit-manipulation number-formatting