Не ясна логика проверки ;)
Вид для печати
Тогда что есть CMP (R0)+,(R0)+
:)
Не знание предмета
- - - Добавлено - - -
Что можно творить на MACRO-11
Код:PROCEDURE READ1
;
; R0 - sector num
; R1 - word count - zeroed
; R2 - memory address - updated
;
; in work
; R3 - sector count
;
BEGIN
LET R4 := BTCSR2
LET (R4) := #DC.STA!DC.NIE
LET R3 := R1 OFF.BY #377
SWAB R3
IF #377 SET.IN R1 THEN
LET R3 := R3 + #1
END
; R3 sector count
LET R4 := R4 + #P$STAT-P$CSR2
REPEAT
LET R5 :B= (R4)
.ASSUME CS.BSY EQ <^O200>
UNTIL RESULT IS PL AND #CS.DRD SET.IN R5
LET R4 := R4 + #P$SCNT-P$STAT
LET (R4)+ := R3 ; 24
.ASSUME P$SNUM EQ <P$SCNT+2>
LET (R4)+ := R0 ; 26
.ASSUME P$CYLL EQ <P$SNUM+2>
SWAB R0
LET (R4)+ := R0 ; 30
.ASSUME P$CYLH EQ <P$CYLL+2>
LET (R4)+ := @#B$DEVU ; 32
.ASSUME P$DH EQ <P$CYLH+2>
LET (R4)+ := BTDH ; 34
.ASSUME P$CMD EQ <P$DH+2>
LET (R4) := #CS.RD ; 36
REPEAT
REPEAT
LET R5 :B= (R4)
.ASSUME CS.BSY EQ <^O200>
UNTIL RESULT IS PL AND #CS.DRQ SET.IN R5
IF #CS.ERR SET.IN (R4) GOTO 80$
LET R4 := R4 + #P$DBUF-P$STAT
THRU R3 := #256.
IF R1 NE #0 THEN
LET (R2)+ := (R4)
LET R1 := R1 - #1
ELSE
TST (R4)
END
END
LET R4 := R4 + #P$STAT-P$DBUF
UNTIL R1 EQ #0
LET CARRY := OFF
RETURN
80$:
RESET
JMP BIOERR
END READ1
ок, попробую по другому спросить, вы видите ошибку явно там,
где у меня "мёртвая зона" и так
[CODE]
1. сойдёт я получил за вариант с ADD #2,R1
на замену этой команды form посоветовал оптимизацию TST (R1)+
я конечно как честный Паскале-Любитель синтаксис ассембл. не совсем
чётко понимаю, но я забыл о чотности и что арифметика "словесная",
то есть смещение ()+ всегда на 2 и только байтовая может быть нечётной
получив такую рекомендацию я пишу код в моём понимании означающий
MOV @#50,R1 ; КЛАДЁМ СОДЕРЖИМОЕ ЯЧЕЙКИ 50 В R1
TST (R1)+ ; form ПОЯСНИЛ, ЧТО ЭТО ПРОВЕРКА НА СУЩЕСТВ. АДРЕСА
; НУЖНОГО, ДАЛЕЕ Я ПИШУ
BEQ GOGOGO ; ЕСЛИ РЕЗУЛЬТАТ ПРЕД.-ЕЙ КОМАНДЫ 0 ЗНАЧИТ ВСЁ ОК И
; МЫ ИДЁМ ФЭТЧИТЬ ДРАЙВЕР, И СЛЕДУЩИЕ ДВЕ СТРОКИ ПЕРЕД
МЕТКОЙ GOGOGO - ЭТО сообщение об ошибке и екзит
за что сразу учебником по макушке%
господа не лишайте стипендии в чём ошибка,
помните вы смотрите на бублик изнутри, я же снаружи да ещё через упаковку ) две разницы !
В ячейке 50 - последний используемый (в данный момент) программой адрес. Нуля там не будет в принципе. Первый свободный - последний используемый + 2. В .FETCH надо указать - с какого адреса грузить. Поскольку первый свободный - это последний используемый + 2 - берём содержимое ячейки 50, добавляем два и этот адрес указываем в вызове .FETCH.
Знающие систему команд и способы адресации PDP-11 вместо ADD #2 используют TST (R1)+, которая сделает следующее - возьмёт содержимое R1, извлечёт содержимое ячейку по адресу, извлечённому из R1 (попутно устанавливая или сбрасывая флаги), увеличит извлечённое из R1 значение на 2 (поскольку команда словная) и запишет обратно в R1. Нас интересует только воздействие на R1, поэтому дальше никаких проверок флагов не делается (хотя обычно после TST они проверяются тем или иным способом). Возможная проблема - R1 указывает на несуществующую память и мы словим прерывание по V4 - в данном случае неактуальна, потому что @#50 всегда (ну, точнее, если мы работает под RT11) указывает на существующую память (последняя ячейка программы).Код:MOV @#50, R1
ADD #2, R1
.FETCH R1, #CL
- - - Добавлено - - -
Вдогонку
Возможные проблемы в коде в сообщении
- после программы не достаточно памяти для загрузки выбранного драйвера (не сильно страшно, подозреваю, что монитор откажется грузить, если памяти не хватает)
- насколько я понял из описания, .FETCH не корректирует значение в @#50, в R0 он возвращает адрес следующей ячейки памяти после загруженного драйвера (а это уже серьёзней, код из другого места может взять содержимое из ячейки @#50 и затереть драйвер)
- даже если за .RELEASE идёт .EXIT - отсутствие .RELEASE - это неряшливый стиль, в результате чего могут появиться вопросы и который потенциально может привести к ошибкам в программе - человек просто забудет написать .RELEASE там, где он точно нужен и потенциально получить нехватку памяти
Правильный подход
- получить информацию (включая размер) о драйвере
- сохранить текущую верхнюю границу + 2
- используя текущую верхнюю границу программы и размер драйвера - посчитать новую и установить её, используя .SETTOP (попутно установится и новое значение в @#50
- загрузить драйвер, используя сохранённое значение из 2-ого пункта
плюс в каждом пункте проверять корректность выполнения действий в пункте
Да, границы проверяются. Даже в старых SJ где много чего без всяких проверок делается.
Добавлю: предварительно сохранить старое значение и восстановить его перед переходом в точку следующего цикла программы (если программа циклическая [например просит ввода команды]) или просто обнулить @#50 перед выходом - это позволит предотвратить лишнюю дисковую активность после .EXIT.
классная шпора-исходник на последнем образе
Код:; ПРОГРАММИРОВАНИЕ КЛЮЧЕЙ
; =======================
.MCALL .EXIT
PKL: MOV #TKL,R1
BR 1$
2$: TSTB @#177564
BPL 2$
MOVB R0,@#177566
1$: MOVB (R1)+,R0
BNE 2$
.EXIT
TKL:
.ASCII <33><164><60><60>/*/
.ASCII \-KK ZNKT\<15> ;- К1
.ASCII \-EX ZNKT\<15> ;- К2
.ASCII \-ZNKT\<15> ;- К3
.ASCII \- \ ;- К4
.ASCII \- \ ;- К5
.ASCII \-*\
.ASCII <33><164><61><60>/*/
.ASCII \-Dir .BAK\<15> ;- НР/К1
.ASCII \-Dir/fu\<15> ;- НР/К2
.ASCII \-Copy/pred (\ ;- НР/К3
.ASCII \-).mac SY:\<15> ;- НР/К4
.ASCII \-Del/noq .BAK\<15> ;- НР/К5
.ASCII \-*\
.ASCII <33><164><62><60>/*/
.ASCII \-\<33>\P\<33>\?wLIST \ ;- УПР/К1
.ASCII \-\<33>\P\<33>\?wQUIT\<33>\?M\ ;- УПР/К2
.ASCII \-\<33>\P\<33>\?wEDIT \ ;- УПР/К3
.ASCII \- \ ;- УПР/К4
.ASCII \-\<33>\P\<33>\?wEXIT\<33>\?M\ ;- УПР/К5
.ASCII \-*\
.ASCII <33><164><63><60>/*/
.ASCII \-Dir/bad/fi\<15> ;- ФИКС/К1
.ASCII \-Copy/w/dev SY: DK:\<15> ;- ФИКС/К2
.ASCII \-Del/noq .BAK\<15> ;- ФИКС/К3
.ASCII \-Sq/noq DK:\<15> ;- ФИКС/К4
.ASCII \- \ ;- ФИКС/К5
.ASCIZ \-*\
.EVEN
.END PKL
с того же образа "скомпилировал" MUZ.MAC
ПРОГРАММА успешно запустилась, ищет - хочет в качестве мелодийКод:! Apxивный paздeл ЖД ! ЛAТ
M У З Ы К A Л Ь Н Ы Й M A Г A З И Н
=====================================
Н A Б O P M E Л O Д И Й
-------------------------
1 - MEЛOДИЯ 1 ( M1 )E
2 - MEЛOДИЯ 2 ( M2 )
3 - MEЛOДИЯ 3 ( M3 )
4 - MEЛOДИЯ 4 ( M4 )
5 - MEЛOДИЯ 5 ( M5 )
6 - MEЛOДИЯ 6 ( M6 )
7 - MEЛOДИЯ 7 ( M7 )
8 - MEЛOДИЯ 8 ( M8 )
9 - MEЛOДИЯ 9 ( M9 )
0 - BЫXOД
! Apxивный paздeл ЖД !
Mn.TXT пронумерованные файлы. Подсовывал ей M1.TXT для теста,
содеращего мелодию из MUZRED.SAV - сплошной гул стандартным
звуком на выходе, прервать и выйти в монитор только через
стоп>0>исп получилось. Шпоры-описания к ней нет увы, как понять
что она хочет в качестве нот ???
там и коментарии есть о входящем формате я ничего не увидел кроме заранее прописанных имён файлов,
как я понял там что с таймером связано, а сама программа кидается в ОЗУ ПП
Код:; *********************************************
; * *
; * М У З Ы К А Л Ь Н Ы Й М А Г А З И Н *
; * *
; *********************************************
; L9 = 0
MUZ:: .MCALL .EXIT,.LOOKUP,.READW,.CLOSE
; К О Н С Т А Н Т Ы
; =================
N = 40 ;- начало координат
.IF DF,L9
RSK2PR = 177510
RDK2PR = 177512
RSK2PD = 177514
RDK2PD = 177516
RSK3PD = 176554
RDK3PD = 176556
.IFF
RSK2PR = 176660
RDK2PR = 176662
RSK2PD = 176664
RDK2PD = 176666
RSK3PD = 176674
RDK3PD = 176676
.ENDC
; И Н И Ц И А Л И З А Ц И Я
; =========================
MINMUZ: CLR @#177560
; М О Н И Т О Р
; =============
MONMUZ: JSR R5,PCS ;- заголовок
TZAG
JSR R5,PMENU ;- главное меню
TGMENU,SCGM
BNE PMUZ ;- на чтение файла
WYH: JSR R5,PCS
TWMUZ
MOV #100,@#177560
.EXIT ;- выход в систему
PMUZ: JSR PC,PCTF ;- прочитать файл
BEQ MONMUZ
JSR PC,PWMEL ;- выполнить мелодию
BR MONMUZ
; ЧТЕНИЕ ФАЙЛА
; ------------
PCTF: MOV @#SCGM,R0
ASL R0
ASL R0
MOV TABR50(R0),@#SPF+2 ;- установка спецификации файла
MOV TABR50+2(R0),@#SPF+4
.LOOKUP #BUFEMT,#10,#SPF ;- открыть файл
BCS PCOSH
TST R0
BEQ PCOSH
MOV R0,R1
MUL #256.,R1
.READW #BUFEMT,#10,#BUFT,R1,#0 ;- прочитать файл
BCS PCOSH
MOV R0,@#DLF
ASL @#DLF ;- длина файла
MOV R0,R1
PSBK: .CLOSE #10 ;- закрыть файл
TST R1
RTS PC
PCOSH: JSR R5,PCS
TOSH
JSR PC,PRK
CLR R1
BR PSBK
TABR50: .RAD50 /M1 /
.RAD50 /M2 /
.RAD50 /M3 /
.RAD50 /M4 /
.RAD50 /M5 /
.RAD50 /M6 /
.RAD50 /M7 /
.RAD50 /M8 /
.RAD50 /M9 /
SPF: .RAD50 /DK M1 TXT/ ;- спецификация файла
BUFEMT: .BLKW 5
; ВЫПОЛНИТЬ МЕЛОДИЮ
; =================
PWMEL: JSR PC,PPRMEL ;- преобразовать мелодию
MOV #40000,APRPP ;- адрес программы в ПП
MOV #MUZPP,APRCP ;- адрес программы в ЦП
MOV #KMUZPP-MUZPP/2,DLPR ;- длина программы
JSR PC,PZPPP ;- запись программы в ПП и запуск
JSR PC,PIMEL ;- исполнить мелодию
RTS PC
; ПРЕОБРАЗОВАТЬ МЕЛОДИЮ
; ---------------------
PPRMEL: MOV #BUFT,R1 ;- просмотр шапки
1$: CMPB (R1)+,#'/
BNE 1$
CLRB -1(R1)
JSR R5,PCS ;- печать шапки
BUFTK
MOV #BUFT,R2 ;- буфер счетчиков
2$: JSR PC,PCT10C
MOV R3,(R2)+
BNE 2$
CLR (R2)+
RTS PC
; ИСПОЛНИТЬ МЕЛОДИЮ
; -----------------
PIMEL: MOV @#100,-(SP)
MOV #POPT,@#100
TST @#RDK2PR ;- сброс канала
1$: SOB R0,1$
;2$: SOB R0,2$
M0:
4$: MOV #BUFT,R2 ;- буфер счетчиков
2$: TSTB @#RSK2PD
BPL 2$
MOVB (R2)+,@#RDK2PD ;- младший байт частоты
1$: TSTB @#RSK2PD
BPL 1$
MOVB (R2)+,@#RDK2PD ;- старший байт частоты
MOV (R2)+,@#SCT ;- длительность
BEQ 4$
3$: TST @#SCT
BNE 3$
TSTB @#RSK2PR ;- прерывание с клавиатуры?
BPL 2$ ;- нет.
TST @#RDK2PR
KIMEL: MOV (SP)+,@#100
RTS PC
; ПРОГРАММА ОБРАБОТКИ ПРЕРЫВАНИЙ ТАЙМЕРА
; --------------------------------------
POPT: DEC @#SCT
RTI
; ЗАГРУЗКА ПРОГРАММЫ В ПП И ЗАПУСК
; --------------------------------
PZPPP: MOVB #20,KOM
JSR PC,PDABP ; запись программы в ПП
1$: MOVB #30,KOM
JSR PC,PDABP ; запуск программы в ПП
RTS PC
; ПЕРЕДАЧА АДРЕСА БЛОКА ПАРАМЕТРОВ
; --------------------------------
PDABP: MOV #ABLPAR,R1
MOV #4,R2
1$: TSTB @#RSK3PD ; передача байта в канал
BPL 1$
MOVB (R1)+,@#RDK3PD
SOB R2,1$
2$: TSTB @#RSK3PD ; ожидание готовности
BPL 2$
RTS PC
ABLPAR: BLPAR,177777 ;- адрес блока параметров
; БЛОК ПАРАМЕТРОВ
; ---------------
BLPAR: .BYTE 0 ;- ответ
KOM: .BYTE 20 ;- команда
TIPU: .WORD 32 ;- ОЗУ
APRPP: .WORD 40000 ;- адрес программы в ПП
APRCP: .WORD MUZPP ;- адрес программы в ЦП
DLPR: .WORD KMUZPP-MUZPP/2 ;- длина программы
; ПРОГРАММА НА ПП
; ===============
WPKL = 300 ;- вектор клавиатуры
WPK2 = 330
MUZPP: CLR @#177130 ;- сброс диска
MOV #401,@#177054 ;- включить таймер ЦП и выключить таймер ПП
MOV @#WPKL,-(SP) ;- установка векторов
MOV @#WPK2,-(SP)
MOV #<POPKL-MUZPP>+40000,@#WPKL
MOV #<POPK2-MUZPP>+40000,@#WPK2
TST @#RDK2PP ;- сброс канала
4$: MOV #100200,@#177716 ;- генерация звука
MOV CZW,R0
BEQ 1$
2$: SOB R0,2$
MOV #100000,@#177716
MOV CZW,R0
3$: SOB R0,3$
BR 4$
1$: MOV (SP)+,@#WPK2
MOV (SP)+,@#WPKL
MOV #1,@#177054
RTS PC
; ОБРАБОТКА ПРЕРЫВАНИЙ КЛАВИАТУРЫ
; -------------------------------
POPKL: CLR CZW
TST @#177702
MOV #100,@#177072 ;- код завершения на ЦП
RTI
; ОБРАБОТКА ПРЕРЫВАНИЙ КАНАЛА 2
; -----------------------------
RDK2PP = 177062
POPK2: BIT #1,ICZW
BNE 1$
MOVB @#RDK2PP,CZW
INC ICZW
RTI
1$: MOVB @#RDK2PP,CZW+1
INC ICZW
RTI
CZW: .WORD 177777
ICZW: .WORD 0
KMUZPP:
; БИБЛИОТЕКА ПРОЦЕДУР
; ===================
; ПРИЕМ КОДА
; ----------
PRK: TSTB @#177560
BPL PRK
MOV @#177562,R0
RTS PC
; ПЕЧАТЬ КОДА
; -----------
PCK: TSTB @#177564
BPL PCK
MOV R0,@#177566
RTS PC
; ПЕЧАТЬ СЛОВА
; ------------
PCS: MOV (R5)+,R0
PCSR:
1$: TSTB @#177564
BPL 1$
MOVB (R0)+,@#177566
BNE 1$
RTS R5
; НОВАЯ СТРОКА
; ------------
PCNS: JSR R5,PCS
TWKPS
RTS PC
; ЧТЕНИЕ 8-РИЧНОГО ЧИСЛА
; ----------------------
; Вход: R1 - текущий адрес
; Выход: R3 - слово
PCT8C: CLR R3
1$: MOVB (R1)+,R0 ;- поиск первой цифры
BEQ KCT8C
CMP R0,#60
BLO 1$
CMP R0,#67
BHI 1$
2$: BIC #177770,R0 ;- запись триады в R0
ASL R3
ASL R3
ASL R3
BIS R0,R3
MOVB (R1)+,R0 ;- чтение следующей цифры
CMP R0,#60
BLO KCT8C
CMP R0,#67
BHI KCT8C
BR 2$
KCT8C: DEC R1
RTS PC
; ЧТЕНИЕ 10-ТИЧНОГО ЧИСЛА
; -----------------------
; Вход: R1 - текущий адрес
; Выход: R3 - слово
PCT10C: CLR R3
1$: MOVB (R1)+,R0 ;- поиск первой цифры
BEQ KCT8C
CMP R0,#60
BLO 1$
CMP R0,#71
BHI 1$
2$: BIC #177760,R0 ;- запись триады в R0
MUL #10.,R3
ADD R0,R3
MOVB (R1)+,R0 ;- чтение следующей цифры
CMP R0,#60
BLO KCT8C
CMP R0,#71
BHI KCT8C
BR 2$
KCT10C: DEC R1
RTS PC
; ВЫБОР МЕНЮ
; ==========
; Вход: (R5) - текст меню
; - указатель меню
; Выход: SCM - указатель меню
; R0 - код выхода
PMENU:
PMENU0: MOV (R5)+,R1 ;- текст меню
MOVB (R1)+,R2 ;- счeтчик меню
MOV R2,R4 ;- верхняя граница меню
CLR R3 ;- текущий указатель меню
MOV #16,R0 ;- РУС
JSR PC,PCK
3$: CMP R3,@(R5)
BNE 1$
JSR R5,PCS ;- включить инверсию
TWINW
1$: MOV R1,R0 ;- напечатать строку
JSR R5,PCSR
MOV R0,R1
CMP R3,@(R5)
BNE 2$
JSR R5,PCS ;- отключить инверсию
TOINW
2$: INC R3 ;- текущий счетчик
SOB R2,3$
MOV #17,R0 ;- ЛАТ
JSR PC,PCK
5$: JSR PC,PRK ;- принять код
CMP R0,#60 ;- цифра?
BLO 4$ ;- нет.
SUB #60,R0
BNE 11$
MOV R4,R0
11$: DEC R0
CMP R0,R4 ;- проверка на верхнюю границу
BHIS 5$
MOV R0,@(R5) ;- новая активная позиция
10$: TST -(R5) ;- на печать меню
BR PMENU0
4$: CMP R0,#15 ;- ввод?
BEQ KMENU ;- да.
; CMP R0,#40 ;- пробел?
; BEQ KMENU ;- да.
CMP R0,#33 ;- АР2?
BNE 5$ ;- нет.
JSR PC,PRK
CMP R0,#101 ;- стрелка вверх?
BNE 7$ ;- нет.
8$: DEC @(R5)
BPL 10$
MOV R4,@(R5)
BR 8$
7$: CMP R0,#104 ;- стрелка влево?
BEQ 8$
CMP R0,#102 ;- стрелка вниз?
BEQ 6$ ;- да.
CMP R0,#103 ;- стрелка вправо?
BNE 5$ ;- нет.
6$: INC @(R5)
CMP @(R5),R4
BNE 10$
CLR @(R5)
BR 10$
KMENU: DEC R4
CMP @(R5)+,R4 ;- выход из меню
RTS R5
; Т Е К С Т Ы
; ===========
TZAG: .ASCII <14><33><41><33><100><16>
.ASCII <33><131><N+1><N+20.>
.ASCII /М У З Ы К А Л Ь Н Ы Й М А Г А З И Н/
.ASCII <33><131><N+2><N+20.>
.ASCII /=====================================/
.ASCII <33><131><N+6><N+26.>
.ASCII /Н А Б О Р М Е Л О Д И Й/
.ASCII <33><131><N+7><N+26.>
.ASCIZ /-------------------------/
TGMENU: .ASCII <10.>
.ASCIZ <33><131><N+09.><N+29.>/1 - МЕЛОДИЯ 1 ( М1 )/
.ASCIZ <33><131><N+10.><N+29.>/2 - МЕЛОДИЯ 2 ( М2 )/
.ASCIZ <33><131><N+11.><N+29.>/3 - МЕЛОДИЯ 3 ( М3 )/
.ASCIZ <33><131><N+12.><N+29.>/4 - МЕЛОДИЯ 4 ( М4 )/
.ASCIZ <33><131><N+13.><N+29.>/5 - МЕЛОДИЯ 5 ( М5 )/
.ASCIZ <33><131><N+14.><N+29.>/6 - МЕЛОДИЯ 6 ( М6 )/
.ASCIZ <33><131><N+15.><N+29.>/7 - МЕЛОДИЯ 7 ( М7 )/
.ASCIZ <33><131><N+16.><N+29.>/8 - МЕЛОДИЯ 8 ( М8 )/
.ASCIZ <33><131><N+17.><N+29.>/9 - МЕЛОДИЯ 9 ( М9 )/
.ASCIZ <33><131><N+19.><N+29.>/0 - ВЫХОД /<33><131><50><75>
TMENUR: .ASCII <2.>
.ASCIZ <33><131><N+23.><N+4.>/ ПУСК /
.ASCIZ <33><131><N+23.><N+12.>/ ВЫХОД /<33><131><N+23.><N>
;.IF DF,L9
TWINW: .ASCIZ <33><145> ;- включить инверсию
TOINW: .ASCIZ <33><177><145> ;- отключить инверсию
;.IFF
;TWINW: .ASCIZ <33><243> ;- включить инверсию
;TOINW: .ASCIZ <33><277><243> ;- отключить инверсию
;.ENDC
TSBRE: .ASCIZ <14><33><41><33><100> ;- сброс экрана
TZB: .ASCIZ <32><40><32> ;- забой
TNE: .ASCIZ <33><110> ;- начало экрана
TSTPS: .ASCIZ <33><113> ;- стирание последней строки
TWKPS: .ASCIZ <15><12> ;- новая строка
TOSH: .ASCII <33><131><N+22.><N+22.><7><16>
.ASCIZ /*** Файл на диске не обнаружен *** /<17>
TKPCC: .ASCIZ <15><33><101>
TWMUZ: .ASCIZ <14><33><41><33><100><17> ;- выход из программы
.EVEN
SCGM: .WORD 0 ;- счетчик главного меню
SCMR: .WORD 0 ;- счетчик меню режимов
ANTS: .WORD 0 ;- адрес начала теста
DLF: .WORD 0 ;- длина файла
SCT: .WORD 0 ;- счетчик таймера
.WORD 111111
BUFTK: .ASCII <33><131><N+22.><N> ;- коортинаты шапки
BUFT: ;- буфер для текста
.END MUZ
Любопытно существует для PDP-11 реализация какого нибудь быстрого и компактного декомпрессора?
Хочется загружать заранее сжатые данные в битпланы и быстро их оттуда вытаскивать в последствии.
Судя по всему LZ4 то что нужно. Но реализацию на ассемблере и 16-битного проца я нашел только для 8086/8088
Я могу вам дать и декомпрессор на PDP-11 коде и компрессор к нему на C/C++ -- см. https://github.com/nzeemin/ukncbtl-u.../Sav2Cartridge
там реализован и простой RLE, и LZSS (из кода by Ostapenko Alexey).
- - - Updated - - -
Bonus track: вот тут @troosh делал LZ4 в ту же утилиту, но вроде как не доделано - https://github.com/troosh/ukncbtl-utils/commits/master
Кроме выложенного почти год назад распаковщика минимального размера, также сегодня выложил более быстрые варианты за счет unroll циклов.
Впрочем подготовка для раскрученного цикла не бесплатна (подготовка адреса для прыжка внутрь цикла и коррекция счётчика цикла), поэтому могут быть данные на которых выиграша в скорости не будет (как бы вообще не замедлилось). Так что лучше померить скорость разных вариантов. Возможно для разных данных стоит использовать разные версии распаковщика, тоесть в коде программы иметь все версии сразу.
Всё тут: https://github.com/troosh/ukncbtl-ut...tridge/sandbox
[ol]
[li]UNLZ4.MAC - компактный вариант[/li]
[li]UNLZ43.MAC - оба цикла раскручены[/li]
[li]UNLZ42.MAC - только цикл копирования раскручен[/li]
[li]UNLZ41.MAC - только цикл литералов раскручен[/li]
[/ol]
Дальнейшее ускорение возможно за счёт копирования слов, а не байт... Но это снова рост размера распаковщика и риск получить код который не заработает, например, на ВМ3.
Почему размер распаковщика дожен вырасти?
На первый взгляд, если заменить
наКод:4$:
.rept 16.
MOVB (R1)+, (R5)+ ; Копируем строку из
.endr
SOB R2, 4$ ; уже распакованных данных
то размер кода только уменьшится.Код:4$:
.rept 8.
MOV (R1)+, (R5)+ ; Копируем строку из
.endr
SOB R2, 4$ ; уже распакованных данных
Вероятно, потому, что ВМ3 делает Trap to 4 при попытке словной записи по нечетному адресу. В отличие от ВМ1/2 и LSI-11, включая наши ее клоны (Э-60). Правда, и LSI-11, и ВМ1/2 пишут таки по четному адресу, игнорируя этот младший адресный бит (А0), он анализируется только при байтовой записи, блокируя запись в невыбранный байт памяти. LSI-11 при этом (при байтовой записи) выставляет записываемый байт в оба байта шины, а адресный бит рулит тем, какой из них запишется, это заявлено в моей любимой книжке про ЦП М2 (3.858.382 ТО), а как там оно у ВМ1 и ВМ2 - не знаю. Но, по-любому, ломиться с нечетным адресом в программу со словной записью неправильно.
randomizer, troosh, в соседнем разделе форума подвезли реализацию LZSA1 для БК - https://zx-pk.ru/threads/11381-napis...=1#post1030619
Исходник: https://gitlab.com/ivagor/lzsa8080/b...ZSA1/lzsa1.asm
Запаковщик тут: https://github.com/emmanuel-marty/lzsa
Решил с распаковщиками для PDP-11 переехать сюда, т.к. здесь подобные вопросы уже обсуждались.
Выложил распаковщик LZSA2 (и обновил LZSA1). Он толще и медленнее LZSA1, зато сжатие заметно лучше. Ну и оптимизировать скорее всего можно.
- - - Добавлено - - -
Хотя надо отметить, что команды ВМ2 в распаковщиках я не использовал (ASH вроде подойдет), может мне и не стоило переезжать из темы БК.
ivagor, а вы FCU архиватор под RT-11 щупали в плане сжатия весьма не плох.
http://archive.pdp-11.org.ru/ukdwk_a.../FCU_PLUSPLUS/
http://archive.pdp-11.org.ru/ukdwk_a...U_Shurick_inc/
FCU я не пробовал, но по описанию там LZ+Хаффман, т.е. должен сжимать на уровне zip. LZSA слабее, там LZ, но распаковщики наверняка более быстрые.
не проверял, а вот пакует большие файлы под осью быстрее и компактнее - это факт.
- - - Добавлено - - -
единственный минус "не универсальный" от LZA архивы не кушает, а так вообще был бы единственным современным архиватором под RT-11, автор насколько известно - Украинский программист.
Минус FCU для нас сейчас в том что сишного запаковщика/распаковщика нет. Теперь только если реверсить из MACRO-11 кода.
В архиве FCU_PLUSPLUS есть AEUK.SAV и LEUK.SAV, которые согласно описанию распаковывают ARJ и LHA. Если это действительно так, то по крайней мере для LHA есть исходники упаковщика. Для ARJ наверняка тоже есть, просто я не искал. Все LZ+Хаффман (arj, lha, zip и, скорее всего, fcu) примерно одинаковые по степени сжатия и сложности распаковщика. Т.е. все они сложнее и медленнее LZSA, их распаковщик больше по размеру и они требуют место под таблицу.
Победить их по степени сжатия сможет LZMA, например shrinkler, на для его нормального использования нужно быстрое умножение.
Умножение (требуется беззнаковое!), да полезно...Но это только одна проблема, - там регистров рабочих в алгоритме распаковке в два раза больше, чем есть у pdp11, а значит нужно их спиливать в стек, либо использовать модификацию кода. Плюс необходимость памяти под контекст (~3 Кбайт).
Я бы разделил вопросы скорости и принципиальной реализуемости. Ключевой момент для скорости - быстрое умножение. Много регистров, конечно, тоже нужно, но раз получилось сделать даже для 8080, то для PDP11 получится (если задаться целью) не хуже. Но версии для 8080 (да и для z80) очень медленные. Для R800 и 8088/86 работают почти приемлемо.
Необходимость выделения 2.5 Кб под таблицы не добавляет привлекательности shrinklerу, но тут все зависит от задач.
Насчет самомодификации. В LZSA2 можно на слово сократить, если хранить повторно используемое смещение в самой команде, но я пока не стал так делать.
Сократил распаковщик LZSA2 на 20 байт и немного ускорил, LZSA1 сократил на 2 байта.
Ребят, мне бы для тестирования кросс-линковщика получить от вас что-нибудь на Фортране и Паскале - можно просто в форме набора .OBJ-файлов + команда для LINK, исходники НЕ нужны. В общем, ищу сложные случаи линковки.
в архиве два файла - программа и библиотека от нужной версии Паскаля,
на выходе после LIN DWKQCO, PASDWK, полученный SAV - выводит символьную
эмблему название инициативной группы (участником которой ты так же являешься,
ув. Никита), подойдёт?
у меня предложение прогони тесты из поставки Фортрана77, системы Грей, что то на форуме было под библиотеку от form'а RSXLIB.OBJ - у меня вот так нахрапом ничего "многобиблиотечного" нет.
Вот другой участник ИГ оформит библиотеки и редактор для работы со спрайтами в Паскале для УК-НЦ - будут )