В настоящее время я пытаюсь написать виртуальную машину Ninja, задача, которая была дана мне в качестве упражнения. Код операции и значение сохраняются в виде 32-битного целого числа без знака, где первые 8 бит являются кодом операции, а остальные — значением. Чтобы справиться с отрицательным значением, я использую макрос, данный мне в упражнении
#define SIGN_EXTEND(i) ((i) & 0x00800000 ? (i) | 0xFF000000 : (i))
Однако при попытке получить код операции
unsigned int i = (PUSHC << 24) | SIGN_EXTEND(-2);
(где PUSHC
равно 1
)
с помощью побитового AND
, как показано здесь ->
int opcode = (i>>24)&0xff
мой результат — 255
, хотя этот метод извлечения работает, когда значение положительное, и в этих случаях воспроизводит правильный код операции.
Исследуя это, я нашел «Как получить значение из непосредственной части 32-битной последовательности в C?», который, по-видимому, имеет дело с тем, что я спрашиваю, однако ответ, данный в этом вопросе, — это именно то, что я делаю, кто-нибудь знает больше?
SIGN_EXTEND
похоже, что он предназначен для использования в декодировании, чтобы взять 24 бита, которые были извлечены из инструкции, и преобразовать их в 32-битное целое число со знаком. Похоже, он не предназначен для использования в кодировании. Для кодирования IMMEDIATE(x)
, по-видимому, предназначен для этого. Учитывая 32-битное целое число со знаком, он создает 24-битное целое число со знаком, при условии, что значение подходит.
Так:
unsigned int i = (PUSHC << 24) | SIGN_EXTEND(-2);
должно быть:
unsigned int i = (PUSHC << 24) | IMMEDIATE(-2);
Спасибо, это действительно решило мою проблему. Я пытался заранее изучить, как работают макросы, но, похоже, я еще не совсем в них разобрался. Я был бы признателен, если бы кто-нибудь мог объяснить, что именно происходит, когда вы вводите в них значение. #define IMMEDIATE(x) ((x) & 0x00FFFFFF)
и #define SIGN_EXTEND(i) ((i) & 0x00800000 ? (i) | 0xFF000000 : (i))
Этот макрос, похоже, преобразует отрицательные значения 24-bit в 32-bit. Так что
SIGN_EXTEND(-2)
использует его не по назначению