До того, как у процессоров появился стек или достаточное количество регистров, параметры часто передавались через «встроенную» передачу параметров, то есть параметры передаются после инструкции JSR
или типа вызова, путем помещения значений или указателей непосредственно после инструкции вызова, с требованием, чтобы вызываемый абонент пропускает их при возврате, чтобы возобновить вызов вызывающего абонента.
Как вы знаете, инструкция вызова захватывает адрес возврата (каким-то образом, где-то: может быть, в стеке или, может быть, в памяти кода подпрограммы!), и этот адрес возврата можно использовать для выборки параметров, которые помещаются после инструкции вызова. Адрес возврата увеличивается для получения последовательных параметров, и когда это сделано, его необходимо увеличить (на 1 или 2) еще раз, чтобы вернуться к фактическому коду вызывающей стороны, а не к встроенным параметрам, которые, конечно же, являются данными. , а не код.
Стиль, который Хайд использует для этого PRTSTR
, представляет собой встроенный механизм параметров.
Вот использование этого PRTSTR
:
...
STRING STR "HELLO THERE"
...
START
JSR PRTSTR # call to print string
ADR STRING # pointer parameter passed "inline" within code,
# this is data, to be used and then skipped over by print string
... # actual return location to resume code in START
Учитывая, что в 6502 были как стек вызовов, так и регистры, использование встроенного механизма для вызовов является своего рода возвратом, но, безусловно, это было сделано. (Встроенный механизм передачи параметров предшествует стекам вызовов и большому количеству регистров, которые мы имеем в современных процессорах.)
Со стеком, но с небольшим количеством регистров, некоторые вызовы с многочисленными параметрами выполнялись бы путем помещения параметров в стек, в то время как другие выполнялись бы путем передачи доступных регистров.
В коде на чистом ассемблере вы можете создать собственное соглашение о вызовах для каждой функции. Только появление C и других языков высокого уровня создает потребность в канонических, регулярных и предсказуемых соглашениях о вызовах, которые могут быть кодифицированы в компиляторе.
Я должен признать, что не понимаю первую из трех инструкций JSR INCRTN
. (Последние два я понимаю — они пропускают указатель на строку (инлайн-параметр после JSR
), а так как указатели двухбайтовые, то и адрес нужно увеличивать на 2 байта — но самый первый из трех мне кажется ошибочным. ) На 6502 нет кода операции ADR
, поэтому я должен предположить, что это псевдокод операции ассемблера, который формирует 2-байтовый указатель на метку.
Мое предположение несколько подтверждает Хайд в 14-6, где говорится:
JSR SASIGN ;STRING ASSIGNMENT
ADR DEST ;DEST = SOURCE
ADR SOURCE
что приведенное выше представляет собой последовательность из 7 байтов (т.е. 1 для кода операции JSR
, 2 для SASIGN
(операнд JSR
) и по 2 для ADR DEST
и ADR SOURCE
).
Таким образом, 16-битная переменная в RTNADR
и RTNADR + 1
должна быть увеличена на единицу, когда код выполняет JSR INCRTN
.
Я считаю, что эту кодовую последовательность можно было бы значительно улучшить, если бы индексный регистр использовался более непосредственно в качестве указателя, вместо косвенного использования памяти вместе с целым числом в индексном регистре Y.
Кроме того, поскольку я не могу понять первый JSR INCRTN
, а второй вызывается дважды, он может просто увеличиться на 2 вместо 1 дважды.
person
Erik Eidt
schedule
13.12.2019
RTNADR += 1
, конечно, вы можете это запрограммировать? - person Jester   schedule 13.12.2019RTNADR
на 1. - person Jester   schedule 13.12.2019