Вот пример, показывающий соответствие между сборкой (то, что вы называете «сокращением») и машинным кодом. Во-первых, вот код ассемблера для алгоритма с некоторыми абстрагированными параметрами:
* = 4000 ; This is the address where our program will be stored
LDX #len
loop LDA src,X
STA dest,X
DEX
BNE loop
Конечно, вы не можете превратить это непосредственно в машинный код. Вам также необходимо заполнить значения len
, src
и dest
:
src = $1234
dest = $5678
len = 10
В имени loop
нужно понимать, что точно так же, как src
присваивается значение $1234
, loop
будет присвоен адрес инструкции после него. Таким образом, в этом случае, поскольку LDX #len
занимает 2 байта (как я скоро вам покажу), loop
устанавливается в $4000 + 2 = $4002
. Это выполняется автоматически ассемблером, но, конечно, вы можете сделать все это и на бумаге.
Так, каков машинный код 6502 для вышеупомянутой программы сборки?
A2 0A
BD 34 12
9D 78 56
CA
D0 F7
Откуда мне это знать? Ну, я только что вставил вышеупомянутую программу в онлайн-ассемблер 6502 по адресу http://www.masswerk.at/6502/assembler.html. Она даже показывает вам детальное сопоставление между сборкой и машинным кодом:
4000 LDX #LEN A2 0A
4002 LOOP LDA SRC,X BD 34 12
4005 STA DEST,X 9D 78 56
4008 DEX CA
4009 BNE LOOP D0 F7
400B
Обратите внимание, что фактическое значение LOOP
даже не используется для вычисления машинного кода для BNE LOOP
, только его относительный адрес по сравнению с самой инструкцией BNE
: F7
равно -9, и разница между $400B
и $4002
- это -9!
Так что, если бы вы делали это вручную, вы бы просто перевели все остальное в машинный код, затем, когда вы доберетесь до перехода, вы вычислите разницу между начальным адресом следующей инструкции и адресом назначения перехода. Он должен быть отрицательным для прыжков назад и положительным для прыжков вперед.