Во-первых, давайте отметим, что вся память 16-разрядного адресного пространства предназначена для использования в соответствии с картой памяти (например, по крайней мере в диапазоне x3000-xFDFF), и она инициализирована. в ноль; вы можете использовать его по своему желанию.
Вообще говоря, ассемблеры L C -3 не допускают использование нескольких директив .ORIG по всему файлу, вместо этого им требуется одна директива в начале файла. Если бы они разрешали последующие директивы .ORIG, это было бы способом выполнения sh того, о чем вы спрашиваете.
Но даже если бы они это делали, мы часто сталкивались с ограничениями кодирования смещения команд. Итак, есть альтернативное решение, которое я покажу ниже.
Но сначала давайте посмотрим на смещение инструкции / непосредственные ограничения кодирования.
Обычные форматы инструкций доступа к памяти данных имеют очень ограниченное смещение, всего 9 битов (+/- около 256), а смещение равно p c. Так, например, следующее не будет работать:
.ORIG x3000
LEA R0, TESTA
LD R1, TESTA
LEA R2, TESTB ; will get an error due to instruction offset encoding limitation
LD R3, TESTB ; will get an error due to instruction offset encoding limitation
HALT
TESTA
.FILL #1234
.BLKW xFA ; exactly enough padding to relocate TESTB to x3100
TESTB
.FILL #4321 ; which we can initialize with a non-zero value
.END
Это наглядно: хотя это успешно поместит TESTB
на x3100, оно не может быть достигнуто ни LEA
, ни LD
инструкции из-за ограниченного 9-битного относительного смещения p c.
(Существует также другое практическое ограничение, заключающееся в том, что при добавлении инструкций операнд .BLKW
должен уменьшаться в размере, что явно болезненно - этот аспект был бы устранен путем поддержки директивы .ORIG
внутри.)
Итак, альтернатива для больших блоков и других подобных объектов - прибегнуть к использованию инициализированной нулями памяти, и ссылаясь на эту другую память, используя переменные указателя поблизости: используя LD
для загрузки адреса, а не LEA
и LDI
для доступа к значению вместо LD
.
.ORIG x3000
LEA R0, TESTA
LD R1, TESTA
LD R2, TESTBRef ; will put x3100 into R3
LDI R3, TESTBRef ; will access the memory value at address x3100..
HALT
TESTA
.FILL #1234
TESTBRef ; a nearby data pointer, that points using the full 16-bits
.FILL x3100
.END
В в последнем случае выше нет объявления о резервировании хранилища на x3100
, и мы не можем инициализировать это хранилище на x3100
с ненулевой инициализацией (например, без строк, без предварительно определенных массивов). ).
Используется указатель данных на данные, TESTBRef
. В отличие от кода к коду / ссылкам на данные (т. Е. инструкции , ссылающиеся на код или данные), указатели на данные к коду / данным (т. Е. data ссылающиеся на код или данные) имеют все 16- биты, доступные для наведения.
Итак, когда мы используем этот подход, просто используя другую память, мы для go автоматически c размещаем метки после других меток (для этих других областей), а также для go ненулевой инициализации.
Некоторые ассемблеры L C -3 допускают несколько файлов, и каждый из них допускает свою собственную директиву .ORIG
- поэтому, используя несколько файлов, мы можем разместить код и данные в разных местах в адресном пространстве. Тем не менее, ограничения кодирования смещения инструкций кода к данным все еще применяются, и поэтому вам, скорее всего, придется в любом случае вручную управлять другими такими областями памяти и использовать указатели данных.
Обратите внимание, что инструкция JSR имеет 11-битное смещение, поэтому ссылки между кодами могут достигать дальше, чем ссылки между кодами.