Просто наткнулся на это в поисках чего-то другого, может быть, немного поздно, но, возможно, это будет полезно для кого-то еще. AFAIAC все программисты на С должны начинать программировать на ассемблере.
В любом случае расширение знака намного проще, чем в двух других предложениях. Просто убедитесь, что вы используете подписанные переменные, а затем используйте 2 смены.
</p>
<pre><code>short instr = state->mem[state->pc];
unsigned int reg = (instr >> 9) & 7; // 0b111
instr &= 0x1ff; // get lower 9 bits
instr = ((instr << 7) >> 7); // sign extend
state->regs[reg] = state->pc + instr;
Если переменная подписана, то компилятор C переводит >> в Arithmetic Shift Right, который сохраняет знак. Это поведение не зависит от платформы.
Итак, предполагая, что instr начинается с 0x1ff, тогда мы имеем, << 7 будет SL (Shift Left) значение, так что instr теперь 0xff80, тогда >> 7 будет ASR, так что instr теперь 0xffff.