;[BEGIN] ;//MODULE: EXECUTE ;//CREATE: 19-05-1998 AUTHOR: Denis Parinov ;//UPDATE: 24-10-1999 DNS Restore module ;--------------------------------------------------------------- ;Rev Date Name Description ;--------------------------------------------------------------- ;R12 20-07-2023 BAO При завершении приложения через функцию #41 или "аварийно" в возвращаемое приложение передаётся код ошибки и флаг CF=1 ;R11 17-04-2023 BAO OPTIMIZED BUFFERS, FREED UP 768 BYTES FOR CODE ;R10 13-04-2023 BAO FIX BUG WITH PARSING DIRECTORY BUFFER ;R09 14-04-2003 DNS NOW EXEC DON'T FOLLOW TO PROGRAM'S DIR ;R08 05-12-2002 DNS FIX BUG WITH INCREMENT TASK ID AND OPEN *.EXE ERROR ;R07 05-12-2002 DNS FIX FOR EXECUTING IN CURRENT DIR WITHOUT PATH ;R06 02-12-2002 DNS FIX BUG WITH NULL-TERMINATED STRING ;R05 02-12-2002 DNS ADD APP_PATH TO THE PROGRAM PREFIX ;R04 26-11-2002 DNS TRY TO FIX EXEC WITH PATH ;R03 19-11-2002 DNS CHECK SUBFN. FOR FN. EXEC ;R02 24-05-1999 DNS FIX CREATE PSP AND ; MOVE EXEC STACK ;R01 14-05-1999 DNS DECREASE HEADER SIZE FOR EXE-FILE ;--------------------------------------------------------------- ////////////////////////////////////////////////////////////////////// ; Функция #47. Получение информации приложения. ; ; вход: HL - буфер данных ; B - номер подфункции: ; B=0 - получение параметров командной строки ; B=1 - получение полного пути к каталогу программы ; B=2 - получение полного пути и имени файла программы ; выход: нет ; ; APPLICATION INFO ;==================== ; B = 0 - GET APP_PARAM ; B = 1 - GET APP_PATH ; B = 2 - GET APP_FULLNAME ////////////////////////////////////////////////////////////////////// ;LAST_PSP_PTR: DW 0 APPINFO: INC B APPINF0: DJNZ APPINF1 EX DE,HL XOR A LD (DE),A LD HL,(LAST_PSP_PTR) LD C,(HL) INC C RET Z INC HL LDIR AND A RET ; Получение параметров командной строки APPINF1: DJNZ APPINF2 EX DE,HL LAST_PSP_PTR+1: LD HL,0 LD C,(HL) INC HL ADD HL,BC INC HL INC HL PUSH HL LD BC,#100 ;!HARDCODE длина коммандной строки XOR A CPIR DEC HL ;R10 ;[x] исправлен баг с парсингом буфера каталога DEC HL ;R10,5 - не тестил ;!!!!! LD BC,#100 ;R10 ;[x] не было этой команды, CPDR мог не прошерстить всё ;!HARDCODE длина коммандной строки LD A,'\' CPDR INC HL INC HL POP BC AND A SBC HL,BC LD A,B ;EX HL,A,BC LD B,H LD H,A LD A,C LD C,L LD L,A LDIR XOR A LD (DE),A RET ; Получение полного пути к каталогу программы APPINF2: DJNZ APPINF3 EX DE,HL LD HL,(LAST_PSP_PTR) LD C,(HL) INC HL ADD HL,BC INC HL INC HL APINF2 LD A,(HL) LDI OR A JR NZ,APINF2 RET APPINF3 LD A,DSS_Error.sys.INVALID_FUNCTION SCF RET ////////////////////////////////////////////////////////////////////// ; Функция #45. Разбор командной строки. ; ; вход: HL - указатель командной строки ; DE - указатель на буфер пользователя ; B - номер подфункции: ; 0 - Разобрать строку ; 1 - Выделить имя диска ; 2 - Выделить директорию ; 3 - Выделить имя файла ; 4 - Выделить расширение файла ; 5 - Выделить имя диска, путь к файлу, имя файла и расш. файла ; 6 - Зарезервировано ; 7 - Выделить параметр командной строки ; 8 - Преобразовать из 11 символьного формата в формат ДОС ; 9 - Преобразовать из формата ДОС в 11 символьный формат ; выход: нет ////////////////////////////////////////////////////////////////////// GLOB_PR EQU 7 ;%10000000 DRIV_PR EQU 3 ;%00001000 PATH_PR EQU 2 ;%00000100 EXTN_PR EQU 1 ;%00000010 NAM_PR EQU 0 ;%00000001 EX_PATH: EXX LD HL,NM_PATH_A ;BUILT-IN BUFFER FOR PATH ;!FIXIT не чё, что используется общий буфер? LD (NM_PATH),HL LD HL,NM_NAME_A LD (NM_NAME),HL LD HL,NM_EXTN_A LD (NM_EXTN),HL LD HL,NM_DRIVE_A LD (NM_DRIVE),HL EXX INC B DEC B ;JR Z,EX_GET_ALL JR Z,EX_FULL ;0 ; разобрать строку DEC B JR Z,EX_GET_DRIVE ;1 ; выделить имя диска DEC B JR Z,EX_GET_PATH ;2 ; выделить директорию DEC B JR Z,EX_GET_NAME ;3 ; выделить имя файла DEC B JR Z,EX_GET_TYPE ;4 ; выделить расширение файла DEC B JR Z,EX_GET_ALL_EX ;5 ; выделить диск, путь, файл и расш. DEC B JR Z,EX_RESR ;6 ; зарезервировано DEC B JP Z,GSWITCH ;7 ; выделить параметр ком-строки DEC B JP Z,GETNAME ;8 ; преобр. имя 11 -> 8.3 формат DEC B JP Z,MASK ;9 ; преобр. имя 8.3 -> 11 формат EX_RESR: LD A,DSS_Error.sys.INVALID_FUNCTION SCF RET ; Выделить имя диска EX_GET_DRIVE: LD (NM_DRIVE),DE CALL EX_FULL RET C LD DE,(NM_DRIVE) LD A,(DE) DEC A CP #FF RET Z CP "A"-1 JR C,ERGD001 CP "Z" JR NC,ERGD001 SUB "A"-1 RET ERGD001 LD A,DSS_Error.sys.INVALID_DRIVE SCF RET ; Выделить директорию EX_GET_PATH LD (NM_PATH),DE JR EX_FULL ; Выделить имя файла EX_GET_NAME LD (NM_NAME),DE JR EX_FULL ; Выделить расширение файла EX_GET_TYPE LD (NM_EXTN),DE JR EX_FULL ; Разобрать строку ; EX_GET_ALL ; JR EX_FULL ; Выделить диск, путь, файл и расш. EX_GET_ALL_EX: EX DE,HL LD C,(HL) INC HL LD B,(HL) INC HL LD (NM_DRIVE),BC LD C,(HL) INC HL LD B,(HL) INC HL LD (NM_PATH),BC LD C,(HL) INC HL LD B,(HL) INC HL LD (NM_NAME),BC LD C,(HL) INC HL LD B,(HL) LD (NM_EXTN),BC EX DE,HL ;JR EX_FULL ; Разобрать строку EX_FULL: EX AF,AF' EXX XOR A LD HL,(NM_PATH) LD (HL),A LD HL,(NM_NAME) ; адрес буфера под имя файла LD (HL),A LD HL,(NM_EXTN) LD (HL),A LD HL,(NM_DRIVE) LD (HL),A EXX EX AF,AF' EX_PAT0: LD DE,TMPBUF LD BC,#0D01 ;!HARDCODE счетчики EX_PAT1: LD A,(HL) CALL UPPER ; a..z -> A..Z LD (DE),A INC HL INC DE INC C ; ++счетчик CP '\' JR Z,PATH_YEP CP ":" JR Z,DRIVE_YEP CP #21 JR C,NAME_YEP CP "?" JR Z,GLOBP1 CP "*" JR Z,GLOBP1 EX_PAT2: DJNZ EX_PAT1 LD A,DSS_Error.sys.INVALID_NAME SCF RET GLOBP1: EX AF,AF' SET GLOB_PR,A EX AF,AF' JR EX_PAT2 NAME_YEP: LD A,2 CP C JR Z,NOFNAME PUSH HL LD HL,TMPBUF LD DE,(NM_NAME) ; адрес буфера под имя файла LD B,0 DEC C DEC C LD A,C LDIR LD C,A XOR A LD (DE),A LD HL,(NM_NAME) LD A,"." CPIR JR NZ,NOEXTN LD C,3 LD DE,(NM_EXTN) EXTSK0: LD A,(HL) OR A JR NZ,EXTSK1 LD A,' ' DEC HL EXTSK1: LD (DE),A INC HL INC DE DEC C JR NZ,EXTSK0 XOR A LD (DE),A EX AF,AF' SET EXTN_PR,A ; указано расш. файла EX AF,AF' NOEXTN: EX AF,AF' SET NAM_PR,A ; указано имя файла EX AF,AF' POP HL NOFNAME: EX AF,AF' AND A RET DRIVE_YEP: XOR A LD (DE),A PUSH HL LD HL,TMPBUF LD DE,(NM_DRIVE) LD B,0 LDIR POP HL EX AF,AF' SET DRIV_PR,A ; указано имя диска EX AF,AF' JP EX_PAT0 PATH_YEP: XOR A LD (DE),A PUSH HL PUSH BC LD HL,(NM_PATH) LD BC,#00FF ; !FIXIT глубина буфера не зависит от DIRSPEC.DEPTH CPIR DEC HL EX DE,HL LD HL,TMPBUF ; 12 пробелов POP BC LD B,0 LDIR POP HL EX AF,AF' SET PATH_PR,A EX AF,AF' JP EX_PAT0 TMPBUF: DB " ",#00 ; 12 пробелов NM_DRIVE: DW NM_DRIVE_A NM_NAME: DW NM_NAME_A NM_EXTN: DW NM_EXTN_A NM_PATH: DW NM_PATH_A NM_DRIVE_A: BLOCK 9,0 NM_NAME_A: DB " ",#00 NM_EXTN_A: DB " ",0 NM_PATH_A EQU BUFFER ;DS 256 ////////////////////////////////////////////////////////////////////// ; Функция #43. Выделить параметр командной строки. ; ; вход: HL - указатель командной строки ; DE - буфер для выдел. параметра ; выход: HL - указатель на след. параметр ком-строки ; CF=0 - конец строки не достигнут (есть другие параметры) ; CF=1 - конец строки (в буфер перенесён последний параметр или ноль) ; ;ENTRY: HL - COMMAND LINE ; DE - SWITCH BUFFER ;EXIT: BUFFER ////////////////////////////////////////////////////////////////////// GSWITCH: XOR A LD (DE),A GSWIT1: LD A,(HL) INC HL CP " " RET C JR Z,GSWIT1 GSWIT2: LD (DE),A LD A,(HL) INC HL INC DE CP " "+1 JR NC,GSWIT2 CP " " LD A,0 LD (DE),A RET ////////////////////////////////////////////////////////////////////// ; Функция #3C. Информация о памяти. ; ; вход: нет ; выход: HL - общее кол-во страниц ; BC - кол-во своб. страниц ////////////////////////////////////////////////////////////////////// FREEMEM: LD C,BIOS.GetMemSize RST ToBIOS RET ////////////////////////////////////////////////////////////////////// ; Функция #3D. Выделение блока памяти. ; ; вход: B - размер блока в страницах по 16kB ; выход: A - идентификатор блока памяти, если CF=0 ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// GETMEM: LD C,BIOS.GetMem RST ToBIOS LD E,A LD A,DSS_Error.sys.NOT_ENOUGH_MEMORY RET C LD D,#00 LD HL,MEMTAB ; массив списка выдел. страниц ADD HL,DE LD A,(TASK) ; уровень текущей программы LD (HL),A LD A,E AND A RET ////////////////////////////////////////////////////////////////////// ; Функция #3E. Освобождение блока памяти. ; ; вход: A - идентификатор блока памяти ; выход: A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// RETMEM: LD E,A LD D,#00 LD HL,MEMTAB ; массив списка выдел. страниц ADD HL,DE LD A,(TASK) ; уровень текущей программы CP (HL) LD A,DSS_Error.sys.INVALID_MEMORY_HND SCF RET NZ PUSH DE LD A,E LD C,BIOS.FreeMem RST ToBIOS POP DE LD A,DSS_Error.sys.INVALID_MEMORY_HND RET C LD HL,MEMTAB ADD HL,DE XOR A LD (HL),A RET ////////////////////////////////////////////////////////////////////// ; Функция #3F. Изменение блока памяти. ; ; вход: A - идентификатор блока памяти ; B - новый размер блока ; выход: A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETMEM: LD E,A LD D,#00 LD HL,MEMTAB ADD HL,DE LD A,(TASK) CP (HL) LD A,DSS_Error.sys.INVALID_MEMORY_HND SCF RET NZ LD D,B PUSH DE LD A,E CALL SIZEBLK POP DE LD A,DSS_Error.sys.INVALID_MEMORY_HND RET C LD A,B CP D RET Z JR C,INCMEM DECMEM: LD B,D LD A,E LD C,BIOS.DivMemBlocks RST ToBIOS LD A,B LD C,BIOS.FreeMem RST ToBIOS XOR A RET ; Добавить страниц памяти к блоку INCMEM: LD A,D SUB B LD B,A LD C,E PUSH BC LD C,BIOS.GetMem RST ToBIOS POP BC LD B,A LD A,DSS_Error.sys.NOT_ENOUGH_MEMORY RET C LD A,C LD C,BIOS.MergeMemBlocks RST ToBIOS XOR A RET SIZEBLK: LD B,#FF LD C,A .loop: INC B PUSH BC LD A,C LD C,BIOS.GetMemPage RST ToBIOS POP BC JR NC,.loop OR A SCF RET Z XOR A RET LEAVMEM: LD HL,MEMTAB LD BC,256 ;!HARDCODE размер блока страниц ОЗУ .loop: LD A,(TASK) CPIR RET NZ PUSH HL PUSH BC DEC HL AND A LD DE,MEMTAB SBC HL,DE LD A,L CALL RETMEM ; освоб. блок памяти POP BC POP HL JP .loop ////////////////////////////////////////////////////////////////////// ; Функция #38. Подключение страницы памяти. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; H - биты 6 и 7 задают номер окна, в которое будет подкл. страница ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ; if B = 0FFh, then logical page number got from DE ////////////////////////////////////////////////////////////////////// SETWIN: BIT 7,H ; if #8000 or high? JR Z,SETWIN1 ; no, go to open in SLOT1 BIT 6,H ; if #C000 or high? JR Z,SETWIN2 ; no, go to open in SLOT2 //JR SETWIN3 ; yes, go to open in SLOT3 ////////////////////////////////////////////////////////////////////// ; Функция #3B. Подключение страницы памяти в третье окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETWIN3: LD C,BIOS.GetMemPage EX DE,HL RST ToBIOS EX DE,HL RET C LD C,SLOT3 IN B,(C) OUT (C),A LD A,B RET ////////////////////////////////////////////////////////////////////// ; Функция #39. Подключение страницы памяти в первое окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETWIN1: LD C,BIOS.GetMemPage EX DE,HL RST ToBIOS EX DE,HL RET C LD C,SLOT1 IN B,(C) OUT (C),A LD A,B RET ////////////////////////////////////////////////////////////////////// ; Функция #3A. Подключение страницы памяти во второе окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETWIN2 LD C,BIOS.GetMemPage EX DE,HL RST ToBIOS EX DE,HL RET C LD C,SLOT2 IN B,(C) OUT (C),A LD A,B RET ;!TODO если надо будет сэкономить память, но привязаться к номерам слотов ; SETWIN1: LD H,SLOT1 : JR SETWIN.ALL ; SETWIN2: LD H,SLOT2 : JR SETWIN.ALL ; SETWIN3: LD H,SLOT3 : JR SETWIN.ALL ; SETWIN: LD C,A ; LD A,H ; AND %1100'0000 ; JR NZ,.no_error ; OR %0100'0000 ; .no_error: RRСA ; OR %100'0010 ; LD H,A ;SLOT number ; LD A,C ; .ALL: LD C,BIOS.GetMemPage ; EX DE,HL ; RST ToBIOS ; EX DE,HL ; RET C ; LD C,H ;SLOT number ; IN B,(C) ; OUT (C),A ; LD A,B ; RET ; ; // SLOT0 - #82 %1000'0010 ; // SLOT0 - #A2 %1010'0010 ; // SLOT0 - #C2 %1100'0010 ; // SLOT0 - #E2 %1110'0010 ;///////////////////////////////////////////////////////////////////// ; Функция #40. Выполнить файл. ; ; вход: HL - указатель на имя файла ; B=0 - загрузить и выполнить программу с коротким именем (без полного пути до программы) ; B=1 - загрузить и выполнить программу с полным путём до программы ; выход: A - код завершения, если CF=0 ; код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// EXEC: _mSavePath INC B ;R03 DEC B ;R03 JP Z,EXEC0 ;R03 DEC B ;R03 JP Z,EXEC1 ;R03 LD A,DSS_Error.sys.INVALID_FUNCTION ;R03 SCF ;R03 RET ;R03 CHECKPATH: ; !TODO сделать проверку на количество циклов LD A,(HL) INC HL CP '\' RET Z CP '/' ;ALT SLASH RET Z CP '!' JR NC,CHECKPATH RET RELATIVE_DIR EQU 0 ABSOLUTE_DIR EQU 1 FINDPATH: SET_PAGE_X ENVPAGE PUSH AF CALL CURRDSK ADD A,"A" LD HL,TMP_CURDIR LD (HL),A INC HL LD A,":" LD (HL),A INC HL CALL CURRDIR CALL MAKE_PATH_ARRAY LD HL,PATH_PNT_ARRAY NEXTPATHI: LD E,(HL) INC HL LD D,(HL) INC HL BIT ABSOLUTE_DIR,(HL) INC HL PUSH HL PUSH BC EX DE,HL CALL Z,GOTO_CURDIR CALL CHDIR JR C,BADPATH LD HL,EXEBUFF LD DE,MASKARE CALL MASK JR C,BADPATH CALL TST_EXT JR C,BADPATH CALL SEARCH BADPATH: POP BC POP HL JR NC,PATHFOUND DJNZ NEXTPATHI SCF PATHFOUND: POP BC LD A,B OUT (SLOT3),A LD A,DSS_Error.sys.PATH_NOT_FOUND RET GOTO_CURDIR: PUSH HL LD HL,TMP_CURDIR CALL CHDIR POP HL RET MAKE_PATH_ARRAY: LD HL,PATH_PNT_ARRAY-1 ;R04 -1 LD DE,ENVTEMP-1 LD B,#00 NEXTAR: LD (HL),C ;R04 INC HL ;R04 XOR A LD (DE),A LD C,A INC DE LD (HL),E INC HL LD (HL),D INC HL ;R04 LD (HL),C ;R04 INC HL INC B NEXTRT: LD A,(DE) CP '\' JR NZ,NEXTCH NEXTDR: SET ABSOLUTE_DIR,C NEXTRL: ;SET RELATIVE_DIR,C ;!TODO ???? NEXTCH: LD A,(DE) CP ";" JR Z,NEXTAR INC DE ; CP "." ; JR Z,NEXTRL CP ":" JR Z,NEXTRT OR A JR NZ,NEXTCH LD (HL),C ;R04 INC HL ;R04 LD (HL),A INC HL LD (HL),A RET ENVPATH DB "PATH=",0 ;;; ; !TODO СДЕЛАТЬ СТРУКТУРОЙ PATH_PNT_ARRAY EQU #FC80 TMP_CURDIR EQU #FD00 ENVTEMP EQU #FE00 INCTASK: LD HL,TASK ;R08 INC (HL) ;R08 RET ;R08 DECTASK: LD HL,TASK ;R08 DEC (HL) ;R08 RET ;R08 ;------------------------------------------------------------------------ ; Загрузить и выполнить программу. ; функ. 40h, B=0. ; ; 1) Открывает exe-файл на чтение; ; 2) Считывает в рабочую область префикс exe-файла; ; 3) Выделяет блок памяти, требуемый для загрузки всего файла или первичного ; загрузчика, если его размер не равен нулю; ; 4) Сохраняет стек; ; 5) Подключает страницы из выделенного блока; ; 6) Строит префикс запуска программы и устанавливает на него регистр IX; ; 7) Считывает файл по адресу указанному в смещении 16 (Адрес расположения ; кода в памяти); ; 8) Закрывает exe-файл, если это не первичный загрузчик; ; 9) Устанавливает стек равным значению из смещения 20 (Адрес расп. стека); ; 10) Передает управление по адресу указанному в смещении 18 (Адрес запуска); ; ; Префикс запуска файла: ; ; -03 1 db ? ; Дескриптор файла, если exe-файл с первичным загрузчиком ; -02 1 db ? ; Идентификатор блока памяти ; -01 1 db ? ; Уровень текущей программы ; +00 1 db ? ; Длина ком-строки ; +01 127 ds ? ; Параметры ком-строки, заканчивается нулем ;------------------------------------------------------------------------ EXEC0: LD (CMDLINE),HL CALL CHECKPATH ;CHECK FOR '\' - SHORT/FULL NAME LD HL,(CMDLINE) JR C,EXEC0_SHORT EXEC1: CALL EXEC_1 SCF RET ; File not found - exit ; при выходе с ошибкой, в регистре А - код ошибки EXEC_1: LD (CMDLINE),HL LD A,#01 ; %7600000R = !FAT_ATTR LD (ACCESS),A CALL GETWORD RET C LD HL,TMPNAME LD DE,MASKARE CALL MASK RET C CALL TST_EXT LD A,3 RET C CALL INCTASK ;R08 CALL OPENEXE JR NC,.noError CALL DECTASK ;R08 AND A RET .noError: POP HL ; убираем лишний адрес_возврата_в_вызвавшую_процедуру JP EXEC02 ;R07 CONTINUE EXECUTING PROGRAM ;SHORT NAME ;TRY TO FIND IN CURRENT DIRECTORY EXEC0_SHORT: CALL EXEC_1 RET C ;FILE NO FOUND, SEARCHING IN PATH ; GET PATH AND ETC. LD HL,ENVPATH LD DE,ENVTEMP LD B,Dss.Environ.Get CALL ENVIRON LD HL,(CMDLINE) LD DE,EXEBUFF COPYEXN: LD A,(HL) LDI OR A JR NZ,COPYEXN CALL FINDPATH LD HL,(CMDLINE) JR EXEC1 EXEC02: LD (EXE_FM),A LD HL,EXEBUFF LD DE,#0080 ;!#0200(512) ;R02 LD A,(EXE_FM) CALL READ JP C,ERREXE LD IX,EXEBUFF LD HL,(EXEBUFF) LD DE,'E'+'X'*256 ;AND A ; не нужно, если бы был CF=1, то чуть выше мы бы ушли на JP C,ERREXE SBC HL,DE LD A,DSS_Error.sys.INVALID_EXE SCF JP NZ,ERREXE LD A,(IX+3) ;!HARDCODE OR A LD A,DSS_Error.sys.UNKNOWN_EXE SCF JP NZ,ERREXE ; LD HL,TASK ; INC (HL) ; ; HERE TO DO: BACK TO CURRDIR ; ;R09 _mRestorStackAfterRestorePath ;R09 ; LD DE,(EXEBUFF.LOADER) LD A,E OR D JP NZ,PRELOAD ; A=0 LD H,A LD L,A LD XL,A LD XH,A ; LD B,#02 LD A,(EXE_FM) CALL MOVE_FP LD DE,(EXEBUFF.LD_ADDR) LD A,D AND #3F LD D,A ADD IX,DE LD DE,#0000 ADC HL,DE LD A,XH SLA A RL L RL H SLA A RL L RL H OR XL JR Z,NOINK INC HL NOINK: LD A,H OR A JP NZ,ERREXE0 LD B,L ;!FIXIT double 1 CALL GETMEM JP C,ERREXE0 LD (EXE_MEM),A EXX POP DE ;снимаем со стека адрес возврата LD HL,#0000 ADD HL,SP LD SP,(EXSTACK) PUSH HL PUSH DE IN A,(SLOT3) LD D,A IN A,(SLOT2) LD E,A IN A,(SLOT1) PUSH DE PUSH AF LD (EXSTACK),SP LD SP,HL EXX ;...... ;!FIXIT.НЕ.СОХРАНЯЕТ.DE.перед.вызовом.BIOS..............................; LD A,(EXE_MEM) LD DE,RAMMAP LD BC,0*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,1*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,2*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,3*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A ;^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^; LD HL,(CMDLINE) LD DE,SECBUF+1 CALL SCOPYS LD A,#80 SUB B LD (SECBUF),A ;R02 LD SP,EXEBUFF+510 ;Вставляется в DSS_PAGE ; LD A,SHARED_PAGE OUT (SLOT1),A OUT (SLOT2),A OUT (SLOT3),A LD HL,(EXEBUFF.LD_ADDR) LD DE,RAMMAP LD A,H AND #C0 CP #40 JR Z,FR4000 CP #80 JR Z,FR8000 CP #C0 JR Z,FRC000 FR4000: LD A,(DE) OUT (SLOT1),A INC DE FR8000: LD A,(DE) OUT (SLOT2),A INC DE FRC000: LD A,(DE) OUT (SLOT3),A CALL M_PSP LD HL,(EXEBUFF.OFFCOD2) LD IX,(EXEBUFF.OFFCOD1) LD B,Dss.Move_FP.FrStart LD A,(EXE_FM) CALL MOVE_FP ;R02 LD SP,#403F ;!HARDCODE STACK before start EXE. Устанавливается когда воткнуты DSS_PAGE ; ; LD DE,(EXEBUFF.LD_ADDR) XOR A LD H,A LD L,A SBC HL,DE EX DE,HL ; de=число чит. байт LD HL,(EXEBUFF.LD_ADDR) ; буфер LD A,(EXE_FM) ; дескр. файла CALL READ ; чтение из файла LD A,(EXE_FM) ; дескр. файла CALL CLOSE ; закрыть файл ;!FIXIT double 2 ;R09 _mRestorePath ; LD SP,(EXEBUFF.SP_REG) LD HL,(EXEBUFF.LD_ADDR) LD DE,#0080 AND A SBC HL,DE EX DE,HL LD XH,D LD XL,E LD HL,(EXEBUFF.PC_REG) LD DE,RETFAR ; адрес п/п "неожиданное завершение процесса" PUSH DE PUSH HL RET ; ;[ ] RETFAR: LD B,DSS_Error.sys.UNEXPECTED_APP_TRMN JP LEAVE ; завершить программу (процесс) ;------------------------------------------------- ; Если расш. файла не задано, задать "exe". ; Если расш. файла задано, сравнить его с "exe". ;------------------------------------------------- TST_EXT: LD HL,EXE_EXT ; "EXE" LD DE,MASKARE+8 LD B,3 LD A,(DE) CP ' ' JR NZ,.loop ; задано расш. LDI LDI LDI XOR A RET ; сравнить расш. с "EXE" .loop: LD A,(DE) CP (HL) SCF RET NZ ; не совпадает INC HL INC DE DJNZ .loop XOR A ; Ok RET ERREXE0: LD A,DSS_Error.sys.NOT_ENOUGH_MEMORY ERREXE: PUSH AF LD A,(EXE_FM) CALL CLOSE CALL DECTASK POP AF RET PRELOAD: EX DE,HL LD DE,(EXEBUFF.LD_ADDR) LD A,D AND #3F LD D,A ADC HL,DE XOR A SLA H RLA SLA H RLA LD B,A LD A,H OR L JR Z,NOINK2 INC B NOINK2: ;!FIXIT double 1 CALL GETMEM JP C,ERREXE0 LD (EXE_MEM),A EXX POP DE LD HL,#0000 ADD HL,SP LD SP,(EXSTACK) PUSH HL PUSH DE IN A,(SLOT3) LD D,A IN A,(SLOT2) LD E,A IN A,(SLOT1) PUSH DE PUSH AF LD (EXSTACK),SP LD SP,HL EXX ;...... ;!FIXIT.НЕ.СОХРАНЯЕТ.DE.перед.вызовом.BIOS..............................; LD A,(EXE_MEM) LD DE,RAMMAP LD BC,#00*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,1*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,2*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,3*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A ;^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^; LD HL,(CMDLINE) LD DE,SECBUF+1 CALL SCOPYS LD A,#80 SUB B LD (SECBUF),A ;R02 LD SP,EXEBUFF+510 ;Вставляется в DSS_PAGE ; LD A,SHARED_PAGE OUT (SLOT1),A OUT (SLOT2),A OUT (SLOT3),A LD HL,(EXEBUFF.LD_ADDR) LD DE,RAMMAP LD A,H AND #C0 CP #40 JR Z,FR4000H CP #80 JR Z,FR8000H CP #C0 JR Z,FRC000H FR4000H: LD A,(DE) OUT (SLOT1),A INC DE FR8000H: LD A,(DE) OUT (SLOT2),A INC DE FRC000H: LD A,(DE) OUT (SLOT3),A CALL M_PSP LD HL,(EXEBUFF.OFFCOD2) LD IX,(EXEBUFF.OFFCOD1) LD B,Dss.Move_FP.FrStart LD A,(EXE_FM) CALL MOVE_FP ;R02 LD SP,#403F ;!HARDCODE STACK before start EXE. Устанавливается когда воткнуты DSS_PAGE ; ; LD HL,(EXEBUFF.LD_ADDR) ; буфер LD DE,(EXEBUFF.LOADER) ; число чит. байт LD A,(EXE_FM) ; дескр. файла CALL READ ; чтение из файла ;!FIXIT double 2 ;R09 _mRestorePath ; LD SP,(EXEBUFF.SP_REG) LD HL,(EXEBUFF.LD_ADDR) LD DE,#0080 AND A SBC HL,DE EX DE,HL LD XH,D LD XL,E LD HL,(EXEBUFF.PC_REG) LD DE,RETFAR PUSH DE PUSH HL RET ; ;///////////////////////////////////////////////////////////////////// ; Функция #41. Завершить программу (процесс). ; ; вход: B - код завершения ; выход: A - код ошибки, если CF=1 ; ; Выход из EXE-файла: ; ; 1) Освобождаются все блоки памяти которые выделялась данному приложению. ; 2) Восстанавливаются страницы которые были подключены до запуска EXE-файла. ; 3) Вспоминается стек. ; 4) В регистр A помещается код возврата и выполняется RET. ; ;///////////////////////////////////////////////////////////////////// LEAVE: LD A,B LD (ERLEVEL),A CALL LEAVMEM CALL DECTASK LD SP,(EXSTACK) POP AF POP HL OUT (SLOT1),A LD A,L OUT (SLOT2),A LD A,H OUT (SLOT3),A POP DE POP HL LD (EXSTACK),SP LD SP,HL EX DE,HL LD A,(ERLEVEL) AND A ;R12 JR Z,.exit SCF ; .exit: JP (HL) ;///////////////////////////////////////////////////////////////////// ; Функция #42. Получить код завершения программы. ; ; вход: нет ; выход: A - код завершения ;///////////////////////////////////////////////////////////////////// WAIT: LD A,(ERLEVEL) AND A RET M_PSP: LD HL,(EXEBUFF.LD_ADDR) DEC H LD D,H LD E,L INC DE LD BC,#00FF LD (HL),B LDIR EX DE,HL DEC H LD DE,#0080 ADD HL,DE EX DE,HL LD XH,D LD XL,E LD HL,SECBUF LD C,(HL) INC C LDIR EX DE,HL ;R06 LD (HL),B LD A,(TASK) LD (IX-1),A LD A,(EXE_MEM) LD (IX-2),A LD A,(EXE_FM) LD (IX-3),A ;R05 INC HL LD (HL),B INC HL CALL CURRDSK ADD A,'A' LD (HL),A INC HL LD A,':' LD (HL),A INC HL PUSH HL CALL CURRDIR POP HL XOR A LD BC,#0100 ;!FIXIT нет привязки к DIRSPEC.DEPTH CPIR ;!FIXIT нет проверки на выход по BC=0 DEC HL DEC HL LD A,'\' CP (HL) INC HL JR Z,.YP_ESLA LD (HL),A INC HL .YP_ESLA: EX DE,HL LD HL,TMPNAME .loop: LD A,(HL) LDI CP ' '+1 JR NC,.loop DEC DE XOR A LD (DE),A LD (LAST_PSP_PTR),IX ; RET SCOPYS: LD BC,#80*256 + ' '+1 .loop: LD A,(HL) CP C JR C,.copy INC HL DJNZ .loop XOR A LD (DE),A LD B,#80 RET .copy: LD BC,#80*256 + ' ' .loop2: LD A,(HL) LD (DE),A INC HL INC DE CP C RET C DJNZ .loop2 RET EXE_EXT: DB "EXE" TASK: DB #01 ; уровень текущей программы RAMMAP: DB #00,#00,#00,#00 ERLEVEL: DB #00 ; код завершения программы (процесса) EXE_FM: DB #00 ; дескр. файла EXE_MEM: DB #00 ; идентификатор блока памяти CMDLINE: DW #0000 EXSTACK: DW XSTACK ; адрес стека ;R11 \\\\\\\\\\\\\\\\\\\\\\\\\\\\ ;; ; EXEBUFF: ; DB "EXE" ; DB #00 ; OFFCOD1 DW #0000 ; OFFCOD2 DW #0000 ; LOADER DW #0000 ; DW #0000 ; DW #0000 ; DW #0000 ; LD_ADDR DW #0000 ; PC_REG DW #0000 ; SP_REG DW #0000 ; BLOCK 512-($-EXEBUFF),0 ; ;(!!!HERE STACK FOR EXEC!!!) ; BLOCK 255,0 ; XSTACK DB #00 ;R11 //////////////////////////// ;//MODULE: EXECUTE ;[END]