Что делает эта побитовая операция для эмуляции инструкции RRC

Я работаю над личным проектом, чтобы улучшить свои знания о том, как работает процессор. Итак, я делаю эмулятор Intel 8080, который представляет собой 8-битный микропроцессор.

В реализации инструкции RRC, пример:

case 0x0f: {    
  uint8_t x = state->a;    
  state->a = ((x & 1) << 7) | (x >> 1);    
  state->cc.cy = (1 == (x&1));    
}

Я не могу понять, как работает эта линия.

state->a = ((x & 1) << 7) | (x >> 1);

Я знаю, что он должен переместить все биты вправо на 1 позицию, но я не могу понять, как это сделать.

Я был бы признателен, если бы кто-нибудь мог предоставить мне пример того, что он на самом деле делает шаг за шагом.


  • state->a — это uint8_t, который эмулирует регистр Intel 8080 с именем A.

  • 0x0f — это шестнадцатеричное значение для RRC.

  • Пример предоставлен на этой странице.


person criw    schedule 27.09.2017    source источник
comment
Откуда вы знаете, что он должен переместить все биты вправо на 1 позицию?   -  person EOF    schedule 27.09.2017
comment
(x >> 1) - двигаем все правильно. ((x & 1) << 7) перемещение самого правого бита в крайнее левое положение. циклический сдвиг вправо на 8 бит.   -  person Eugene Sh.    schedule 27.09.2017
comment
x >> 1 сдвигает (беззнаковую) величину в x на один бит вправо, оставляя ноль в старшем бите. (x & 1) << 7) перемещает младший значащий бит в самый старший (оставляя нули в младших значащих битах). Комбинация | этих двух показателей достигла RRC.   -  person Jonathan Leffler    schedule 27.09.2017
comment
@JonathanLeffler @EugeneSh. Спасибо! Теперь я понял, проблема была в том, что я не понимал (x & 1) << 7). Если вы хотите, вы можете дать правильный ответ, чтобы я мог проголосовать за него.   -  person criw    schedule 27.09.2017
comment
@EOF копирует и вставляет ручное определение RRC для Intel 8080. Содержимое аккумулятора сдвигается на одну позицию вправо, при этом младший бит переносится в позицию старшего бита аккумулятора. Читая это сейчас, я вижу, что это также дает ответ на мой вопрос, но сначала я этого не понял.   -  person criw    schedule 27.09.2017


Ответы (1)


Давайте изучим шаги по порядку:

  • uint8_t x = state->a; Использовать временную переменную для текущего значения регистра A;
  • (x & 1) << 7 сместить младший бит в старший бит; (x & 1) — это значение младшего бита, поскольку все остальные биты x маскируются.
  • (x >> 1) сдвинуть остальные биты на одну позицию вправо (к младшим битам).
  • state->a = ((x & 1) << 7) | (x >> 1); объединить биты из предыдущих 2 шагов и сохранить как новое значение регистра A;
  • state->cc.cy = (1 == (x&1)); сохранить младший бит исходного значения в бит переноса (это бит, который был повернут в старший бит).

Результатом этих шагов является поворот 8 битов на один шаг вправо, при этом младший бит попадает во флаг переноса. справочная карта 8080 описывает это как Rotate Accumulator Right thru Carry.

Обратите внимание, что шаги можно упростить:

  • state->a = ((x & 1) << 7) | (x >> 1); совпадает с state->a = (x << 7) | (x >> 1);, потому что state->a это uint8_t.
  • state->cc.cy = (1 == (x&1)) совпадает с state->cc.cy = x & 1;
person chqrlie    schedule 27.09.2017
comment
Проблемным моментом для ОП является второй. Маска отсутствует во всем, кроме самой правой части. Кстати, я вообще не понимаю, зачем это делается при работе с 8-битной переменной... - person Eugene Sh.; 27.09.2017
comment
Спасибо за разъяснение! на самом деле это был второй пункт, который я не понял, и ссылка поможет мне с будущими инструкциями - person criw; 28.09.2017
comment
Интересно - сайт emulator101.com, на который ссылается OP, имеет как RRC, так и RAR. Код RAR копирует бит переноса в MSB вместо MSB. Мне было интересно, почему код RRC корректировал бит переноса, но было бы яснее, если бы младший бит был скопирован в бит переноса. - person Jonathan Leffler; 28.09.2017
comment
@JonathanLeffler: Я тоже озадачен: реализация на emulator101.com согласуется с документацией, на которую я ссылался, но кажется несовместимой с мнемоникой: RRC, Повернуть аккумулятор прямо через Carry и RAR Повернуть Аккумулятор справа. - person chqrlie; 28.09.2017
comment
@JonathanLeffler: Я понял: карта неверна, а мнемоники выбраны плохо. Оригинальная документация от Intel ] имеет следующее описание: RLC Rotate Accumulator Left. RRC Поверните аккумулятор вправо. RAL Повернуть аккумулятор влево через Carry. RAR Rotate Accumulator прямо через Carry. - person chqrlie; 28.09.2017