我正在尝试为 C++ 中的 hack 汇编语言创建一个反汇编程序。现在我的问题在于将 16 位二进制转换回 A 指令。在检查操作码(第一位)为 0 后,我必须将其后的其他 15 位转换回前面带有“@”的十进制。转换一直进行到 000001111111111 并输出“@1023”,但 000011111111111更高版本仅输出“@2559”。这是到目前为止的代码
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int BtoA (int n)
{
int num = n;
int decimal = 0;
int base = 0;
int tmp = num;
while (tmp != 0)
{
int last_dig = tmp % 10;
tmp /= 10;
decimal += last_dig * pow(2, base);
base++;
}
return decimal;
}
int main()
{
cout << "Welcome to the Hack Disassembler!\n";
int opCode;
int aIns;
cout << "\nIs the OP-Code 1 or 0? ";
cin >> opCode;
if (opCode == 0)
{
cout << "\nWhat are the other 15 bits? ";
cin >> aIns;
cout << "\nThat A Instruction is @" << BtoA(aIns) << "!\n";
}
}
尝试将变量
aIns
更改为键入 std::string
。如果是int
类型,超过std::numeric_limits<int>::max()
就会溢出,对于32位整数来说是2'147'483'647
。那是一个 10 位数字。当您添加第 11 位数字时,您会得到 11'111'111'111
,即溢出。
// main.cpp
#include <iostream>
#include <stdexcept>
#include <string>
int bitstring_to_int(std::string const& s)
{
if (s.empty())
throw std::invalid_argument(
'"' + s + "\" is empty. "
"Instructions must have at least 1 bit.");
if (s.length() > 15)
throw std::invalid_argument(
'"' + s + "\" is too wide. "
"Instructions can have at most 15 bits.");
for (auto const& c : s)
if (c != '0' && c != '1')
throw std::invalid_argument(
'"' + s + "\" contains invalid character(s). "
"It should be composed entirely of '0`s and '1's.");
int n{};
int bit{ 1 };
for (auto i{ s.length() }; i--; bit <<= 1u)
if (s[i] == '1')
n |= bit;
return n;
}
int main()
{
std::cout << "Welcome to the Hack Disassembler!\n";
int opCode;
std::string aIns;
std::cout << "\nIs the OP-Code 1 or 0? ";
std::cin >> opCode;
if (opCode == 0)
{
std::cout << "\nWhat are the other 15 bits? ";
std::cin >> aIns;
std::cout << "\nThat A Instruction is @" << bitstring_to_int(aIns) << "!\n";
}
}
// end file: main.cpp
Welcome to the Hack Disassembler!
Is the OP-Code 1 or 0? 0
What are the other 15 bits? 111111111111111
That A Instruction is @32767!