hobot, можно конкретную ссылку на диск? и желательно командники для сборки.
Вид для печати
hobot, можно конкретную ссылку на диск? и желательно командники для сборки.
к сложным вариантам можно отнести
Код:ПРОГРАММА PRUN
Программа PRUN предназначена для запуска кода на периферийном процессоре.
УКНЦ. Для работы достаточно скопировать файл PRUN.SAV на SY:, написать
программу (код не обязательно делать позиционно-незвисимым), скомпилить
и собрать в виде перемещаемой программы (.REL) командой LINK/FOREGROUND.
Для выхода из ПП программы можно использовать команду RETURN (при этом
область памяти, выделенная под программу, останется зантой или передать
управление подпрограмме освобождения памяти по адресу 176300:
MOV #начальныйадрес,R1
JMP @#176300
Приведенный ниже пример печатает "Хочу пива !!!" в центре нижней служебной
строки и выходит, освобождая занятую память.
Сборка и запуск программы:
.MAC PPTEST
.LIN/FO PPTEST
.PRUN PPTEST
.TITLE PPTEST -- ТЕСТ ПРОГРАМИРОВАНИЯ ПП
.IDENT /V01.00/
START: MOV #TEXT+1,R0 ;КОНВЕРТИРУЕМ СТРОКУ ТЕКСТА
10$: TSTB @R0 ; В РУССКИЙ ЯЗЫК
BEQ 20$ ;
CMPB #'@,(R0)+ ;
BHI 10$ ;
BISB #200,-1(R0) ;
BR 10$ ;
20$: EMT 56 ;ПЕЧАТАЕМ СТРОКУ В НИЖНЕЙ
.WORD TEXT ; СЛУЖЕБНОЙ СТРОКЕ
MOV #START,R1 ;ОСВОБОЖДАЕМ ПАМЯТЬ И ВЫХОДИМ
JMP @#176300 ;
TEXT: .ASCIZ <14.>/hO^U PIWA!!!/ ;ТЕКСТ ДЛЯ СЛУЖЕБНОЙ СТРОКИ
.END START
К сложным вариантам можно отнести программы с перекрытиями (резидентными на диске и в памяти) и виртуальные массивы FORTRAN
Ну если уж отвечать на сообщение 8-летней давности, так хоть ссылки давать.
Видимо вот этот ассемблер имеется в виду - https://github.com/alemorf/pdp11asm - за него ничего не скажу. не использовал.
Под УКНЦ работает родная RT-11, так что мне кажется более естественным и надёжным использовать родные MACRO и LINK, которые можно запускать через RT-11 Simulator от Patron - см. http://emulator.pdp-11.org.ru/RT-11/distr/ и https://zx-pk.ru/threads/24755-emulyator-rt-11.html
Собственно для своих проектов я так и делаю.
Кроме того, есть кросс-ассемблер macro11 от Richard Krehbiel - например тут: https://github.com/shattered/macro11
И ещё до кучи я дописываю кросс-линкер - см. https://github.com/nzeemin/pclink11 и https://zx-pk.ru/threads/30666-pclin...kovshchik.html
Любопытно распознает ли он символы длинной более 6? Не могу себе представить большой проект без человекочитаемых символов.
Именно из-за этого ограничения я стал использовать GNU Assembler несмотря на некоторые неудобства. (А из замеченных недостатков, он не проверят что переход по инструкции BR не вышел за предел 64-х слов)
Распознавать он может и распознает, но проблема в том, что если использовать стандартный LINK - всё равно упрёмся в шесть символом. Стандартный формат OBJ таков. Так что для полной поддержки нужен и транслятор и линкер. При этом трансляторы, которые были написаны в те времена - они практически все (если не все) использовали стандартный OBJ, со всеми вытекающими...
Форкнут. живет и поддерживается тут
https://github.com/simh/simtools/tre...mblers/macro11
есть какой-то способ - "обнулить всю память за одну команду". Может кто знает ? (помню, что работает не на всех реализациях PDP-11)
За одну не получится. Но если подготовить регистры, то можно
Не совсем за одну.
Есть способ обнулить память и чисто остановиться (речь разумеется идет о ситуации когда управление памятью выключено). Выглядит это так:Результатом будет непрерывное выполнение команды CALL -(PC) по адресу 0, что вызовет последовательную запись нулей вниз, начиная с адреса 157776. Конечным итгогом будет запись 0 - команды HALT - по адресу 0 и выполнение ее.Код:MOV #160000,SP
MOV #4747,@#0
CLR PC
Стоит отметить, что способ не сработает на процессорах с защитой стека - там раньше произойдет прерывание по границе стека.
Есть еще вариант - команда MOV -(PC),-(PC) которая копирует сама себя вниз по памяти, но тут завершение не будет чистым :)
да, наверное, это именно то. Не совсем в одну команду - сначала в стек заносится, наверное, конец памяти. Но потом (точно помню - одна команда).
Думаю в Вашем варианте - одна лишняя. А на каких именно машинах работало, а на каких - нет не помню. Даже пробовали типы процессоров таким "тестом" определять. Вроде - порядок выполнения (очередность действий "внутри" команды) у разных процессоров разная.
- - - Добавлено - - -
лишняя команда, наверное - HALT, в пульт можно и вручную переключить (и убедиться, что память обнулилась). Чем завершалось(каким событием) - не помню.
Машины были скорее всего : 100/25; 11/34; разные Воронежские на 1811(F-11); разные на J-11 и 1831; МС1201.01-02; самодельные на 1807ВМ1(T-11).
Можно и сейчас попробовать запускать на разных, но сначала интересно сократить "программку" именно до одной команды.
То, то! Просто в R6 заносишь 160000, по нулевому адресу пишешь 4747 и пускаешь машинку с нулевого адреса.
Работало на всех машинках без ДП. В частности, я это делал на Э-60 с процессором М2, на ДВК с 1801ВМ1 и ВМ2. А вот на ВМ3 - облом, вылетает куда-то по прерыванию (Trap to 4 ? - Не помню) с 000400 (376? 374? Тоже не помню...) в R6. То есть, очищена память 400-157776, а 0-376 - нет.
Ни одной лишней нету.
Разве что выставить регистры и содержимое ячейки 0 из пульта - тогда останется только сама одна команда :)
Вот на них как раз такой способ работать не будет - как только SP снизится ниже 400, возникнет прерывание по вектору 4.
...которой тут нету в принципе - она самогенерящаяся в конце :)
Так она сама собой организуется. Если смотреть на то, что предложил коллега form, лишние все команды, ибо действия на ДВК следующие
R6/xxxxxx 160000<Enter>
0/xxxxxx 4747<Enter>
0G
На УКНЦ действия примерно те же, только служебные кнопки другие. В частности, вместо G давят, вроде-бы, ИСП. Ну не помню я пультовой режим УКНЦ...
с J-11 - понятно с М2 и 1201.01-02 - тоже.
на каких еще из перечисленных мной будет работать на каких нет ?
Вроде разбирались тогда и пришли к выводу, что порядок выполнения команд у разных процессоров - разный (что-то в процессе выполнения команды выполняется в разной очередности - сначала делается одно, потом другое - при одинаковом результате в итоге и в данном случае препятствует выполнению (обнулению памяти). Запустили бы на разных машинах (у кого какие есть) да и в разных эмуляторах при разных конфигах и сообщили бы о результате.
В советских не особо силен. У ВМ3 есть ненастраиваемое YSA прерывание.
Насчет Э100/25 не уверен, но либо в нем, либо в СМ1420 - в том что 22-битный - есть регистр SL (177774) в котором выставляется ограничение стека (скорее всего все-таки в СМ1420).
- - - Добавлено - - -
У разных процессоров разное поведение. В DECовском описании J11 в конце есть таблица различий. Опираясь на эти различия и прочие обвески DECовская программа автоконфигурации определяет тип процессора.
Многие подобные команды при компиляции выдают ошибку Z чтобы показать что они неоднозначны. Например JMP (R0)+, MOV R0,(R0)+ итд.
В каком-то драйвере для УК-НЦ видел MOV PC,LABEL - это тоже неоднозначная команда, и ее спасает только, что драйвер кроме как на УКНЦ нигде не работает :)
Как я и говорил - чисто за одно команду не получится.
Если же вспомнить СМ-4 с памятью с контролем чётности, где нам было по барабану - что прописано, главное, что бы прописалось - то мы записывали в 157776 код 14747 и пускали с адреса 157776. Результат - все контрольные биты в памяти были проинициализированы.
замораживаться должен регистр текущего значения (который 0177714).
=== ребята, у меня такой вопрос, как мне содержимое оттуда получить в переменную
в простой программе на Паскале для функции Random ? иначе при первом запуске всегда
одинаковое расположение псевдослучайных элементов ?
Загадайте число, быть может оно пригодится вам ТАМ... (с) Сталкер, или как его там...
Сколько лет Ваше Превосходительство рассчитывает находиться у власти? (с) Анчурия.
Оба числа используются для установки ГСЧ. Как в Сталкере - не знаю, а в Анчурии - банально: перед запуском игры делают
Ну, там перед этим огранияивают это N до 200 или что-то в том же духе, но это мелочи. Заодно можно считерить - набирай то число, которое ты запомнил с прошлого удачного раза и будет тебе счастье!..Код:1630 FOR I=1 TO N
1640 LET G2=RND(N)
1650 NEXT I
AFZ, готовой RND и RANDOMIZE для OMSI Pascal"я нет, как и модуля CRT (!)
Скрытый текст
Вопрос в том, неужели нет шансов использовать значение таймера?
Функция RND (ранее уже публиковал, это из школьных времён черновика)
может через переменную типа REGISTER можно? по аналогии с RA и RD клавиатуры?Код:FUNCTION RND: REAL;
VAR IRND: INTEGER;
BEGIN
/*$C
BR M1
RN: .WORD 435
M1: MOV RN, R1
MUL #12869, R1
ADD #6925, R1
MOV R1, RN
BIC #^O100000, R1
MOV R1, IRND(SP)
*/
RND:=IRND/32767;
END;
[свернуть]
В тему разработки на MACRO-11, нашёл для себя вот такой приём.
Иногда бывает что нужно контролировать выход кода за некоторую границу - дальше идут данные с фиксированного адреса, т.е. их нельзя двигать.
Раньше я это делал вручную, иногда забывая и отлавливая глупые ошибки из-за этого.
Собственно нашёл вот такой вариант, с использованием директивы .IIF:
Получается что .IIF сработает, если текущий адрес станет больше заданного, тогда в код добавится строчка "ERR023", что приведёт к появлению неопределённой метки, и на линковке вы это увидите в сообщении об ошибке.Код:; до этого тут блок кода
.IIF GT <.-023340>, ERR023
.=023340
; дальше тут данные с фиксированного адреса
.IIF GT <.-023340>, .ERROR ; ERR023
"Быстрый" рандомайзер. Это с вики. Линейный сдвиговый регистр.
Рандом в R0. Он хуже прочих, но довольно быстр. Можно применить разные ухищрения чтобы получить более-менее рандомное число.Код:.radix 16
LFSR00: .WORD 0ACE1
LFSR01: .WORD 0B400
RANDOM: mov R1, -(SP)
mov LFSR00, R0
mov LFSR01, R1
clc
ror R0
bcc 2$
xor R1, R0
2$: mov R0, LFSR00
mov (SP)+, R1
return
.radix 8
Так и делаем. Все равно будет циклично.
Вопрос по теме! Как работать из OMSI Pascal с бинарными файлами?
FILE OF CHAR читается через READ только до первого встреченного нуля.
Есть там ещё какие-то хитрые GET и PUT, но я не понял как они работают.
Предположительно: бинарные файлы побайтово читать нельзя, нужно только через буферы. Плоховасто. :-(
Насколько мне помнится, должно проходить что то типа
Дальше пример не из RT, а из RSX, но насколько мне помнится, в OMSI всё было очень похожеКод:
TYPE BYTE =0..255; /* не помню все встроенные типы, если вдруг такого нет */
BINARY = FILE OF BYTE;
С ходу программы, которая работала бы без буфера - не нашел. А с двоичными файлами и буфером:
Код:PROGRAM SYSTEM_GENERATION;
CONST
BUFF_LAST = 377B;
(* NEXT CONSTANT - FROM FILE RTS.MAC,
( ALSO, MODULE PDP11 CONTAIN IT ) *)
INITIAL_START_ENTRY = 452B;
INITIAL_START_STACK_BOTTOM = 454B;
INITIAL_START_STACK_LIMIT = 456B;
LOADER_INFO = 460B;
TYPE
CARDINAL =0..65535;
FLAG_TYPE =(ENTRY_POINT_FLAG,
CODE_FLAG,
LINKER_TABLE_FLAG,
DEBUGGER_TABLE_FLAG,
OLD_LOAD_KEY_FLAG,
NEW_LOAD_KEY_FLAG,
FIRST_FREE_LOC_FLAG,
OLD_FIRST_FREE_LOC_FLAG,
MAX_FLAG);
FLAG_SET =SET OF FLAG_TYPE;
FILE_NAME =PACKED ARRAY [1..35] OF CHAR;
BLOCK =0..BUFF_LAST;
BIG_BUFFER=ARRAY [BLOCK] OF CARDINAL;
WORK =FILE OF BIG_BUFFER;
DOUBLE =ARRAY [0..1] OF CARDINAL;
VAR
FOUND : FLAG_SET;
FLAG : FLAG_TYPE;
WHERE,
WORD,
NBYTES,
I,
X : CARDINAL;
LOD_NAME,
RTS_NAME,
TSK_NAME : FILE_NAME;
LOD_FILE,
RTS_FILE,
TSK_FILE : WORK;
EOF_LOD_FILE : BOOLEAN;
CH : CHAR;
CHECK_SUM : CARDINAL;
BUFFER_R : BIG_BUFFER;
INDEX_R,
LIMIT_R : BLOCK;
SYSTEM_ENTRY_POINT_VALUE: CARDINAL;
SYSTEM_LOAD_KEY_VALUE : CARDINAL;
OLD_FREE_LOC : CARDINAL;
FIRST_FREE_LOC : CARDINAL;
BUFFER_W : BIG_BUFFER;
INDEX_W,
CURRENT_BLOCK,
LIMIT_W : CARDINAL;
LIMIT_RTS : CARDINAL;
RTS_BLOCK : CARDINAL;
EOF_RTS_FILE : BOOLEAN;
PROCEDURE EXITST(I: INTEGER ); EXTERNAL;
FUNCTION FLGTYP(WORD: CARDINAL): FLAG_TYPE; EXTERNAL;
PROCEDURE INIT_TTIO;
BEGIN
IF INPUT^ <> ' ' THEN
REPEAT
READ(CH)
UNTIL CH = ' ';
END (* INIT_TTIO *);
PROCEDURE HALT(I: CARDINAL);
BEGIN
CASE I OF
1: WRITELN('LOD INPUT FILE HAS WRONG FORMAT');
2: WRITELN('NO ENTRY POINT BLOCK FOUND ON LOD INPUT FILE');
3: WRITELN('NO NEW KEY BLOCK FOUND ON LOD INPUT FILE');
4: WRITELN('NO FIRST FREE LOC BLOCK FOUND ON LOD INPUT FILE');
5: WRITELN('SINTAX ERROR IN FILE NAME');
6: WRITELN('EOF REACHED ON LOD INPUT FILE');
7: WRITELN('CHECK. SUMM ERROR ON LOD INPUT FILE');
8: WRITELN('BOTH PARTS OF SYSTEM TRY TO OCCUPY SAME LOCATION');
9: WRITELN('EOF REACHED ON RTS INPUT FILE');
10: WRITELN('NO OLD FIRST FREE LOC BLOCK FOUND ON LOD INPUT FILE');
ELSE WRITELN('UNKNOWN ERROR')
END;
EXITST(4)
END (* HALT *);
PROCEDURE READ_FILE_NAME(VAR F_N: FILE_NAME;
VAR S : BOOLEAN;
VAR D : BOOLEAN );
VAR
I: INTEGER;
BEGIN
FOR I:=1 TO 35 DO F_N[I]:=CHR(0);
I:=0;
S:=FALSE;
D:=FALSE;
REPEAT
I:=I+1;
READ(F_N[I]);
IF F_N[I] = ' ' THEN BEGIN
IF EOLN AND (I=1) THEN D:=TRUE;
I:=I-1
END;
UNTIL EOLN OR EOF OR D OR (I>=34);
IF EOF THEN EXITST(0);
IF EOLN AND (I<=34) THEN S:=TRUE;
IF EOLN OR (I>=34) THEN READLN;
END (* READ_FILE_NAME *);
(*-------------------rabota s LOD-fajlom--------------------*)
PROCEDURE READ_SECTOR;
BEGIN
BUFFER_R:=LOD_FILE^;
GET(LOD_FILE);
INDEX_R:=0;
LIMIT_R:=BUFFER_R[BUFF_LAST];
IF LIMIT_R=0 THEN EOF_LOD_FILE:=TRUE;
END;
PROCEDURE READ_AND_CHECK;
VAR
X : CARDINAL;
BEGIN
IF EOF_LOD_FILE THEN
HALT(6)
ELSE BEGIN
X:=BUFFER_R[INDEX_R];
INDEX_R:=INDEX_R+1;
IF INDEX_R = LIMIT_R THEN
IF LIMIT_R = BUFF_LAST THEN
READ_SECTOR
ELSE
EOF_LOD_FILE := TRUE;
IF CHECK_SUM <> X THEN HALT(7)
END;
END (* READ_AND_CHECK *);
PROCEDURE READ_WORD(VAR X:CARDINAL);
BEGIN
IF EOF_LOD_FILE
THEN HALT(6)
ELSE
BEGIN
X := BUFFER_R[INDEX_R];
INDEX_R := INDEX_R + 1;
IF INDEX_R = LIMIT_R
THEN
IF LIMIT_R = BUFF_LAST
THEN READ_SECTOR
ELSE EOF_LOD_FILE :=TRUE;
CHECK_SUM := CHECK_SUM + X
END;
END;
PROCEDURE SKIP_RECORD( COUNT : CARDINAL );
VAR
X : CARDINAL;
BEGIN
WHILE COUNT > 0 DO BEGIN
READ_WORD(X);
COUNT := COUNT - 1
END
END;
PROCEDURE START_READ;
BEGIN
CHECK_SUM := 0;
EOF_LOD_FILE := FALSE;
READ_SECTOR
END;
PROCEDURE OPEN_READ;
VAR
SUCCESS,
DEFAULT : BOOLEAN;
BEGIN
WRITE('MODULA-2 PROGRAM LOAD FILE >');
READ_FILE_NAME(LOD_NAME,SUCCESS,DEFAULT);
IF SUCCESS
THEN
IF DEFAULT
THEN RESET(LOD_FILE,'SY:MOD.LOD/SE/RO')
ELSE RESET(LOD_FILE,LOD_NAME,'SY:MOD.LOD/SE/RO')
ELSE
HALT(5);
START_READ
END;
PROCEDURE RE_OPEN_READ;
BEGIN
RESET(LOD_FILE);
START_READ
END;
PROCEDURE CLOSE_READ;
BEGIN
CLOSE(LOD_FILE)
END;
(*---------------------rabota s TSK-fajlom---------------*)
PROCEDURE WRITE_SECTOR;
VAR
I : BLOCK;
BEGIN
SEEK(TSK_FILE,CURRENT_BLOCK);
TSK_FILE^ := BUFFER_W;
PUT(TSK_FILE);
INDEX_W := 0;
CURRENT_BLOCK := CURRENT_BLOCK + 1
END;
PROCEDURE WRITE_WORD( W : CARDINAL );
VAR
I : BLOCK;
BEGIN
IF W <> 0
THEN
IF BUFFER_W [INDEX_W] <> 0
THEN
HALT(8)
ELSE
BUFFER_W[INDEX_W] := W;
IF INDEX_W < BUFF_LAST
THEN
INDEX_W := INDEX_W + 1
ELSE
BEGIN
WRITE_SECTOR;
IF LIMIT_W < CURRENT_BLOCK
THEN
BEGIN
FOR I := 0 TO BUFF_LAST DO BUFFER_W [I] := 0;
LIMIT_W := CURRENT_BLOCK
END
ELSE
BEGIN
BUFFER_W := TSK_FILE^;
GET(TSK_FILE)
END
END
END;
PROCEDURE WRITE_ZERO_LABEL_BLOCK;
VAR
I : BLOCK;
BEGIN
FOR I := 0 TO BUFF_LAST DO BUFFER_W[I] := 0;
WRITE_SECTOR;
WRITE_SECTOR
END;
PROCEDURE START_WRITE( WHERE : CARDINAL );
VAR
I : CARDINAL;
BEGIN
CURRENT_BLOCK := ( WHERE DIV (( BUFF_LAST+1)*2)) + 3;
INDEX_W := ( WHERE DIV 2 ) MOD ( BUFF_LAST+1 );
IF LIMIT_W < CURRENT_BLOCK
THEN
BEGIN
FOR I := 0 TO BUFF_LAST DO BUFFER_W [I] := 0;
REPEAT
LIMIT_W := LIMIT_W + 1;
IF LIMIT_W < CURRENT_BLOCK
THEN
BEGIN
SEEK(TSK_FILE,LIMIT_W);
TSK_FILE^ := BUFFER_W;
PUT(TSK_FILE)
END;
UNTIL LIMIT_W = CURRENT_BLOCK
END
ELSE
BEGIN
SEEK(TSK_FILE,CURRENT_BLOCK);
BUFFER_W := TSK_FILE^
END
END;
PROCEDURE END_WRITE;
BEGIN
WRITE_SECTOR
END;
PROCEDURE OPEN_WRITE;
VAR
I : INTEGER;
POINT : BOOLEAN;
BEGIN
FOR I := 1 TO 35 DO TSK_NAME[I] := CHR(0);
I := 1;
WHILE ( LOD_NAME[I] <> CHR(0) ) AND
( LOD_NAME[I] <> '.' ) AND
( LOD_NAME[I] <> ';' ) AND
( I <= 34 ) DO BEGIN
TSK_NAME[I] := LOD_NAME[I];
I := I + 1
END;
IF I = 1
THEN
REWRITE(TSK_FILE,'SY:MOD.TSK/SE/NOBL/RW')
ELSE
BEGIN
LOD_NAME[I] := '.';
LOD_NAME[I+1] := 'T';
LOD_NAME[I+2] := 'S';
LOD_NAME[I+3] := 'K';
REWRITE(TSK_FILE,TSK_NAME,'SY:MOD.TSK/SE/NOBL/RW')
END;
INDEX_W := 0;
LIMIT_W := 1;
CURRENT_BLOCK := 1
END;
PROCEDURE CLOSE_WRITE;
BEGIN
CLOSE(TSK_FILE)
END;
PROCEDURE TRANSFER_RECORD( C,A : CARDINAL );
VAR
X : CARDINAL;
BEGIN
START_WRITE(A);
WHILE C > 0 DO BEGIN
READ_WORD (X);
WRITE_WORD(X);
C := C - 1
END;
END_WRITE
END;
(*--------------------rabota s RTS--------------------*)
PROCEDURE READ_RTS_SECTOR;
BEGIN
RTS_BLOCK := RTS_BLOCK + 1;
SEEK(RTS_FILE,RTS_BLOCK);
BUFFER_R := RTS_FILE^;
GET(RTS_FILE);
INDEX_R := 0
END;
PROCEDURE READ_RTS_WORD( VAR X : CARDINAL);
BEGIN
IF EOF_RTS_FILE
THEN
HALT(9)
ELSE
BEGIN
X := BUFFER_R[INDEX_R];
IF RTS_BLOCK < LIMIT_RTS DIV ((BUFF_LAST+1)*2) + 3
THEN
IF INDEX_R < BUFF_LAST
THEN
INDEX_R := INDEX_R + 1
ELSE
READ_RTS_SECTOR
ELSE
IF INDEX_R < ( LIMIT_RTS DIV 2 ) MOD ( BUFF_LAST+1 )
THEN
INDEX_R := INDEX_R + 1
ELSE
EOF_RTS_FILE :=TRUE
END
END;
PROCEDURE MERGE_RTS;
VAR
I : BLOCK;
X : CARDINAL;
F1 : CARDINAL;
F2 : CARDINAL;
BEGIN
FOR I := 0 TO BUFF_LAST DO BUFFER_W[I] := BUFFER_R[I];
LIMIT_RTS := BUFFER_R [5];
CURRENT_BLOCK := 1;
WRITE_SECTOR;
START_WRITE(0);
READ_RTS_SECTOR; (* 2 BLOCK *)
READ_RTS_SECTOR; (* 3 BLOCK *)
REPEAT
READ_RTS_WORD(X);
WRITE_WORD(X);
UNTIL EOF_RTS_FILE;
END_WRITE;
CURRENT_BLOCK := 1;
SEEK(TSK_FILE,CURRENT_BLOCK);
BUFFER_W := TSK_FILE^;
IF (FIRST_FREE_LOC MOD 100B) = 0 THEN FIRST_FREE_LOC := FIRST_FREE_LOC+1;
F1 := ( FIRST_FREE_LOC DIV 100B )*100B + 77B;
F2 := ( FIRST_FREE_LOC + 77B ) DIV 100B;
(* HIGHEST VIRT. ADR., MAPPED BY ADR. WINDOW 0 *)
BUFFER_W [5] := F1;
(* HIGHEST TASK VIRTUAL ADDRESS (=BUFFER_W[5]) *)
BUFFER_W [6] := F1;
(* TASK LOAD SIZE IN 64(10)-WORDS BLOCKS (SIZE OF THE ROOT SEGMENT) *)
BUFFER_W [7] := F2;
(* TASK MAXIMUM SIZE IN 64(10)-WORDS BLOCKS. = THE SIZE OF THE
ROOT SEGMENT + ANY ADDITIONAL PHYSICAL MEMORY, NEEDED TO CONTAIN
TASK OVERLAYS *)
BUFFER_W [8] := F2;
(* TASK EXTENSION - UP TO 64 KB *)
BUFFER_W [352B DIV 2] := 2000B-F2;
(* RELATIVE BLOCK NUMBER OF R/O IMAGE *)
BUFFER_W [364B DIV 2] := FIRST_FREE_LOC DIV (( BUFF_LAST+1)*2) + 4;
TSK_FILE^ := BUFFER_W;
PUT(TSK_FILE);
CURRENT_BLOCK := 3;
SEEK(TSK_FILE,CURRENT_BLOCK);
BUFFER_W := TSK_FILE^;
(* INITIAL STACK POINTER *)
BUFFER_W [8] := 0; (* WE ARE USED ALL 64 KB MEMORY *)
TSK_FILE^ := BUFFER_W;
PUT(TSK_FILE)
END;
PROCEDURE OPEN_RTS_READ;
VAR
S,
D : BOOLEAN;
BEGIN
WRITE(CHR(15B));
WRITELN(' FILE OF RUN TIME SYSTEM OR');
WRITE ('<CR> FOR DEFAULT MS:[1,54]RTS.TSK:');
READ_FILE_NAME(RTS_NAME,S,D);
IF S
THEN
IF D
THEN
RESET(RTS_FILE,'MS:[1,54]RTS.TSK/RO/SE')
ELSE
RESET(RTS_FILE,RTS_NAME,'SY:[1,54]RTS.TSK/RO/SE')
ELSE
HALT(5);
RTS_BLOCK := 0;
READ_RTS_SECTOR;
LIMIT_RTS := 177777B
END;
PROCEDURE CLOSE_RTS_READ;
BEGIN
CLOSE(RTS_FILE)
END;
PROCEDURE WRITE_LUN_BLOCK;
VAR
I : CARDINAL;
BEGIN
CURRENT_BLOCK := 2;
SEEK(TSK_FILE,CURRENT_BLOCK);
FOR I := 1 TO BUFF_LAST DO BUFFER_W [I] := 0;
FOR I := 1 TO 16 DO BUFFER_W [2*I-2] := 54523B;
FOR I := 19 TO 20 DO BUFFER_W [2*I-2] := 54523B;
BUFFER_W [2*17-2] := 44524B;
BUFFER_W [2*18-2] := 44524B;
WRITE_SECTOR
END;
PROCEDURE WRITE_COMMUNICATION_AREA;
BEGIN
START_WRITE(INITIAL_START_ENTRY);
WRITE_WORD(SYSTEM_ENTRY_POINT_VALUE);
END_WRITE;
START_WRITE(INITIAL_START_STACK_BOTTOM);
WRITE_WORD(0); (* USE ALL MEMORY *)
END_WRITE;
START_WRITE(INITIAL_START_STACK_LIMIT);
WRITE_WORD (FIRST_FREE_LOC);
END_WRITE;
START_WRITE(LOADER_INFO);
WRITE_WORD (SYSTEM_LOAD_KEY_VALUE);
END_WRITE;
END;
(*---------------------M A I N---------------------*)
BEGIN
INIT_TTIO;
OPEN_READ;
OPEN_WRITE;
WRITE_ZERO_LABEL_BLOCK;
FOUND := [];
WHILE NOT EOF_LOD_FILE DO BEGIN
READ_WORD(X);
FLAG := FLGTYP(X);
READ_WORD(NBYTES);
READ_WORD(WHERE);
IF FLAG >= MAX_FLAG THEN HALT(1);
FOUND := FOUND+[FLAG];
CASE FLAG OF
ENTRY_POINT_FLAG : SYSTEM_ENTRY_POINT_VALUE := WHERE;
NEW_LOAD_KEY_FLAG : SYSTEM_LOAD_KEY_VALUE := WHERE;
OLD_FIRST_FREE_LOC_FLAG : OLD_FREE_LOC := WHERE;
FIRST_FREE_LOC_FLAG : FIRST_FREE_LOC := WHERE;
ELSE
END;
IF FLAG = CODE_FLAG
THEN TRANSFER_RECORD((NBYTES-6) DIV 2, WHERE)
ELSE SKIP_RECORD ((NBYTES-6) DIV 2 );
READ_AND_CHECK
END;
IF NOT (ENTRY_POINT_FLAG IN FOUND) THEN HALT(2);
IF NOT (NEW_LOAD_KEY_FLAG IN FOUND) THEN HALT(3);
IF NOT (OLD_FIRST_FREE_LOC_FLAG IN FOUND) THEN HALT(10);
IF NOT (FIRST_FREE_LOC_FLAG IN FOUND) THEN HALT(4);
TRANSFER_RECORD(0,FIRST_FREE_LOC-1);
CLOSE_READ;
OPEN_RTS_READ;
MERGE_RTS;
CLOSE_RTS_READ;
WRITE_COMMUNICATION_AREA;
WRITE_LUN_BLOCK;
CLOSE_WRITE;
WRITELN('END SYSTEM GENERATION ');
END.
Oleg N. Cher, ты раздел "работы с файлами" 1 раз прочитай и все вопросы исчезнут ) В целом по Паскалю, лучше бы конечно в теме Паскаля + МАКРО11 обсуждать = ибо ближе к теме легче потом нужную инф. найти.
- - - Добавлено - - -
и конечно при работе с файлами надо контроллировать моментКод:8.1.1. ПРОЦЕДУРЫ РАБОТЫ С ФАЙЛАМИ
PUT(F)
- ПРИСОЕДИНЯЕТ ЗНАЧЕНИЕ БУФЕРНОЙ ПЕРЕМЕННОЙ F^ К ФАЙЛУ
"F". ОПРЕДЕЛЕНО ТОЛЬКО В СЛУЧАЕ, КОГДА ПЕРЕД ИСПОЛНЕНИЕМ
ЗНАЧЕНИЕ ПРЕДИКАТА EOF(F) ЕСТЬ TRUE; EOF(F) СОХРАНЯЕТ
ЗНАЧЕНИЕ TRUE, ЗНАЧЕНИЕ ЖЕ F^ СТАНОВИТСЯ НЕОПРЕДЕЛЕННЫМ;
GET(F)
- СМЕЩАЕТ ТЕКУЩУЮ ПОЗИЦИЮ ФАЙЛА (ГОЛОВКУ ЧТЕНИЯ-ЗАПИСИ) НА
СЛЕДУЮЩУЮ КОМПОНЕНТУ И ПРИПИСЫВАЕТ ЗНАЧЕНИЕ ЭТОЙ
КОМПОНЕНТЫ БУФЕРНОЙ ПЕРЕМЕННОЙ F^. ЕСЛИ СЛЕДУЮЩЕЙ
КОМПОНЕНТЫ НЕ СУЩЕСТВУЕТ, ТО ЗНАЧЕНИЕМ ЕОF(F) СТАНОВИТСЯ
TRUE, А ЗНАЧЕНИЕ F^ НЕ ОПРЕДЕЛЕНО. РЕЗУЛЬТАТ GET(F)
OПРЕДЕЛЕН ТОЛЬКО ТОГДА, КОГДА ПЕРЕД ИСПОЛНЕНИЕМ
СООТВЕТСТВУЮЩЕГО ВЫЗОВА EOF(F)=FАLSE;
RESET(F)
- ВОЗВРАЩАЕТ ТЕКУЩУЮ ПОЗИЦИЮ ФАЙЛА В НАЧАЛО ФАЙЛА И
ПРИПИСЫВАЕТ БУФЕРНОЙ ПЕРЕМЕННОЙ F^ ЗНAЧЕНИЕ ПЕРВОГО
ЭЛЕМЕНТА "F". ЗНАЧЕНИЕМ EOF(F) СТАНОВИТСЯ FALSE, ЕСЛИ
"F" НЕ ПУСТ; В ПРОTИВНОМ СЛУЧАЕ F^ НЕ ОПРЕДЕЛЕНО, А
ЗНАЧEНИЕМ EOF(F) ОСТАЕТСЯ TRUE;
REWRITE(F)
- УНИЧТОЖАЕТ ТЕКУЩЕЕ ЗНАЧЕНИЕ "F", ТАК ЧТО МОЖЕТ НАЧАТЬСЯ
ЗАПОЛНЕНИЕ НОВОГО ФАЙЛА; EOF(F) ПРИНИМАЕТ ЗНАЧЕНИЕ TRUE;
BREAK(F)
- ВЫЗЫВАЕТ НЕМЕДЛЕННЫЙ ВЫВОД ВОЗМОЖНО ЕЩЕ НЕПОЛНОГО БУФЕРА
(БЛОКА) В ФАЙЛ. ЭТО НАДО ИСПОЛЬЗОВАТЬ ПРИ РАБОТЕ С
ТЕРМИНАЛОМ, НАПРИМЕР, ДЛЯ ВЫВОДА ПОДСКАЗКИ ИЛИ
СООБЩЕНИЯ. СЛЕДУЕТ ОТМЕТИТЬ, ЧТО ДАННЫЙ ПАСКАЛЬ НЕ
БУФЕРИЗУЕТ РАБОТУ С ДРАЙВЕРАМИ,О КОТОРЫХ ИЗВЕСТНО ЧТО
ОНИ ЯВЛЯЮТСЯ "ИНТЕРАКТИВНЫМИ", ТАКИМИ КАК ВЫХОДНОЙ ФАЙЛ
ПО УМОЛЧАНИЮ .
PAGE(F)
- ЗАСТАВЛЯЕТ ПРИНТЕР ПЕРЕХОДИТЬ НА НАЧАЛО НОВОЙ СТРАНИЦЫ
ПЕРЕД ПЕЧАТЬЮ СЛЕДУЮЩЕЙ СТРОКИ ТЕКСТОВОГО ФАЙЛА.
ПРИМЕР:
VAR F:TEXT;
BEGIN
REWRITE(F,'TT:');
WRITELN(F,'ВВЕДИТЕ КОМАНДНУЮ СТРОКУ');
BREAK(F); (* ВЫВЕСТИ ДАННЫЕ НА ТТ: *)
END.
CLOSE(F)
- ПЕРЕСЫЛАЕТ НА ВНЕШНЕЕ УСТРОЙСТВО НЕ ДО КОНЦА ЗАПОЛНЕННЫЙ
БУФЕР, УСТРАНЯЕТ СВЯЗЬ С ВНЕШНИМ ФАЙЛОМ И ОСВОБОЖДАЕТ
БУФЕРНУЮ ПАМЯТЬ ДЛЯ ИСПОЛЬЗОВАНИЯ ЕЕ В ДРУГИХ ЦЕЛЯХ.
ПРОЦЕДУРЫ "RESET" ИЛИ "REWRITE" ДОЛЖНЫ ПРЕДШЕСТВОВАТЬ
ВСЯКОЙ РАБОТЕ С ФАЙЛОВОЙ ПЕРЕМЕННОЙ.
П_Р_И_М_Е_Ч_А_Н_И_Е. ПРОЦЕДУРA "CLOSE" ВСЕГДА ДОЛЖНА
ИСПОЛЬЗОВАТЬСЯ В КОНЦЕ РАБОТЫ С ФАЙЛОМ, СОЗДАННЫМ ПРОГРАММОЙ
(ВЫХОДНЫМ ФАЙЛОМ), ИНАЧЕ МОЖНО ПОТЕРЯТЬ ПОСЛЕДНИЙ БУФЕР,КОТОРЫЙ
НЕ БУДЕТ ЗАПИСАН В ФАЙЛ. ЗАКРЫВАНИЕ ФАЙЛОВ ДЛЯ ВВОДА НЕ ЯВЛЯЕТСЯ
ОБЯЗАТЕЛЬНЫМ, НО ПОЗВОЛЯЕТ ОСВОБОДИТЬ БУФЕРНУЮ ПАМЯТЬ.
8.1.2. ДОПОЛНИТЕЛЬНЫЕ АРГУМЕНТЫ ДЛЯ "RESET" И "REWRITE"
В ДАННОЙ РЕАЛИЗАЦИИ РАСШИРЕНЫ СТАНДАРТНЫЕ ПРОЦЕДУРЫ "RESET"
И "REWRITE" ТРЕМЯ ДОПОЛНИТЕЛЬНЫМИ ПАРАМЕТРАМИ ДЛЯ УКАЗАНИЯ СВЯЗИ
МЕЖДУ ВНУТРЕННИМИ ФАЙЛОВЫМИ ПЕРЕМЕННЫМИ И ФАЙЛАМИ НА ВНЕШНИХ
УСТРОЙСТВАХ
PROCEDURE RESET(F:FILE;NAME,DEFEXT:STRING;
VAR LEN:INTEGER)
ПРОЦЕДУРА RESET СВЯЗЫВАЕТ ФАЙЛОВУЮ ПЕРЕМЕННУЮ С СУЩЕСТВУЮЩИМ
ВНЕШНИМ ФАЙЛОМ, А ТАКЖЕ УСТАНАВЛИВАЕТ УКАЗАТЕЛЬ ФАЙЛА НА ПЕРВЫЙ
ЭЛЕМЕНТ (ЗАПИСЬ). "F" ВСЕГДА ДОЛЖНА ПРИСУТСТВОВАТЬ И БЫТЬ
ФАЙЛОВОЙ ПЕРЕМЕННОЙ. ИМЯ ФАЙЛА "NAME" И РАСШИРЕНИЕ ИМЕНИ ФАЙЛА
ДОЛЖНЫ ИМЕТЬ ТИП "ARRAY OF CHAR".
ИМЯ ФАЙЛА ДОЛЖНО СООТВЕТСТВОВАТЬ ПРИНЯТОМУ В ОСДВК
СТАНДАРТНОМУ ОБОЗНАЧЕНИЮ И МОЖЕТ ВКЛЮЧАТЬ ИМЯ И НОМЕР УСТРОЙСТВА,
А ТАКЖЕ ТИП ФАЙЛА. ЕСЛИ ВО ВТОРОМ ПАРАМЕТРЕ ОТСУТСТВУЕТ ТИП
ФАЙЛА,ТО ПО УМОЛЧАНИЮ БУДЕТ ИСПОЛЬЗОВАН ТИП "DAT".
ПЕРЕМЕННАЯ "LEN" ПОЛУЧИТ ЗНАЧЕНИЕ, РАВНОЕ ЧИСЛУ БЛОКОВ ПО
512 БАЙТ В ФАЙЛЕ, ЛИБО - 1, ЕСЛИ ФАЙЛ НЕ НАЙДЕН. СЛЕДУЕТ УЧЕСТЬ,
ЧТО ЕСЛИ ЭТОТ ПАРАМЕТР НЕ ИСПОЛЬЗОВАН, ТО ОТСУТСТВИЕ ФАЙЛА
ПРИВЕДЕТ К ФАТАЛЬНОЙ ОШИБКЕ ПРОГРАММЫ.
PROCEDURE REWRITE(F:FILE; NAME,DEFEXT:STRING;
VAR LEN:INTEGER)
ПРОЦЕДУРА "REWRITE" СОЗДАЕТ НОВЫЙ ФАЙЛ НА ВНЕШНЕМ
УСТРОЙСТВЕ. ПАРАМЕТРЫ "NAME" И "DEFEXT" ИМЕЮТ ТО ЖЕ ЗНАЧЕНИЕ
(СМЫСЛ), ЧТО И ДЛЯ ПРОЦЕДУРЫ "RESET". ПАРАМЕТР "LEN" УКАЗЫВАЕТ
РАЗМЕР СОЗДАВАЕМОГО ФАЙЛА В БЛОКАХ ПО 512 БАЙТ.
ПРИМЕР:
VAR NAME: ARRAY[1..20] OF CHAR;
INF,OUTF: TEXT;
(* ОПРЕДЕЛЕНО В СИСТЕМЕ КАК "FILE OF CHAR *)
LEN: INTEGER;
BEGIN
(* СВЯЗАТЬ OUTF С УСТРОЙСТВОМ ПЕЧАТИ *)
REWRITE(OUTF,'LP:');
REPEAT
WRITE('FILENAME: ');
(* ЗАПРОСИТЬ ИМЯ ФАЙЛА С ТЕРМИНАЛА *)
READLN(NAME);
(*СВЯЗАТЬ INF С СУЩЕСТВУЮЩИМ ФАЙЛОМ *)
RESET(INF,NAME,'PAS',LEN)
(* ПОВТОРЯТЬ ПОКА ФАЙЛ НЕ БУДЕТ ОТКРЫТ *)
UNTIL LEN<>-1;
END.
"конец строки" стандартные функции EOLN и "конец файла" EOF
Код:
WHILE NOT EOF(F) DO
BEGIN P(F^); GET(F)
END
Хобот, ты конечно красава. У тебя есть пример рабочего кода, который ты точно проверил, и он работает?
Про GET и PUT я уже прочитал, но нихрена не понял как они работают. Дайте примеров кода.
Не возражаю против переноса моих сообщений в нужную тему.
Hunta, спасибо конечно, но то простыня необозримейшая. А попроще никак нельзя? Создавать вручную буфер, когда ОС уже сама создала буфер - получится двойная буферизация. И только потому, что файл не текстовый. Или я что-то не так понял?
- - - Добавлено - - -
Вот это:
за пример кода не катит, хорошо? Потому что непонятно, что такое P, ну и F тоже. К тому же, никто не проверял как оно работает с бинарными файлами. Но вообще доку по Паскалю мне цитировать не надо, я её уже видел.Код:WHILE NOT EOF(F) DO
BEGIN P(F^); GET(F)
END
Ничем не могу помочь
Ни RT, ни RSX не буферизует
Писал в конце 90-ых, я не буду сейчас разбираться, чего там и как
Оно РАБОТАЕТ (написано мной для меня, так что гарантируется) с двоичными файлами и создает файл в формате задачи для RSX (двоичный) из результата компиляции-линковки программы на Modula-2
- - - Добавлено - - -
Простыня - это несколько десятком листов (по 92 строки на лист) программы на фортране, состоящей из пяти-десяти подпрограмм. А этот пример - так, на один зуб.
Код:HD7>PASDWK SHONC,TT:=SHONC
SHOWONC OMSI PASCAL-1 RT11 V1.1G 4- -88 Page 1
Univ. Tasmania, Info. Sciences, Physics Bldg, Hobart 7001, site #72-12
LINE STMT LEVEL NEST SOURCE STATEMENT
1 PROGRAM SHOWONC;
2 VAR
3 SYM: CHAR;
4 INF: FILE OF CHAR;
5 BEGIN
6 1 1 1 RESET(INF,'ONC.DAT');
7 2 1 1 WHILE NOT EOF DO
8 3 1 2 BEGIN
9 4 1 3 READ(INF,SYM);
10 5 1 3 WRITE(SYM:1);
11 6 1 3 END;
12
13 7 1 1 CLOSE(INF);
14 8 1 1 WRITELN;
15 9 1 1 END.
ERRORS DETECTED: 0
FREE MEMORY: 9835 WORDS
ERRORS DETECTED: 0
FREE MEMORY: 9835 WORDS
HD7>RU SHONC
OLEG_N_CHER DETECTED ! END OF FILE ON DEVICE - FROM PC 004542
HD7>TY ONC.DAT
OLEG_N_CHER DETECTED !
HD7>TY SHONC.PAS
PROGRAM SHOWONC;
VAR
SYM: CHAR;
INF: FILE OF CHAR;
BEGIN
RESET(INF,'ONC.DAT');
WHILE NOT EOF DO
BEGIN
READ(INF,SYM);
WRITE(SYM:1);
END;
CLOSE(INF);
WRITELN;
END.
HD7>