安全地将 2 个字节转换为短字节
Safely convert 2 bytes to short
我正在为 Intel 8080 制作一个仿真器。其中一个操作码需要通过组合 b
和 c
寄存器(均为 1 字节)的 16 位地址。我有一个寄存器彼此相邻的结构。我结合两个寄存器的方式是:
using byte = char;
struct {
... code
byte b;
byte c;
... code
} state;
...somewhere in code
// memory is an array of byte with a size of 65535
memory[*reinterpret_cast<short*>(&state.b)]
我想我可以 OR
把它们放在一起,但是那行不通。
short address = state.b | state.c
我尝试这样做的另一种方法是创建一个短片,然后分别设置 2 个字节。
short address;
*reinterpret_cast<byte*>(&address) = state.b;
*(reinterpret_cast<byte*>(&address) + 1) = state.c;
是否有 better/safer 方法来实现我想要做的事情?
short j;
j = state.b;
j <<= 8;
j |= state.c;
如果您需要相反的字节顺序,请反转 state.b
和 state.c
。
short address = ((unsigned short)state.b << 8) | (unsigned char)state.c;
这就是便携方式。您使用 reinterpret_cast
的方式并没有那么糟糕,只要您了解它只适用于具有正确字节顺序的体系结构。
正如其他人所提到的,存在字节序问题,但您也可以使用联合来操纵内存,而无需进行任何移位。
示例代码
#include <cstdint>
#include <iostream>
using byte = std::uint8_t;
struct Regs
{
union
{
std::uint16_t bc;
struct
{
// The order of these bytes matters
byte c;
byte b;
};
};
};
int main()
{
Regs regs;
regs.b = 1; // 0000 0001
regs.c = 7; // 0000 0111
// Read these vertically to know the value associated with each bit
//
// 2 1
// 5 2631
// 6 8426 8421
//
// The overall binary: 0000 0001 0000 0111
//
// 256 + 4 + 2 + 1 = 263
std::cout << regs.bc << "\n";
return 0;
}
示例输出
263
您可以使用:
unsigned short address = state.b * 0x100u + state.c;
使用乘法而不是移位可以避免与移动符号位等相关的所有问题
address
应该是 unsigned
否则你会导致超出范围的分配,并且你可能想使用 0 到 65535 作为你的地址范围,而不是 -32768 到 32767 .
我正在为 Intel 8080 制作一个仿真器。其中一个操作码需要通过组合 b
和 c
寄存器(均为 1 字节)的 16 位地址。我有一个寄存器彼此相邻的结构。我结合两个寄存器的方式是:
using byte = char;
struct {
... code
byte b;
byte c;
... code
} state;
...somewhere in code
// memory is an array of byte with a size of 65535
memory[*reinterpret_cast<short*>(&state.b)]
我想我可以 OR
把它们放在一起,但是那行不通。
short address = state.b | state.c
我尝试这样做的另一种方法是创建一个短片,然后分别设置 2 个字节。
short address;
*reinterpret_cast<byte*>(&address) = state.b;
*(reinterpret_cast<byte*>(&address) + 1) = state.c;
是否有 better/safer 方法来实现我想要做的事情?
short j;
j = state.b;
j <<= 8;
j |= state.c;
如果您需要相反的字节顺序,请反转 state.b
和 state.c
。
short address = ((unsigned short)state.b << 8) | (unsigned char)state.c;
这就是便携方式。您使用 reinterpret_cast
的方式并没有那么糟糕,只要您了解它只适用于具有正确字节顺序的体系结构。
正如其他人所提到的,存在字节序问题,但您也可以使用联合来操纵内存,而无需进行任何移位。
示例代码
#include <cstdint>
#include <iostream>
using byte = std::uint8_t;
struct Regs
{
union
{
std::uint16_t bc;
struct
{
// The order of these bytes matters
byte c;
byte b;
};
};
};
int main()
{
Regs regs;
regs.b = 1; // 0000 0001
regs.c = 7; // 0000 0111
// Read these vertically to know the value associated with each bit
//
// 2 1
// 5 2631
// 6 8426 8421
//
// The overall binary: 0000 0001 0000 0111
//
// 256 + 4 + 2 + 1 = 263
std::cout << regs.bc << "\n";
return 0;
}
示例输出
263
您可以使用:
unsigned short address = state.b * 0x100u + state.c;
使用乘法而不是移位可以避免与移动符号位等相关的所有问题
address
应该是 unsigned
否则你会导致超出范围的分配,并且你可能想使用 0 到 65535 作为你的地址范围,而不是 -32768 到 32767 .