Я пишу эмулятор ZX Spectrum на C# "для удовольствия" (думаю, я уже жалею, что начал).
Я знаю, что у Z80 порядок следования байтов с прямым порядком байтов, поэтому в ОЗУ сначала хранится младший байт.
На что я не могу найти однозначного ответа, так это на то, как он ведет себя с 16-битной инструкцией LD
.
Например:
LD BC, 0x1234
После этого B
содержит 0x12
, а C
содержит 0x34
или наоборот?
Итак, после вышеизложенного, если я выполню:
LD A, 0x56
LD (BC), A
Будет ли память 0x1234
или 0x3412
содержать 0x56
?
Было бы неплохо, если бы кто-нибудь мог дать ссылку на надежный источник.
Вы написали инструкцию так, как ее отображает дизассемблер, или вы написали ее на ассемблере. Он использует «естественный» порядок, людям нравится их старший байт слева и наименее значимый справа. Та же история с парами регистров, у BC самый значащий регистр слева. Однако ваш эмулятор видит 0x01 0x34 0x12. Little-endian, 0x34 стоит первым. Только интерфейс шины памяти имеет детальный порядок байтов.
Значения в исходном коде asm являются значениями, а не кодировками; они используют обычный первый порядок старшей значащей цифры.
Является ли таблица производителя надежным источником? Руководство пользователя Z80 Ну и естественно в памяти после опкода сначала 0x34 потом 0x12
У меня есть это руководство... в нем просто сказано: "При выполнении инструкции LD HL, 5000h, пара регистров HL содержит 5000h". Не очень понятно.
На вопрос можно было бы ответить на странице 46 / 47 руководства пользователя, где описывается, как кодируется ld de,0659h
, к сожалению, рисунок 37 был испорчен и вместо этого показывает and 7
:-)
Порядок байтов вступает в игру только тогда, когда мы разбиваем 16-битное значение на две 8-битные части, и есть выбор подходов, что происходит, когда такое 16-битное значение хранится в памяти, например:
С кодированием непосредственных инструкций в инструкциях, таких как ld bc, 0x1234
: просмотрев отдельные байты машинного кода для этой инструкции, мы увидим 0x01 0x34 0x12, сохраняя 0x1234 в порядке байтов с прямым порядком байтов.
С 16-битным значением в качестве данных в памяти и просмотром отдельных байтов в памяти требуется порядок байтов, поэтому используйте прямой порядок байтов.
Однако, если пара регистров BC
загружена со значением 0x1234, то это адрес памяти, с которым будет работать косвенное использование BC
. В этом нет проблемы порядка следования байтов, поскольку в этом сценарии мы не рассматриваем отдельные байты.
Теперь, если вы хотите знать, как регистр BC
составляется из B
и C
, нам нужно знать, какой из них является старшим, а какой — младшим.
Из руководства:
PUSH BC - это PUSH B, затем C
Таким образом, это означает, что в памяти стека будет значение из C
, затем значение из B
по адресу +1 больше, чем там, где хранилось C
. Поскольку 16-битные данные в памяти хранятся с использованием прямого порядка байтов, мы можем сделать вывод, что C — это младший порядок, а B — старший порядок BC
16-битной пары регистров.
Таким образом, BC
равно B
* 256 + C
. Заметим, однако, что это просто по определению, но на самом деле не идет к порядку байтов — поскольку нет «адресации» отдельных байтов, нет и другого порядка, как в памяти (из-за того, что память имеет оба адреса и значения).
Однако выбор высокого и низкого не меняет того, что вместе они содержат значение 0x1234, как в наших примерах.
Кажется, это имеет смысл, спасибо за четкое объяснение.
Если вы когда-нибудь сомневаетесь, иногда самый простой способ — проверить это самостоятельно. Итак, эмуляторы не всегда точны, но если у вас нет настоящего оборудования, они — ваш лучший вариант. Для чего-то подобного вы можете доверять почти всем эмуляторам, чтобы сделать это правильно.
@ puppydrum64, это хороший комментарий, но он больше подходит для ОП, чем для меня.
Упс, я прокомментировал не тот пост!
Есть другая пара регистров... HL... Работает так же... Угадайте, что означают H и L...