Впрочем, это и не удивительно, авторы сами об этом везде рассказывают:
И, действительно, судя по исходникам, программный стек начинается с адреса $80.Is there a stack?
There is no hardware stack register, but the vCPU maintains a stack in the top half of the zero page. There are addressing modes that make function calling and returning relatively easy, and dynamic stacks possible when needed.
Я решил не копать пока авторские муторные исходники, а попробовать реализовать software stack
самостоятельно. На мой взгляд всё должно работать примерно так:
Предположим, что у нас выполняется некоторая программа, из которой будет вызов подпрограммы,
и предположим пока для простоты, что ячейки адреса возврата находятся в нулевой странице ОЗУ
по адресам 80Н и 81Н для младшего и старшего байтов адреса, соответственно, а в ячейке 7FH
находится указатель "стека":
Code: Select all
ORG 0000H
LDA 80H; указатель "стека"
STA [7FH]; инициализируем
... что-то делаем ...
LDA 00H
LD AC,OUT; - clear port
NOP; - Delay
NOP; - 20 mS
;------------ собираемся вызвать подпрограмму
LD 80H,X; Укажем на ячейку памяти "стека"
LDA RETADDR<; в A - младший байт RETADDR
STA [X]; сохраняем младший байт в ячейку памяти "стека"
ADD 01Н,X; сдвинем вверх указатель стека
LDA >RETADDR; в A - старший байт RETADDR
STA [X]; сохраняем старший байт в ячейку памяти "стека"
;------------ адрес возврата сохранен в программном "стеке"
LDA [7FH]; берем указатель стека
ADD 02Н; указатель сдвигаем на свободную ячейку 82Н
STA [7FH]; сохраняем указатель "стека"
;------------ готовим вызов подпрограммы по адресу 3F55H
LD 3FH,Y; - старший адрес (или сегмент) перехода
LDA 30H; - аргумент, передаваемый в функцию
JMP Y,55Н; переход к подпрограмме
NOP; - after JMP
RETADDR: - адрес возврата из подпрограммы (компилятор его знает)
...
...
...
SUB3F55:
... что-то делаем ...
...
;------------ готовим возврат из подпрограммы
LDA [7FH]; берем указатель стека
SUB 01Н,X; сдвинем вниз указатель стека
LDA [X]; взяли из "стека" старший адрес
LD AC,Y; указали старший адрес возврата
SUB 01Н,X; сдвинем вниз указатель стека
LDA [7FH]; берем указатель стека
SUB 02Н; указатель сдвигаем на свободную ячейку 80Н
STA [7FH]; сохраняем указатель "стека"
LDA [X]; взяли из "стека" младший адрес
JMP Y,AC; возвращаемся из подпрограммы на RETADDR
Если вызов подпрограммы ближний, типа BRA, то сохранять в стеке необходимо лишь младший байт
адреса возврата - программа будет короче.