Ещё раз - в Паскале всё просчитывается в момент компиляции - потому что понятно - кто в кого вложен и как был вызов
Если Вам это не понятно - это не мои проблемы
Ещё раз - в Паскале всё просчитывается в момент компиляции - потому что понятно - кто в кого вложен и как был вызов
Если Вам это не понятно - это не мои проблемы
Oleg N. Cher (19.03.2020)
Вообще доступ к локальным переменным из вложенных процедур организован несколько менее эффективно. Это действительно так. Но ведь можно такие процедуры и не юзать. Вот в Си их вообще нет, и не парятся.
Есть попытки выпустить реализацию Оберона-07 без вложенных процедур. Но это только эксперименты.
Еще раз обращаю внимание A,B и C это процедуры напрямую вложенные в процедуру D, но процедура A вызывается через B или C, хотя можно еще и напрямую из D вызвать. Возможные состояния стека:
Avars Bvars Dvars
Avars Cvars Dvars
Avars Dvars
Как образом при компиляции здесь можно подсчитать где окажутся переменные процедуры D в тот момент когда вызвана процедура A?
Доступ к таким локальным переменным идёт по смещению, передаваемому извне при вызове вложенной процедуры. О чём спор вообще?
hobot (20.03.2020)
Немного инфы перед анонсом большего для pdp-11:
Код:C:\ming-w64\bin> pdp11-aout-gcc -v Using built-in specs. COLLECT_GCC=pdp11-aout-gcc COLLECT_LTO_WRAPPER=c:/ming-w64/bin/../libexec/gcc/pdp11-aout/10.0.1/lto-wrapper.exe Target: pdp11-aout Configured with: ../configure --prefix=/opt/pdp11/ming-w64 --target=pdp11-aout --host=i686-w64-mingw32 --disable-shared --enable-static --disable-threads --disable-multilib --enable-languages=c,c++ --disable-libstdcxx --disable-libsanitizer --disable-gold --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libssp --disable-nls --disable-plugin --disable-silent-rules --disable-sjlj-exceptions --without-headers --without-isl --without-cloog --enable-stage1-checking --disable-libgcc --with-gmp=/opt/pdp11/ming-w64 --with-mpfr=/opt/pdp11/ming-w64 --with-mpc=/opt/pdp11/ming-w64 --without-iconv Thread model: single Supported LTO compression algorithms: zlib gcc version 10.0.1 20200318 (experimental) (GCC)Код:D:\workspace\pdp11-toolchain\hello-gcc> make pdp11-aout-as -o crt0rt.o crt0rt.s pdp11-aout-gcc -O1 -m10 -c -o hello.o hello.c pdp11-aout-as -o puts.o puts.s pdp11-aout-ld -T pdp11-aout.ld -o hello.out hello.o puts.o -Map=hello.out.map bin2load -a -f hello.out -o hello.lda lda2sav -o hello.sav hello.lda
Правильно понимаю что из нового тут только lda2sav, чтобы использовать этот тулчейн для RT-11 ?
https://github.com/yshestakov/pdp11-...-gcc/lda2sav.c
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Да, правильно.
И свежий GCC (master, 10.0.1) + binutils 2.34, собранный с помощью MinGW в 32-bit Windows executables.
Я чуть позже перенесу (добавлю) в pdp11 бакэнд GCC описание процессоров ВМ1 и ВМ2, чтоб генерился код под них.
Прямо сейчас сборка в виже ZIP лежит у Vslav на сайте:
https://www.1801bm1.com/files/pdp11/cross-compilers/
hobot (20.03.2020), nzeemin (20.03.2020), Oleg N. Cher (20.03.2020), randomizer (20.03.2020), Vslav (20.03.2020)
Тут пока чистый GCC. Как сделаю поддержку ВМ1/ВМ2 - попробую закинуть
Oleg N. Cher (20.03.2020), Vslav (20.03.2020)
Поднимем тему немного.
Решил скинуть сюда отдельные примеры работы с библиотекой ULBLIB (входит в состав RT-11 Source Kit). Вдруг кому пригодится.
Сам многократно писал с нуля функционал который уже есть в этой библиотеке.
Для начала пример обработки ошибок в программе.В принципе тут все должно быть понятно.Код:.MCALL .MODULE .MODULE ULB,RELEASE=V01,VERSION=00,COMMENT=<ERROR HANDLING>,AUDIT=YES .MCALL .EXIT ;SYSTEM MACROS .INCLUD /SY:ULBMAC/ ;ULBLIB MACROS ERAREA: .BLKB ;ERROR CODE .BLKB ;ERROR LEVEL/RETURN FLAG .WORD ERRPRE ;ERROR MESSAGE PREFIX .WORD ERRLEV ;ERROR LEVEL BYTE .WORD ERRTAB ;ERROR MESSAGE OFFSET TABLE .BLKW ;FILE NAME BLOCK/ADDRESS OF STRING .WORD $ABORT ;ABORT ENTRY ERRPRE: .NLCSI TYPE=I,PART=PREFIX ERRLEV: .ASCII /X-/<200> .EVEN MSGLST ERRTAB ERRMSG ERR,<Just an error> ERRMSG WAR,<Warning and nothing more> ERRMSG FIL,<File error > ERRMSG STR,<Error with string > ERRMSG FAT,<Fatal error> MSGEND DBLK: .RAD50 /SY FILNAMTYP/ TEXT: .ASCII /"Hi there"/<200> .EVEN $START:: .ERR #ERAREA,#ERR,LEVEL=FATAL,RETURN=YES .ERR #ERAREA,#WAR,LEVEL=WARNING,RETURN=YES .ERR #ERAREA,#FIL,LEVEL=FATAL,FILE=#DBLK,RETURN=YES .ERR #ERAREA,#STR,LEVEL=PADLA,ASCII=#TEXT,RETURN=YES .ERR #ERAREA,#FAT,LEVEL=U BR $START $ABORT:: .EXIT .END $START
Определяется таблица ERRTAB.
В этой таблице определяются сообщения с уникальным кодом.
Код занимает один байт со знаком.
Положительные значения назначаются автоматически макрокомандой ERRMSG.
Отрицательные значения зарезервированы для файловых и прочих системных ошибок (об этом в другой раз).
Таблиц может быть несколько, хотя скорее всего одной хватит.
Макрокоманда .ERR вызывает печать сообщения с заданным уровнем (используется первая буква).
Если указан адрес стандартного блока имени файла - к сообщению добавляется имя файла.
Если указан адрес дополнительной строки - к сообщению добавляется строка.
Одновременно указать блок имени файла и дополнительную строку нельзя.
Для стандартных уровней (W,E,F,U) устанавливаются правильные биты в байте ошибки программы (@#53).
Если не указан RETURN=YES, возврата не происходит, управление передается на заданную в блоке описания точку входа.
Как-то так
- - - Добавлено - - -Код:.EX UL/LINK:SY:ULBLIB ?ULB-F-Just an error ?ULB-W-Warning and nothing more ?ULB-F-File error SY:FILNAM.TYP ?ULB-P-Error with string "Hi there" ?ULB-U-Fatal error .
Здесь без примеров.
Просто описание вызовов.
Вызов $INIDM можно так же вызвать повторно чтобы освободить всю выделенную ранее память (предварительно нужно обнулить второе слово $FRHD).Код:;CALL $INIDM -- Инициализация динамической памяти. ; ;На входе: ; R0 - Адрес двухсловного массива $FRHD (нужно определить в программе) ; +00 - начальный адрес используемой памяти (обычно содержимое @#50 плюс 2) ; +02 - 0 ; ;На выходе: ; C - 0=успех, 1=ошибка ; R0 - Размер свободной памяти в байтах ; @#50 - Максимальный доступный программе адрес ;CALL $RQCB -- Запрос блока динамической памяти ; ;На входе: ; R0 - адрес $FRHD ; R1 - размер блока в байтах ; ;На выходе: ; C - 0=успех, 1=ошибка ; R0 - адрес выделенного блока памяти ; R1 - реальный размер выделенного блока памяти ;CALL $RLCB - Освобождение блока памяти ; ;На входе: ; R0 - Адрес $FRHD ; R1 - Размер блока памяти ; R2 - Адрес блока памяти
Память выделяется сверху вниз. Если планируется вызывать подпрограммы работы с файлами из ULBLIB, сразу после инициализации динамической памяти стоит выделить "в пустоту" блок памяти под USR (не требуется в XB/XM/ZB/ZM или если выгрузка USR запрещена). Размер USR в байтах можно получить по смещению 374 от начала RMON.
Так же не требуется выделять блок памяти под USR если все нужные драйвера гарантированно загружены.
Для вывода сообщения об ошибке выделения памяти можно воспользоваться макрокомандой .ERR как показано выше со стандартным кодом FE.NOM.
- - - Добавлено - - -
Здесь кратко о макросах/подпрограммах ULBLIB для работы с файлами.
Начало программы может выглядеть примерно так:Для работы с файлами средствами ULBLIB используются дескрипторы фалов (FDB).Код:$FRHD:: .BLKW 2 ;ЗАГОЛОВОК СПИСКА СВОБОДНОЙ ПАМЯТИ OUTSPC: .BLKW 3*5 ;БЛОКИ ВЫХОДНЫХ ФАЙЛОВ INPSPC: .BLKW 6*4 ;БЛОКИ ВХОДНЫХ ФАЙЛОВ DEFEXT: .RAD50 /INPOUTOUTOUT/ ;РАСШИРЕНИЯ ФАЙЛОВ ПО УМОЛЧАНИЮ ;+ ;ТОЧКА ЗАПУСКА. ;- $START:: MOV @#50,R0 ;ПОЛУЧАЕМ ВЕРХНИЙ АДРЕС TST (R0)+ ;СЛЕДУЮЩИЙ АДРЕС - НАЧАЛО СВОБОДНОЙ ;ПАМЯТИ MOV R0,$FRHD ;СОХРАНЯЕМ ЕГО ;+ ;ТОЧКА ПОВТОРНОГО ВХОДА. ;- $RETRY: MOV #$FRHD+4,R5 ;АДРЕС ЗАГОЛОВКА (+4) CLR -(R5) ;ИНИЦИАЛИЗИРУЕМ ЗАГОЛОВОК MOV -(R5),R4 ;ПОЛУЧАЕМ АДРЕС НАЧАЛА СВОБОДНОЙ ;ПАМЯТИ MOV R4,R0 ;КОПИРУЕМ ДЛЯ ИСПОЛЬЗОВАНИЯ TST -(R0) ;ПРЕДЫДУЩИЙ АДРЕС - ВЕРХ ПРОГРАММЫ .SETTOP ;ВОССТАНАВЛИВАЕМ ВЕРХНИЙ АДРЕС ; ;ВЕРХНИЙ АДРЕС ВОССТАНАВЛИВАЕТСЯ ЧТОБЫ ИЗБЕЖАТЬ ЛИШНЕЙ АКТИВНОСТИ С ФАЙЛОМ ;SWAP.SYS ПРИ ВЫХОДЕ ИЗ ПРОГРАММЫ. ; .SRESET ;ЗАКРЫВАЕМ ОТКРЫТЫЕ КАНАЛЫ, ;ВЫГРУЖАЕМ ЗАГРУЖЕННЫЕ ДРАЙВЕРЫ ; ;В ЭТОМ МЕСТЕ: ; R5 = АДРЕС ЗАГОЛОВКА СПИСКА СВОБОДНОЙ ПАМЯТИ ; R4 = НАЧАЛЬНЫЙ АДРЕС СВОБОДНОЙ ПАМЯТИ ; ;МЫ ИСПОЛЬЗУЕМ .CSISPC, ВСЕ ОСТАЛЬНЫЕ ОПЕРАЦИИ ВЫПОЛНЯЮТСЯ СРЕДСТВАМИ ;БИБЛИОТЕКИ ULBLIB. ; 10$: MOV @#42,SP ;ВОССТАНАВЛИВАЕМ УКАЗАТЕЛЬ СТЕКА .CSISPC #OUTSPC,#DEFEXT,#0,R4 ;РАЗБИРАЕМ КОМАНДНУЮ СТРОКУ ; ;КОМАНДНАЯ СТРОКА ЧИТАЕТСЯ С ТЕРМИНАЛА ИЛИ ИЗ КОМАНДНОГО ФАЙЛА, ;ПРОВЕРЯЕТСЯ НА СООТВЕТСТВИЕ CSI, ОБРАБОТКА ОШИБОК ПРОИСХОДИТ ;ПРИ ЭТОМ БЕЗ НАШЕГО УЧАСТИЯ. ; ;R4 ССЫЛАЕТСЯ НА КОПИЮ КОМАНДНОЙ СТРОКИ ДЛЯ ДОПОЛНИТЕЛЬНОЙ ПРОВЕРКИ. ; ........................................................................... ; ;ЗДЕСЬ И ДАЛЕЕ СЧИТАЕМ ЧТО СОДЕРЖИМОЕ РЕГИСТРОВ R4 И R5 ОСТАЛОСЬ ТЕМ ЖЕ, ;ЧТО БЫЛО ВЫШЕ. ; ;ИНИЦИАЛИЗИРУЕМ ДИНАМИЧЕСКУЮ ПАМЯТЬ. ; .GVAL R4,#300 ;ЧИТАЕМ КОНФИГУРАЦИЮ СИСТЕМЫ MOV R0,-(SP) ;СОХРАНЯЕМ НА ПОТОМ .GVAL R4,#374 ;ЧИТАЕМ РАЗМЕР USR MOV R0,-(SP) ;СОХРАНЯЕМ НА ПОТОМ MOV R5,R0 ;ЗАГОЛОВОК CALL $INIDM ;ИНИЦИАЛИЗИРУЕМ ПАМЯТЬ BCC 30$ ;CC - OK 20$: .ERR #ERAREA,#FE.NOM,LEVEL=F ;МАЛО ПАМЯТИ 30$: MOV (SP)+,R1 ;ВОССТАНАВЛИВАЕМ РАЗМЕР USR BIT #1000,(SP)+ ;USR ВСЕГДА В ПАМЯТИ? BNE 40$ ;ДА MOV R5,R0 ;ЗАГОЛОВОК CALL $RQCB ;РЕЗЕРВИРУЕМ ПАМЯТЬ ПОД USR ;(ТРЕБУЕТСЯ ДЛЯ .FETCH) BCS 20$ ;CS - МАЛО ПАМЯТИ 40$:
Для открытия файлов по дескриптору используется макрокоманда .OPEN.Код:;+ ;ДЕСКРИПТОРЫ ФАЙЛОВ. ;ИСХОДЯЩЕМУ ПРИВЯЗЫВАЕМ КАНАЛ 0, ВХОДЯЩЕМУ КАНАЛ 1. ;МАКСИМАЛЬНАЯ ДЛИНА СТРОКИ - 132. БАЙТА, ;РАЗМЕР РАБОЧЕГО БУФЕРА - 512. БАЙТ. ; ;ЕСЛИ НЕ ПЛАНИУРЕТСЯ РАБОТА СО СТРОКАМИ (БУДУТ ИСПОЛЬЗОВАНЫ ВЫЗОВЫ ;.READ/.WRITE), RECSIZ И BUFSIZ ДОЛЖНЫ БЫТЬ РАВНЫ 0. ;- OUTFDB: .FILE <OUT>,0,OUTSPC,RECSIZ=132.,BUFSIZ=512. INPFDB: .FILE <IN>,1,INPSPC,RECSIZ=132.,BUFSIZ=512.
При этом выделяется память под драйвер (если нужно), загружается драйвер (если нужно), выделяется память под рабочий буфер (если указано).
Входящие файлы открываются с помощью .LOOKUP, исходящие - с помощью .ENTER.Последовательное чтение строк из файла выполняется макрокомандой GET$S.Код:MOV #OUTFDB,R2 ;ДЕСКРИПТОР ФАЙЛА .OPEN R2,R5 ;ОТКРЫВАЕМ ФАЙЛ BCC 60$ ;CC - OK ; ;ОБРАБОТКА ОШИБОК РАБОТЫ С ФАЙЛОМ. ;R2 У НАС СОДЛЕРЖИТ АДРЕС FDB. ; 50$: .ERR #ERAREA,F.ERR(R2),LEVEL=F,FILE=F.OPNM(R2) ;ОБРАБОТКА ОШИБОК 60$:
В случае ошибки будет установлен бит C.
R0 после вызова GET$S ссылается на FDB.
Код ошибки можно получить по смещению F.ERR дескриптора файла.
Код FE.EOF означает, что во входящем файле больше нечего читать.
Последовательная запись строк в файл выполняется макрокомандой PUT$S.Код:;+ ;СЧИТАЕМ ЧТО В R2 У НАС АДРЕС FDB ВХОДЯЩЕГО ФАЙЛА ;- GET$S R2 ;ЧИТАЕМ СТРОКУ BCC 70$ ;CC - OK CMPB #FE.EOF,F.ERR(R0) ;КОНЕЦ ФАЙЛА? BNE 50$ ;НЕТ, ОШИБКА ; ;ЗДЕСЬ МОЖНО ЗАВЕРШИТЬ РАБОТУ С ФАЙЛАМИ И ПЕРЕЙТИ К ОБРАБОТКЕ СЛЕДУЮЩЕЙ ;КОМАНДЫ. ; ........................................................................... 70$: MOV F.NRBD+2(R0),R1 ;ПОЛУЧАЕМ АДРЕС СТРОКИ MOV F.NRBD(R0),R2 ;ПОЛУЧАЕМ ДЛИНУ СТРОКИ
В случае ошибки будет установлен бит C.
R0 после вызова PUT$S ссылается на FDB.Если для чтения/записи файла используются макрокоманды .READ/.WRITE, для обработки ошибок нужно сконвертировать код RT-11 в код ошибки для .ERR.Код:;+ ;СЧИТАЕМ ЧТО В R2 У НАС АДРЕС FDB ИСХОДЯЩЕГО ФАЙЛА, ;В R1 - АДРЕС СТРОКИ, В R3 - ДЛИНА. ;- PUT$S R2,R1,R3 ;ЗАПИСЫВАЕМ СТРОКУ BCS 50$ ;CS - ОШИБКА
Для этого есть подпрограммы $IERR (для .READ/.READC/.READW) и $OERR (для .WRITE/.WRITC/.WRITW).
Обе подпрограммы на входе требуют адрес FDB в R1, на выходе C устанавливается, F.ERR(R1) содержит код ошибки, пригодный для .ERR.Для закрытия файла используется подпрограмма $CLOSE.Код:.READW #AREA,#1,#BUFF,#WCNT,#BLKN ;ВЫПОЛНЯЕМ ЧТЕНИЕ BCC OK ;CC - OK MOV R2,R1 ;FDB CALL $IERR ;КОНВЕРТИРУЕМ КОД ОШИБКИ BR 50$ ;ОБРАБАТЫВАЕМ ОШИБКУ
На входе R0 должен содержать адрес FDB.
Подпрограмма $CLOSE записывает остатки рабочего буфера в исходящий файл и закрывает его.
Входящий файл можно так же закрыть просто макрокомандой .PURGE или .CLOSE на соответствующем канале.Примерно такКод:MOV R2,R0 ;FDB CALL $CLOSE ;ЗАКРЫВАЕМ ФАЙЛ BCS 50$ ;CS - ОШИБКА
Последний раз редактировалось form; 15.05.2020 в 18:09.
PDP-11/83, Электроника МС0511 (УК-НЦ), DECserver 90M
Q-Bus: H9278-A, DLV11-J, DZQ11, DHV11, DELQA-M, LPV11, CQD-420/TM, DRV11
PMI: KDJ11-BF, MSV11-JE
VT220, CM7209
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)