我在理解这段代码时遇到问题。我所知道的是,我们已将代码传递到汇编器中,该汇编器已将代码转换为“字节代码”。现在我有一个虚拟机应该可以读取这段代码。该函数应该读取第一个字节代码指令。我不明白这段代码中发生了什么。我想我们正在尝试读取这个字节码,但不明白它是如何完成的。
static int32_t bytecode_to_int32(const uint8_t *bytecode, size_t size)
{
int32_t result;
t_bool sign;
int i;
result = 0;
sign = (t_bool)(bytecode[0] & 0x80);
i = 0;
while (size)
{
if (sign)
result += ((bytecode[size - 1] ^ 0xFF) << (i++ * 8));
else
result += bytecode[size - 1] << (i++ * 8);
size--;
}
if (sign)
result = ~(result);
return (result);
}
这段代码写得有些糟糕,一行中有很多操作,因此包含各种潜在的错误。它看起来很脆。
-
bytecode[0] & 0x80
只需读取 MSB 符号位,假设它是 2 的补码或类似的,然后将其转换为布尔值。
- 该循环从最高有效字节向后迭代到最低有效字节。
- 如果符号为负,代码将执行数据字节与 0xFF 的异或。基本上反转数据中的所有位。 XOR 的结果是
int
.
- 然后数据字节(或上述 XOR 的结果)被移位
i * 8
位向左。数据总是隐式提升为int
,所以万一i * 8
碰巧给出的结果大于INT_MAX
,这里有一个巨大的未定义行为错误。转换为更安全的做法uint32_t
在移位之前,进行移位,然后转换为有符号类型。
- 所结果的
int
被转换为int32_t
- 这些可以是相同类型或不同类型,具体取决于系统。
- i 加 1,size 减 1。
- 如果符号为负,则
int32_t
被反转为符号扩展的某个 2 的补码负数,并且所有数据位再次反转。除了通过左移移入的所有零也被替换为 1。这是有意还是无意,我无法判断。例如,如果你从类似的事情开始0x0081
你现在有类似的东西0xFFFF01FF
。我不知道这种格式有何意义。
我的看法是bytecode[size - 1] ^ 0xFF
(这相当于~
)用于切换数据位,以便稍后在以下情况下切换回其原始值:~
稍后调用。一名程序员has用评论记录这些技巧,如果它们接近能力的话。
无论如何,不要使用此代码。如果目的只是交换 4 字节整数的字节顺序(字节序),则必须从头开始重写此代码。
正确的做法是:
static int32_t big32_to_little32 (const uint8_t* bytes)
{
uint32_t result = (uint32_t)bytes[0] << 24 |
(uint32_t)bytes[1] << 16 |
(uint32_t)bytes[2] << 8 |
(uint32_t)bytes[3] << 0 ;
return (int32_t)result;
}
任何比上述更复杂的代码都是高度可疑的代码。我们不必担心符号是特殊情况,上面的代码保留了原始的符号格式。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)