Просмотр полной версии : Программирование на УКНЦ как?
Страницы :
1
[
2]
3
4
5
6
7
В приложении - тест скорости вывода символов в порт терминала - CPS.SAV (http://zx.pk.ru/attachment.php?attachmentid=31263) с исходником.
Есть два варианта теста:
1. CPS.SAV - без ожидания прерывания по WAIT.
2. CPS2.SAV - с ожиданием прерывания по WAIT.
Интересно, какие результаты получаются на реальном оборудовании..
Сейчас посмотрим.
Главное однотерминальную систему загрузить :)
Только что окончательно обнаружил, что на моей тестовой УКНЦ'шке периферийный процессор тактируется 8-ю мегагерцами! Помнится, мне товарищ, который подарил ее, говорил, что разгонял ПП. Придется переходить на вторую УКНЦ.
Только что окончательно обнаружил, что на моей тестовой УКНЦ'шке периферийный процессор тактируется 8-ю мегагерцами! Помнится, мне товарищ, который подарил ее, говорил, что разгонял ПП. Придется переходить на вторую УКНЦ.
Проверь на живом УКНЦ, ну и может пригодится когда - пример одной проги и для ЦП и для ПП :)
В эмуляторе пашет :)
.TITLE PPCP
.IDENT /V01.00/
$USRSP == 42 ;USER STACK POINTER
CR = 15 ;CARRIAGE RETURN
LF = 12 ;LINE FEED
.MCALL .EXIT,.TTYOUT ;SYSTEM MACRO CALLS
START:: CMP @#$USRSP,SP ;RUNNING UNDER RT-11?
BEQ 10$ ;EQ->YES
MOV #PR.PP,PRINT ;UPDATE PRINT HANDLER
MOV #EX.PP,EXIT ;UPDATE EXIT HANDLER
10$: MOV #TEXT,R1 ;POINT TO ASCIZ STRING
CALL @PRINT ;PRINT IT
JMP @EXIT ;EXIT
PR.PP:: MOV R1,10$ ;SET STRING ADDRESS
JSR R4,@#163006 ;PRINT STRING
10$: .BLKW ;
RETURN ;RETURN
PR.RT:: MOVB (R1)+,R0 ;GET CHAR
BEQ 10$ ;EQ -> END OF LINE
.TTYOUT ;PRINT CHARACTER
BR PR.RT ;LOOP
10$: RETURN ;RETURN
EX.RT:: .EXIT ;EXIT TO OS
EX.PP:: MOV #START,R1 ;FREE MEMORY AND EXIT
JMP @#176300 ;
PRINT:: .WORD PR.RT ;RT-11 BY DEFAULT
EXIT:: .WORD EX.RT ;
TEXT: .ASCIZ <CR><LF>/HELLO WORLD!/<CR><LF>
.END START
В приложении - тест скорости вывода символов в порт терминала - CPS.SAV (http://zx.pk.ru/attachment.php?attachmentid=31263) с исходником.
Есть два варианта теста:
1. CPS.SAV - без ожидания прерывания по WAIT.
2. CPS2.SAV - с ожиданием прерывания по WAIT.
Интересно, какие результаты получаются на реальном оборудовании..
На консоли при 9600 оба теста 960.
На DLV11-J пробовать не стал так как терминал прога не учитывает, а из-за русского текста внутри компилиться не желает (патчить MACRO нет охоты) :)
Немножко потестил скорость работы процессоров на УКНЦ - ужаснулся, какой тормоз периферийный процессор. Команды типа MOV Rx,Rx он выполняет за 16 тактов, вместо 8, как если бы время памяти было 1Т.
Проверил на реальной УКНЦ, нетурбированной. Оказалось еще медленней - 20 тактов.
---------- Post added at 19:05 ---------- Previous post was at 19:03 ----------
Проверь на живом УКНЦ, ну и может пригодится когда - пример одной проги и для ЦП и для ПП :)
В эмуляторе пашет :)
Проверю, если приложишь диск с программой)
Проверил на реальной УКНЦ, нетурбированной. Оказалось еще медленней - 20 тактов.
---------- Post added at 19:05 ---------- Previous post was at 19:03 ----------
Проверю, если приложишь диск с программой)
Держи.
А кто собственно мешает с помощью E11 класть что угодно в образы? :)
На консоли при 9600 оба теста 960.Так и должно быть при 10 бит на байт.
Интересно, какая реальная скорость при выводе в порт терминала у УКНЦ..
Так и должно быть при 10 бит на байт.
Интересно, какая реальная скорость при выводе в порт терминала у УКНЦ..
Ну стандартный 9600,N,8,1
На УКНЦ тащить муторно - надо дискеты задействовать :)
Проверь на живом УКНЦ, ну и может пригодится когда - пример одной проги и для ЦП и для ПП :)
В эмуляторе пашет :)
Да, на реале тоже работает.
Да, на реале тоже работает.
Ну и отлично.
В реале если большие объемы данных надо выводить (сразу), надо учесть, что на ЦП продолжает работать система и еще будет "." выводить :)
Немножко потестил скорость работы процессоров на УКНЦ - ужаснулся, какой тормоз периферийный процессор. Команды типа MOV Rx,Rx он выполняет за 16 тактов, вместо 8, как если бы время памяти было 1Т. Сначала показалось странным, но потом разобрался. Во-первых, как это я раньше не заметил, шина данных ОЗУ ПП - 8-битная! И все 16-битные транзакции выполняются в 2 раза медленнее. Во-вторых, доступ к ОЗУ возможен только во время временного слота 'Ц.П.', который наступает раз в 4 такта. Т.е. 2 такта на слот 'Ц.Э.' (цикл экрана), и 2 такта на 'Ц.П.' (цикл процессора). В общем, имеем около 390тыс. операций типа регистр/регистр на ПП, что более, чем в два раза медленнее, чем на том же Спектруме, не смотря на то, что тактовая частота ПП 6.25МГц.
Собственно я про это несколько раз писал, про отличие времени исполнения в ОЗУ ЦП, ОЗУ ПП и ПЗУ. Самая быстрая - это ПЗУ. А вот контроллер ОЗУ делит доступ к памяти между видеоадаптером и процессором. При этом у ЦП частота 8 Мгц, а у контроллера ОЗУ 6,25 Мгц, небольшая рассинхронизация. Таким образом выходит, что доступ к ОЗУ ЦП минимум за 320 нс (3T для ЦП), максимум - 960 нс (8T для ЦП). В ПП ситуация похуже - минимум 960 нс (6T), максимум - 1280 нс (8T), хотя более гладкая. Так что как-то не получается, что программа в ПП работает в 2 раза медленнее, учитывая еще предвыборку. Еще кстати частота сетевого таймера в УКНЦ не 50 Гц, а 50,08 Гц, между импульсами не 20000 мкс, а 19968 мкс, различие мизерное, но мало ли что.
Теперь несколько слов про тайминги, которые появились в эмуляторе УКНЦ. Сами тайминги взяты из архива эмулятора PDP-11 на Forth. Там в каталоге pdpemu есть файл 1806VM2.TIM, а сами смещения в этой таблице расписаны в файле pdpbeg.f, конкретные времена по командам - файл pdpinstr.f. В этом архиве есть файлик readme.txt с контактной информацией, но я с автором не связывался. Кстати в этом эмуляторе было кое-что по особенностям исполнения команд, которое подтвердилось на реальных тестах, но которое не отражено в техническом описании на процессор 1801ВМ2.
Отличия состоят в разности исполнения словных и байтовых команд MOV, MOVB, CLR, CLRB, MFPS. Словные команды MOV и CLR для dst исполняют только цикл записи, а вот байтовые команды MOVB, CLRB, MFPS для dst в памяти производят цикл чтение-пауза-вывод. Это практически подтвердилось на реальной УКНЦ.
байтовые команды MOVB, CLRB, MFPS
Байтовый MFPS это как? :)
Или в том смысле что он в принципе такой и так работает?
Байтовый MFPS это как? :)
Или в томи смысле что он в принципе такой и так работает?
Ну на самом деле он только байтовый и есть. Ведь запись dst он делает как байт, а регистр также расширяет знаковым разрядом.
---------- Post added at 00:08 ---------- Previous post was at 00:07 ----------
Расширят также как MOVB.
Ну на самом деле он только байтовый и есть. Ведь запись dst он делает как байт, а регистр также расширяет знаковым разрядом.
---------- Post added at 00:08 ---------- Previous post was at 00:07 ----------
Расширят также как MOVB.
Процессор по правилам должен при записи в регистр побайтово расширить значение до слова. Не уверен есть ли исключения. Касается именно MOVB, но не всяких BICB, BISB, CLRB.
На УКНЦ кстати помню сталкивался с приколом где-то в прошивке - с параллельным портом чтоли. Там хитро сделано, что нечетные адреса тоже нужно пословно адресовать :)
Процессор по правилам должен при записи в регистр побайтово расширить значение до слова. Не уверен есть ли исключения. Касается именно MOVB, но не всяких BICB, BISB, CLRB.
Байтовые команды с регистром работают только с младшим байтом, старший не трогают. Исключением являются MOVB и MFPS, которые расширяют старший байт знаковым разрядом.
На УКНЦ кстати помню сталкивался с приколом где-то в прошивке - с параллельным портом чтоли. Там хитро сделано, что нечетные адреса тоже нужно пословно адресовать :)
Ну да, для параллельного порта используется 8-разрядная микросхема 580ВВ55, у которой только две адресных линии. Разработчики почему то подключили к ним не AD2 и AD1, а AD1 и AD0. Подключение идет через 1801ВП1-120, который содержит дешифратор адреса для параллельного порта. Линии данных подключены только к младшему байту. Самому процессору 1801ВМ2 по барабану, какой адрес, четный или нечетный, что сказали, то и выставил на шину. Поэтому в данном случае и надо производить словное обращение даже по нечетным адресам. Если записывается байт по нечетному адресу, то он будет в старшем байте, а в младшем будут нули. Также и чтение байта по нечетному адресу, процессор прочтет слово, а возьмет только старший байт.
Байтовые команды с регистром работают только с младшим байтом, старший не трогают. Исключением являются MOVB и MFPS, которые расширяют старший байт знаковым разрядом.
Точнее любые MF* кроме MOV. Не забываем, что ВМ2 - не единственный процессор на свете :)
Ну да, для параллельного порта используется 8-разрядная микросхема 580ВВ55, у которой только две адресных линии. Разработчики почему то подключили к ним не AD2 и AD1, а AD1 и AD0.
Воспользовались тем, что ВМ2 не трапается на odd address :)
Точнее любые MF* кроме MOV. Не забываем, что ВМ2 - не единственный процессор на свете :)
Ну я вел речь исключительно про 1801ВМ2, а ВМ3 и другие с диспетчером памяти и не упоминал...
Воспользовались тем, что ВМ2 не трапается на odd address :)
Также как и LSI-11.
Ну я вел речь исключительно про 1801ВМ2, а ВМ3 и другие с диспетчером памяти и не упоминал...
Также как и LSI-11.
11/03, 11/23...
Есть MF команда не касающаяся MMU :)
Хотя косвенно, ее вроде не бывает на процах без него.
Я просто упоминал там, что расширение знака - правило, а не исключение.
Есть MF команда не касающаяся MMU :)
Хотя косвенно, ее вроде не бывает на процах без него.
Это какая MF? Знаю только MFPD и MFPI, но они словные. Кстати на первых релизах 1801ВМ3 был глюк. Так как у этого процессора нет раздела на зоны инструкций и данных, то по идее эти команды должны исполняться одинаково, но так как команда MFPD в своем коде содержит установленный старший бит, то она исполнялась как байтовая. Приходилось патчить программы и заменять MFPD на MFPI.
Вспомнил еще про MFPT, но там вроде не такие большие значения были, все таки тип процессора.
Я просто упоминал там, что расширение знака - правило, а не исключение.
Вообще-то расширение знака - это исключение.
Вспомнил еще про MFPT, но там вроде не такие большие значения были, все таки тип процессора.
Ну это я просто прикололся вообще про MF команды :)
Вообще-то расширение знака - это исключение.
Какое же это исключение если почти все (или вообще все) процессоры себя именно так ведут?
Уже как-то просил, но все забили...
Запустите кто-нибудь на чем есть: ДВК, УКНЦ...
Интересно все-таки сравнить :)
Какое же это исключение если почти все (или вообще все) процессоры себя именно так ведут?
А какие процессоры. В PDP-шных процессорах расширение знака есть только для MOVB и MFPS. Про них вроде и ведем речь. Для байтовых команд изменяется только младший байт, старший не трогается, вполне нормально. Жаль только нельзя работать так со старшим байтом в регистрах.
А какие процессоры. В PDP-шных процессорах расширение знака есть только для MOVB и MFPS. Про них вроде и ведем речь. Для байтовых команд изменяется только младший байт, старший не трогается, вполне нормально. Жаль только нельзя работать так со старшим байтом в регистрах.
Совершенно верно - про них и говорим и я говорю, что это правило: именно так эти команды работают на всех известных мне процессорах. Есключение было бы если бы так оно работало на УКНЦ, а на других не расширяло. Остальные команды не должны трогать и это вроде даже документировано.
места под метод адресации не хватит работать со старшим байтом регистра :)
а делать кособокую срань как в интеле когда на байт сошел с дорожки и вообще вся картина поменялась, а не пара команд - бе :)
---------- Post added at 04:14 ---------- Previous post was at 04:00 ----------
Кстати об эмуляторе УКНЦ... Подумал тут: это единственный известный мне нашинский эмулятор который правильно работает с VT52 ESC последовательностями. В силу того, что собственно VT52 не эмулирует сам по себе :)))
Уже как-то просил, но все забили...
Запустите кто-нибудь на чем есть: ДВК, УКНЦ...
Интересно все-таки сравнить :)
Оно конечно в эмуляторе, но ему (эмулятору то есть) можно верить. Процессор 1801ВМ2.
NOASH31
NODESTFIRST
JMP4
NOJMPPLUS2
NOODD
NOSWABV
NOUNDOAUTO
Оно конечно в эмуляторе, но ему (эмулятору то есть) можно верить. Процессор 1801ВМ2.
NOASH31
NODESTFIRST
JMP4
NOJMPPLUS2
NOODD
NOSWABV
NOUNDOAUTO
Ну на эмуляторе-то я уже запустил - тут проблем нет :)
У меня на KDJ11BF так:
NOASH31
DESTFIRST
NOJMP4
NOJMPPLUS2
ODD
NOSWABV
NOUNDOAUTO
Кстати об эмуляторе УКНЦ... Подумал тут: это единственный известный мне нашинский эмулятор который правильно работает с VT52 ESC последовательностями. В силу того, что собственно VT52 не эмулирует сам по себе :)))
Естественно VT-52 эмулируется программой в СПЗУ, но не все то гладко. ESC A, ESC B, ESC C и ESC D - если курсор уперся в край экрана, то он должен так там и остаться, а в УКНЦ при необходимости делается скроллинг, т.е. ESC A работает как ESC I, а ESC B, как LF. Нет псевдографики, холдскрина. Хотя все это поправимо с помощью загружаемых модулей, благо сделать свою функцию обработки Esc-последовательности труда не представляет. На диске sysimage есть пример - ESCFG, реализует ESC F и ESC G, псевдографика правда взята с КЦГД.
Естественно VT-52 эмулируется программой в СПЗУ, но не все то гладко. ESC A, ESC B, ESC C и ESC D - если курсор уперся в край экрана, то он должен так там и остаться, а в УКНЦ при необходимости делается скроллинг, т.е. ESC A работает как ESC I, а ESC B, как LF. Нет псевдографики, холдскрина. Хотя все это поправимо с помощью загружаемых модулей, благо сделать свою функцию обработки Esc-последовательности труда не представляет. На диске sysimage есть пример - ESCFG, реализует ESC F и ESC G, псевдографика правда взята с КЦГД.
Ну в УКНЦ это уже к самому УКНЦ относится и в любом случае почти незаметно разницы. В K52 вот видно только отсутствие графики.
На советских же эмуляторах PDP-11 сколько мне их не попадалось в K52 работать в принципе невозможно было :)
Ну в УКНЦ это уже к самому УКНЦ относится и в любом случае почти незаметно разницы. В K52 вот видно только отсутствие графики.
На советских же эмуляторах PDP-11 сколько мне их не попадалось в K52 работать в принципе невозможно было :)
А чем же так все плохо? Ведь реализовать для минимума надо BS, LF, CR, ESC =, ESC >, ESC A, ESC B, ESC C, ESC D, ESC H, ESC I, ESC J, ESC K и ESC Y.
Сложности возникнут с ДКЛ-клавиатурой только.
А чем же так все плохо? Ведь реализовать для минимума надо BS, LF, CR, ESC =, ESC >, ESC A, ESC B, ESC C, ESC D, ESC H, ESC I, ESC J, ESC K и ESC Y.
Сложности возникнут с ДКЛ-клавиатурой только.
Тем, что советские программеры (или может это один и тот же?) считают, что <ESC>J - это стирание экрана :)
Тем, что советские программеры (или может это один и тот же?) считают, что <ESC>J - это стирание экрана :)
Ну естественно, обычно же употребляется <ESC>H<ESC>J. :D
Ну естественно, обычно же употребляется <ESC>H<ESC>J. :D
DEC к сожалению имеет наглость использовать возможности своих терминалов :)
---------- Post added at 04:46 ---------- Previous post was at 04:35 ----------
Про С2 в эмуляторе еще ничего не слышно? :)
А то выпадает из ряда: все остальное у меня между собой связано тем или иным способом :)
Оно конечно в эмуляторе, но ему (эмулятору то есть) можно верить. Процессор 1801ВМ2.
NOASH31
NODESTFIRST
JMP4
NOJMPPLUS2
NOODD
NOSWABV
NOUNDOAUTO
На реале абсолютно так же.
Кстати, тут кто-то уже выкладывал результат этого теста.
На реале абсолютно так же.
Кстати, тут кто-то уже выкладывал результат этого теста.
Мне не попадался. Свой на 11/83 я выклдывал.
Уже даже пнул автора E11 по поводу разногласий :)
Кратенькoe исследованиe о количестве тактов, за которые выполняются команды ПП и ЦП:
ПП:
Все команды выполняются за число тактов, кратное 4, т.к. такова периодичность доступа к ОЗУ ПП.
Мнемоника Такты Циклы
--------------------------------------------
NOP R
MOV Rx,Rx - 20 R
MOV #nnnn,Rn) R + R
MOV -(Rn)+,Rn R + R
TST (Rn) R + R
MOV Rn,-(Rn)+ R + W
CLR (Rn) - 40 R + W
JMP (PC) - 44 R + R
MOV @(Rn)+,Rn R + R + R
MOV nnnn(Rn),Rn R + R + R
INC (Rn) - 60 R + RMW
MOV Rn,@(Rn)+ R + R + W
MOV Rn,nnnn(Rn) - 64 R + R + W
MOV (Rn),(Rn) - 68 R + R + W
MOV @nnnn(Rn),R1- 80 R + R + R + R
MUL Rn,Rn - 96 R
DIV Rn,Rn - 128 R
DIV #nnnn,Rn - 164 R
ЦП:
Дробное число тактов округленно до 0.25, хотя на самом деле, из-за сходимости между 8МГц ЦП и 6.25МГц ПП равной 25, шаг времени выполнения в тактах ЦП может быть до 0.04 такта.
Мнемоника Такты Циклы
--------------------------------------------
NOP - 13.75 R
MOV Rx,Rx - 11.75 R
MOV #nnnn,Rn) R + R
MOV -(Rn)+,Rn R + R
TST (Rn) - 29 R + R
MOV Rn,-(Rn)+ - 33.75 R + W
CLR (Rn) - 34 R + W
JMP (PC) - 35.25 R + R
INC (Rn) - 40.5 R + RMW
MOV @(Rn)+,Rn - 45.75 R + R + R
MOV nnnn(Rn),Rn - 46 R + R + R
MOV Rn,@(Rn)+ R + R + W
MOV Rn,nnnn(Rn) - 47 R + R + W
MOV (Rn),(Rn) - 49.5 R + R + W
MOV @nnnn(Rn),R1- 59.5 R + R + R + R
MUL Rn,Rn - 96 R
DIV Rn,Rn - 128 R
DIV #nnnn,Rn - 152.5 R
MUL два варианта есть - 32bit и 16bit. Не уверен правда, что влияет, но мало ли.
---------- Post added at 05:21 ---------- Previous post was at 05:19 ----------
А где сам тест-то? :)
MUL два варианта есть - 32bit и 16bit. Не уверен правда, что влияет, но мало ли.
Вариант один. Только в случае, если регистр-приемник нечетный, теряется старшая часть результата.
---------- Post added at 01:24 ---------- Previous post was at 01:23 ----------
А где сам тест-то? :)
Сам тест пока сырой, только некоторые команды, про которые написал.
Вариант один. Только в случае, если регистр-приемник нечетный, теряется старшая часть результата.
---------- Post added at 01:24 ---------- Previous post was at 01:23 ----------
Сам тест пока сырой, только некоторые команды, про которые написал.
Варианты - кто их знает как оно сделано - меня ничто не удивит :)
Достаточно вспомнить злополучный ASH(C) на J11 - вроде все ясно, ан нет :)
А тест - так и фиг с ним что сырой, зато может народу идеи какие придут в голову сразу.
Варианты - кто их знает как оно сделано - меня ничто не удивит :)
По поводу 1801ВМ2 ясно как сделано. Есть техописание, результаты практических тестов. Регистры в блоке расширенной арифметики 32-разрядные, а используются регистры с номерами Rn и (Rn .OR. 1), поэтому микропрограмма не зависит от четности регистра. В случае использования нечетного регистра в регистры блока расширенной арифметики загружается один и тот же регистр в младшую и старшую часть. Также и с сохранением, если нечетный, то в регистре сохраняется два раза, естественно первый раз после этого теряется.
form, задам глупый вопрос: а RSX-11 возможно собрать без поддержки диспетчера памяти для загрузки в 56К памяти?
form, задам глупый вопрос: а RSX-11 возможно собрать без поддержки диспетчера памяти для загрузки в 56К памяти?
Так отвечал же уже. Можно RSX11M собрать. Муторно правда - MMUшный вариант проще. Но в принципе можно. Драйвера только если железа нестандартное надо делать в двух вариантах - драйвер I/O и драйвер загрузки/сохранения.
Нам мой взгляд, при исследованиях растактовок выполнения команд нужно стремиться:
1. На первом этапе - выяснить зависимость растактовок циклов шины от задержки памяти, сравнивая продолжительность выполнения одних и тех же команд при использовании разных типов памяти (ОЗУ, ПЗУ, регистров устройств).
2. На втором этапе - определить "алгоритмическую добавку" для каждой команды, определяющую превышение числа тактов, необходимых для выполнения команды, над числом тактов, необходимых для выполнения всех использующихся в команде циклов шины.
Нам мой взгляд, при исследованиях растактовок выполнения команд нужно стремиться:
2. На втором этапе - определить "алгоритмическую добавку" для каждой команды, определяющую превышение числа тактов, необходимых для выполнения команды, над числом тактов, необходимых для выполнения всех использующихся в команде циклов шины.
Если просто вычесть из фактического времени выполнения команды все циклы шины, это нам в остатке не даст никакой полезной информации, т.к. на ВМ2 работа ALU идет в параллель с циклами доступа к шине.
А тест нацелен только на две вещи. Первое олучить фактические времена выполнения команд, для тестирования правильности работы, как эмуляторов, так и реальных машинок. И второе, используя эти фактические времена, путем некоторых вычислений сравнить правильность понимания внутренней работы ВМ2 с тем, что должно получаться при заданных задержках и фазах шины.
Если просто вычесть из фактического времени выполнения команды все циклы шины, это нам в остатке не даст никакой полезной информации, т.к. на ВМ2 работа ALU идет в параллель с циклами доступа к шине.Из этого утверждения следует, что продолжительность выполнения всех команд с одинаковым количеством одинаковых циклов шины - одинакова.
У процессора 1801ВМ1 это точно не так. Подозреваю, что и у 1801ВМ2 - тоже.
Первое получить фактические времена выполнения команд, для тестирования правильности работы, как эмуляторов, так и реальных машинок.При эмуляции выполнения процессором команды - для каждой операции доступа к памяти, производящейся для чтения/записи аргументов - необходимо учитывать задержку памяти. Иначе эмуляция команды CMP (R0),(R1) будет осуществляться за одинаковое количество тактов и при выборке операндов из ОЗУ, и из ПЗУ.
При эмуляции выполнения процессором команды - для каждой операции доступа к памяти, производящейся для чтения/записи аргументов - необходимо учитывать задержку памяти. Иначе эмуляция команды CMP (R0),(R1) будет осуществляться за одинаковое количество тактов и при выборке операндов из ОЗУ, и из ПЗУ.
С этим все согласны. Но я уже писал, что у УКНЦ время доступа к памяти довольно плавающее, из-за перемежающихся циклов доступа к ОЗУ еще и видеоадаптера, т.е. это не 1801ВП1-013 или 1801ВП1-030. Так же в 1801ВМ2 есть предвыборка команд, может так произойти, что дешифрация команды пройдет относительно быстро, надо доступ на шину для операционного блока, а там еще из памяти команда вытягивается для предвыборки, чувствуется на магистрали ПП особенно.
---------- Post added at 14:05 ---------- Previous post was at 13:51 ----------
Кстати еще по поводу большого времени исполнения команд на магистрали ПП в УКНЦ. Как известно процессор 1801ВМ2 имеет вход AR для подтверждения приема адреса по SYNC. Так вот на магистрали ПП сигнал на AR подается с большим запаздыванием, чем на магистрали ЦП. На магистрали ПП для части устройств (в том числе разъемы ВУ) шина AD проходит через буфер 1801ВП1-055, что тоже вносит задержку, поэтому и AR защелкивается позже, чтобы адрес смогли считать.
Из этого утверждения следует, что продолжительность выполнения всех команд с одинаковым количеством одинаковых циклов шины - одинакова.
У процессора 1801ВМ1 это точно не так. Подозреваю, что и у 1801ВМ2 - тоже.
Нет, не следует) В параллель - не значит, что перкрывает полностью)
я уже писал, что у УКНЦ время доступа к памяти довольно плавающееЭто лишь увеличивает количество необходимых этапов тестирования, но никак не изменяет их объективно необходимой последовательности.
При отсутствии базовой информации о связи задержки памяти в наносекундах с продолжительностью циклов шины в тактах - сложно (если вообще возможно) адекватно интерпретировать результаты тестов более "высоких уровней".
Например, поскольку задержка памяти "округяется" шиной до целых тактов - величина тактовой частоты в герцах связана с продолжительностью выполнения команд в наносекундах нелинейно.
Если не выводить универсальных "формул быстродействия", то адекватность эмуляции будет достижима только при эмуляции той конфигурации, которая использовалась при тестировании. Изменение тактовой частоты реального компьютера хотя бы на один герц или изменение задержки адресуемой памяти хотя бы на одну наносекунду - может привести к весьма существенным отклонениям реального быстродействия от эмулируемого.
...
Нет, не следует) В параллель - не значит, что перкрывает полностью)Да, на быстрой памяти, читающей ячейку за два такта - АЛУ 1801ВМ1 добавляет к продолжительности некоторых команд ещё один такт, а на медленной памяти - полностью успевает сработать за время ожидания памяти и "свой такт" не добавляет.
Но определение зависимости "алгоритмической задержки" от задержки памяти - это лишь ещё один этап тестирования, никак не отменяющий объективной необходимости соблюдения их рациональной последовательности.
Если не выводить универсальных "формул быстродействия", то адекватность эмуляции будет достижима только при эмуляции той конфигурации, которая использовалась при тестировании. Изменение тактовой частоты реального компьютера хотя бы на один герц или изменение задержки адресуемой памяти хотя бы на одну наносекунду - может привести к весьма существенным отклонениям реального быстродействия от эмулируемого.
Для полноценной правильной эмуляции нужна эмуляция всех ступеней выполнения команд ВМ2, равно, как и такая же эмуляция железа УКНЦ. При таком, и только таком подходе возможна точная эмуляция. Все остальное, как-то установка в эмуляторе командам процессора их примерное время выполнения, полученное хоть какими тестами, даст лишь приближенную по скорости модель УКНЦ, но никак не 100% совместимую.
Для полноценной правильной эмуляции нужна эмуляция всех ступеней выполнения команд ВМ2, равно, как и такая же эмуляция железа УКНЦ. При таком, и только таком подходе возможна точная эмуляция. Все остальное, как-то установка в эмуляторе командам процессора их примерное время выполнения, полученное хоть какими тестами, даст лишь приближенную по скорости модель УКНЦ, но никак не 100% совместимую.
Ну по поводу 100% совместимости, не совместимы даже УКНЦ разных заводов, из-за небольшой разнице в схемотехнике. Вроде бы мелочь, а влияет. В качестве примера - формирование сигнала AR на магистрали ПП. Уже выкладывались тесты из программы SPEED, так у всех одинаково только исполнение MUL и DIV, а регистровый и косвенно-регистровый тесты отличаются.
Про 100% эмуляцию железа - знаю некоторые особенности связанные с конвеером 1801ВМ2, пробовал их на реальной машине, на эмуляторе это естественно не работает. Далее 100% эмуляция 1801ВП1-128 (контроллер дисковода) - это только на уровне кода MFM, я достаточно хорошо знаю как он работает, но ведь эмулятор повесится при таком эмулировании, производительности не хватит. Да это в принципе и не надо, эти тонкости никто реально не использует, разве только для того, чтобы отличить, работает программа на реале или в эмуляторе.
Попытался представить себе эмуляцию 11/83 с полноценной MSV11-J :)
Попытался представить себе эмуляцию 11/83 с полноценной MSV11-J :)
Кстати по поводу DCJ-11, существует ведь распечатка микрокода, вот поле для эмуляции с абсолютной точностью до полутакта.
Ну по поводу 100% совместимости, не совместимы даже УКНЦ разных заводов, из-за небольшой разнице в схемотехнике. Вроде бы мелочь, а влияет. В качестве примера - формирование сигнала AR на магистрали ПП. Уже выкладывались тесты из программы SPEED, так у всех одинаково только исполнение MUL и DIV, а регистровый и косвенно-регистровый тесты отличаются.
Про 100% эмуляцию железа - знаю некоторые особенности связанные с конвеером 1801ВМ2, пробовал их на реальной машине, на эмуляторе это естественно не работает. Далее 100% эмуляция 1801ВП1-128 (контроллер дисковода) - это только на уровне кода MFM, я достаточно хорошо знаю как он работает, но ведь эмулятор повесится при таком эмулировании, производительности не хватит. Да это в принципе и не надо, эти тонкости никто реально не использует, разве только для того, чтобы отличить, работает программа на реале или в эмуляторе.
На сколько я помню, разница в схемотехники касалась практически только видеоформирователя.
Но надо тогда мой тест позапускать на разных машинах.
Если эмулятор работает примерно, а не как реал, то всегда есть шанс наткнуться на то, что что-то работает не так.
Кстати по поводу DCJ-11, существует ведь распечатка микрокода, вот поле для эмуляции с абсолютной точностью до полутакта.
Речь не о DCJ11, а например об эмуляции кэш памяти :)
Точнее о попытках извлечь пользу из этого :)
Точную эмуляцию всего тютелька в тютельку считаю бесполезной - практической пользы нет, совместимости софту (в том числе ощущениям) не добавит. Куда важнее грамотно сэмулировать нормальную асинхронную работу с железом чтобы оно не дергалось как в simh :)
Кстати по поводу DCJ-11, существует ведь распечатка микрокода, вот поле для эмуляции с абсолютной точностью до полутакта.
Как хорошо, что я не знаю, что такое 11/83, MSV11-J, DCJ-11) Позволяет легко по ключевым словам игнорить подобные мессейджи в теме про УКНЦ, чтобы не уходить в сторону)
Как хорошо, что я не знаю, что такое 11/83, MSV11-J, DCJ-11) Позволяет легко по ключевым словам игнорить подобные мессейджи в теме про УКНЦ, чтобы не уходить в сторону)
Ну положим от УКНЦ тема ушла с самого начала ибо первые же вопросы подразумевали не УКНЦ именно, а больше RT-11 :)
А уж о том какое отношение имеет эмуляция УКНЦ к программированию на УКНЦ... ;)
На сколько я помню, разница в схемотехники касалась практически только видеоформирователя.
Но надо тогда мой тест позапускать на разных машинах.
Если эмулятор работает примерно, а не как реал, то всегда есть шанс наткнуться на то, что что-то работает не так.
Не только, формирование сигнала AR, по внешнему событию оставили только линию магнитофона (убрали линию ИНДЕКС с накопителя), скорость С2 можно регулировать программно.
Вот задерка на AR очень влияет на быстродействие.
Но надо УКНЦ с Квантовской и СЭМЗовской схемотехникой.
---------- Post added at 15:52 ---------- Previous post was at 15:38 ----------
Ну положим от УКНЦ тема ушла с самого начала ибо первые же вопросы подразумевали не УКНЦ именно, а больше RT-11 :)
Да, нафлудили прилично, но от темы не особенно отошли, все-таки программирование на УКНЦ проходит в системе RT-11.
А уж о том какое отношение имеет эмуляция УКНЦ к программированию на УКНЦ... ;)
А ведь всякие тесты для определения длительности команд все равно пишутся на реальной УКНЦ.
Для полноценной правильной эмуляции нужна эмуляция всех ступеней выполнения команд ВМ2, равно, как и такая же эмуляция железа УКНЦ. При таком, и только таком подходе возможна точная эмуляция. Все остальное, как-то установка в эмуляторе командам процессора их примерное время выполнения, полученное хоть какими тестами, даст лишь приближенную по скорости модель УКНЦ, но никак не 100% совместимую.Важно (на мой взгляд) чётко понимать правильную последовательность шагов по "приближению к идеалу".
При действиях в правильном порядке - каждый следующий уровень тестирования повышает точность эмуляции.
Конечно, некоторые шаги не зависят друг от друга и могут выполняться в любом порядке.
Так, например, определение зависимости числа тактов в каждом типе цикла шины от тактовой частоты и задержки памати, никак не связано с определением последовательности циклов шины в каждой команде процессора.
Однако, важно понимать, что если точно знать, какие команды выполняют какие циклы, но не знать, сколько тактов занимает каждый цикл - то это точно так же бесполезно в плане точности эмуляции, как и, наоборот - точно знать растактовку циклов, но не знать, какие команды их выполняют. Для достижения самого первого приближения к идеалу в точности эмуляции - нужно точно знать и то, и другое.
И только тогда, чётко определившись с детерминированной частью проблемы - можно начинать статистические исследования влияния квазислучайных факторов.
Зачем же отказываться от определения наилучшей методики тестирования и оптимальной (в плане достижимой степени приближения к идеальному результату) последоватеьности тестов.
вопрос по ассемблеру
что означает формулировка
Адрес строки символов расположен после команды EMT
Не в R0 не в R1, а после и именно адрес? Мне совершенно не понятно,
как такой код должен выглядеть, если можно пример две-три строчки для
наглядности?
вопрос по ассемблеру
что означает формулировка
Не в R0 не в R1, а после и именно адрес? Мне совершенно не понятно,
как такой код должен выглядеть, если можно пример две-три строчки для
наглядности?
EMT блябля
.WORD адрес
EMT блябля
.WORD адрес
То есть хорошо, а по какому принципу адрес исчислить ?
Или под адресом подразумевается метка? Вряд-ли же.
.WORD подразумевает численный аргумент
То есть хорошо, а по какому принципу адрес исчислить ?
Или под адресом подразумевается метка? Вряд-ли же.
.WORD подразумевает численный аргумент
Метка и есть адрес. Кроме случая когда программа грузится в заранее неизвестное место памяти (в ПП укнц без помощи PRUN например) - в этом случае вычисляешь относительно PC и записываешь в метку после EMT.
Для вычисления есть макрокоманда в системной библиотеке RT-11.
.ADDR #LABEL,Rx (или @Rx) - заносит реальный адрес в Rx (@Rx).
Метка и есть адрес. Кроме случая когда программа грузится в заранее неизвестное место памяти (в ПП укнц без помощи PRUN например) - в этом случае вычисляешь относительно PC и записываешь в метку после EMT.
Для вычисления есть макрокоманда в системной библиотеке RT-11.
.ADDR #LABEL,Rx (или @Rx) - заносит реальный адрес в Rx (@Rx).При передаче аргументов в коде программы - они всегда вычисляются на этапе компиляции (иначе овчинка не стоит выделки). Ведь всё затевается лишь для того, чтобы сэкономить одно слово при каждом вызове подпрограммы.
При передаче аргументов в коде программы - они всегда вычисляются на этапе компиляции (иначе овчинка не стоит выделки). Ведь всё затевается лишь для того, чтобы сэкономить одно слово при каждом вызове подпрограммы.
На этапе компиляции вычислить реальный адрес однако ну никак не получится если заранее неизвестен способ загрузки. Попробуй SAV файлу (у которого именно на этапе компиляции все вычисленно) загрузить скажем с адреса 1002 (бервый блок и выше) и посмотреть много ли программ заработают :)
Для PRUN специально REL формат выбран чтобы можно было любой файл с позиционнозависимым кодом грузить и не париться.
Или ты имеешь в виду порочность самого интерфейса когда надо адрес писать после вызова EMT/подпрограммы? :)
На этапе компиляции вычислить реальный адрес однако ну никак не получится если заранее неизвестен способ загрузки.Если автор программы хочет передавать в коде реальные адреса - его программа не может быть перемещаемой. Если же автор хочет передавать, например, смещения от начала программной секции сообщений - проблем с перемещаемостью не возникнет.
Но по сути дела - нет принципиальной разницы между вызовом с передачей аргумента в коде или в регистре. И в том, и в другом случае правила одни и те же.
Речь немного о другом - когда в программе используется передача аргументов в коде - это практически всегда означает их вычисление на этапе компиляции/компоновки. Иначе такой способ не имеет преимуществ.
Если автор программы хочет передавать в коде реальные адреса - его программа не может быть перемещаемой.
Ась?
То есть то, что такие проги есть и работают - пофигу. Их все-равно нет потому что не может быть? ;)
Если же автор хочет передавать, например, смещения от начала программной секции сообщений - проблем с перемещаемостью не возникнет.
MOV #LABEL,Rx ;ПРОБЛЕМА
А писать программы когда нужно в аргументах передавать LABEL-START оправдано далеко не всегда. В частности для загрузки всяких драйверов в ПП совершенно неоправданно ибо лекго без всякой позиционнонезависимости все делается :)[/QUOTE]
Но по сути дела - нет принципиальной разницы между вызовом с передачей аргумента в коде или в регистре. И в том, и в другом случае правила одни и те же.
Когда ты сам пишешь то, что вызываешь, ты можешь делать что хочешь. А если речь идет о EMT, надо полагать, что вызывается не твой обработчик EMT и передаешь ты ему то, что он просит, а не то, что тебе удобнее. И тут на этапе компиляции ничего вычислить не удастся если только это не частный случай - загрузка REL к примеру.
Речь немного о другом - когда в программе используется передача аргументов в коде - это практически всегда означает их вычисление на этапе компиляции/компоновки. Иначе такой способ не имеет преимуществ.
Да, но при этом или программа грузитя/мапится всегда в одно место или реализован механизм перемещения (REL) либо ты сам пишешь так, чтобы оно не зависило от местоположения и в этом случае ты так или иначе довычисляешь адреса на ходу если нужно именно адрес знать (например строки).
Для упрощения - приведите пример .PRINT когда все вычислено на этапе компиляции и работает при любом положении :)
Да, но при этом или программа грузитя/мапится всегда в одно место или реализован механизм перемещения (REL) либо ты сам пишешь так, чтобы оно не зависило от местоположения и в этом случае ты так или иначе довычисляешь адреса на ходу если нужно именно адрес знать (например строки).Именно так.
Именно так.
Так это я оговорил первой строчкой и все остальное относилось к случаю когда это не так :)
Так это я оговорил первой строчкой и все остальное относилось к случаю когда это не такЕсли кого-то ( например - нас ) интересует, чем передача аргументов в коде отличается от передачи аргументов в регистре или в стеке, то единственное отличие - в размере кода.
Когда аргументы могут быть вычислены на этапе компиляции/компоновки - их передача в коде позволяет экономить по одному слову на каждый случай передачи аргумента (для подпрограммы с 5-ю аргументами такого типа - при каждом вызове будет экономиться по 5 слов).
Если же аргументы должны вычисляться на этапе выполнения - их передача в коде не будет иметь никаких преимуществ и чаще всего будет занимать больше места, чем передача тех же аргументов в регистре или стеке.
Если же аргументы должны вычисляться на этапе выполнения - их передача в коде не будет иметь никаких преимуществ и чаще всего будет занимать больше места, чем передача тех же аргументов в регистре или стеке.
Ну так понятно, что вычислять адрес на этапе выполнения нужно только тогда когда это оправдано - в драйвере устройства например. Хотя начиная с 5.2 и без этого можно обойтись :)
А способ передачи - это уже от фантазии зависит.
В RSX к примеру есть два варианта вызова одних и тех же директив - либо все аргументы в стеке либо адрес этих самых аргументов в стеке - пользуй по обстоятельствам :)
А с програмерской точки зрения есть еще третий вариант - второй случай, но список аргументов пишешь как в первом (кладется в psect) :)
Я тут упоминал про РАФОС и RSXизм тех кто его делал - так вот там для всех макрокоманд с AREA также сделано - можно заготавливать блоки AREA, можно пихать их в PSECT :)
Я тут упоминал про РАФОС и RSXизм тех кто его делал - так вот там для всех макрокоманд с AREA также сделано - можно заготавливать блоки AREA, можно пихать их в PSECTНо сделано довольно криво - не у всех аргументов отбрасываются '#', что приводит к помещению в текст программы описаний, несовместимых со стандартом MACRO-11, при том, что точно такие же вызовы обычного формата проходят без проблем.
Например:
000000 AREA: .Read BLOCK, #0, #BUF, #256., #0
A 000000 .BYTE #0,8.
000002 .WORD 0
A 000004 .WORD #BUF
A 000006 .WORD #256.
A 000010 .WORD #1
000012 .Read #AREA, #0, #BUF, #256., #0
000012 MOV #AREA,%0
000016 MOV #0+<8.*^O400>,(0)
000022 CLR 2.(0)
000026 MOV #BUF,4.(0)
000034 MOV #256.,6.(0)
000042 MOV #1,8.(0)
000050 EMT ^O375
Можно заметить, что в первом вызове, при формировании блока аргументов - у последнего параметра ( счётчик слов #0 ) решётка была-таки отброшена.
Но сделано довольно криво
Да просто делать пытались расширяя существующий набор макросов да запутались :)
В RSX-то три формы вызовов отличаются написанием: XXX$, XXX$C и XXX$S, а тут попытались все в один флакон запихать.
Полезность же этого - вопрос спорный - просто RSXовец делал - так сказать для души. Статусы выхода тоже по-RSXовски звучат в описании: ERROR, SEVERE, FATAL вместо привычных (в RT-11) ERROR, FATAL, UNCONDITIONAL. И описание статусов соответственно хромает ибо SEVERE самим своим названием подразумевает, что произошло несколько ошибок :)
Кстати, а в фодосе тоже такое делали или там не стали? :)
---------- Post added at 20:51 ---------- Previous post was at 20:46 ----------
Кстати посмотрел на "кривость". Так это как раз правильно.
Директивы генерации DPB (пардон, AREA) должны использовать формы пригодные для .WORD и это документировано.
---------- Post added at 20:53 ---------- Previous post was at 20:51 ----------
Вот собственно выдержка из руководства:
LABEL: .PRGREQ BLOCK,ARG1,...,ARGN
ГДЕ
АRG1,...,АRGN
- ДОПУСТИМЫЕ АРГУМЕНТЫ ДЛЯ ДИРЕКТИВ .WОRD И .ВYТЕ.
Погоди-те, не забивайте пожалуйста на мой вопрос !!!
Вам наверное кажется что я всё понял и вам уже не интересно,
но мне то только ещё больше непонятностей добавилось.
Вот ещё раз (на пальцах) как мне закодить допустим
EMT 44 - вывод строки символов на экран. Адрес строки символов расположен
после команды EMT, конец строки - байт 0.
в своём шедевриальном ucl я использовал EMT 351 но там через регистр там всё ясно
а тут как быть, что такое адрес строки ??? Где физически (в самой программе) сама строка???
Вот такой у меня снова вопрос. Спасибо.
Где физически (в самой программе) сама строка???
Вот такой у меня снова вопрос. Спасибо.
Сначала покажи как ты эту строку в программе будешь записывать. Скорее всего ответ получится сам собой :)
MSG:: .Asciz "TEXT"<0>
Насколько я понял этоt EMT 44 по нулю конец строки понимает?
MSG:: .Asciz "TEXT"<0>
Насколько я понял этоt EMT 44 по нулю конец строки понимает?
Так вот MSG у тебя и есть адрес. Если речь идет об обычной программе в системе.
А что такое просто "EMT 44" - вообще не ясно. EMT 44 где?
Ну ясно что не в RT-11 - там такого просто нет. Если в периферийном процессоре УКНЦ, то проще посмотреть листинги ПЗУ как оно используется, но в этом случае как уже говорилось, будет ли #MSG (или .WORD MSG) ссылкой на нужный адрес - зависит от способа загрузки.
EMT 44 - уф, я читаю описание и похоже залез в дебри в которых
не поням ))) Список ЕМТ команд он не универсальный ? Отдельный
для ПП и для "системы" - я как-то другой логики у меня мозг видимо,
косвенно вот чуть выше везде на двухчисленные емты идёт упоминание
про какой-то ПП )))
---- ну тоесть конечно про УКНЦшный ПП ))))
---------- Post added at 18:31 ---------- Previous post was at 18:29 ----------
Ну ясно что не в RT-11 - там такого просто нет.
А там что есть? EMT 351 для вывода строки так?
EMT 44 - уф, я читаю описание и похоже залез в дебри в которых
не поням ))) Список ЕМТ команд он не универсальный ? Отдельный
для ПП и для "системы" - я как-то другой логики у меня мозг видимо,
косвенно вот чуть выше везде на двухчисленные емты идёт упоминание
про какой-то ПП )))
Ну мне трудно угадать описание чего именно ты читаешь. Если же говорить просто о EMT, то EMT с любым номером вызывает прерывание процессора по вектору 30. Это все, что делает EMT :)
Посему как минимум надо знать о чем речь вообще. О системе RT-11, о программах загруженных в область периферийного процессора УКНЦ или вообще о функционале который добавляется после того как что-либо загружено ;)
Понял, пойду дальше "паскалить" )))
Но я ещё вернусь ))) Я всё уточню )))
И снова что нибудь спрошу, обязательно
Понял, пойду дальше "паскалить" )))
Но я ещё вернусь ))) Я всё уточню )))
И снова что нибудь спрошу, обязательно
Только чтобы вопрос однозначен был ;)
А то могу еще страшнее сказку рассказать: (шепотом) EMT может генерить прерывания с вектором, физический адрес которого не равен 30! ;)))
Правда сразу успокою, к УКНЦ это не относится :)
EMT 44 - это в ПП УКНЦ, почитать можно здесь (http://felixl.com/Uknc_RAM_description_app), приложение 2.
А примеры есть не только в листингах ПЗУ УКНЦ, но можно глянуть и KBS.MAC на диске sysimage.dsk, он там выводит надписи в верхнюю информационную строку, адрес строки задается после EMT.
А про EMT в RT-11 лучше почитать оригинальную документацию, ну в крайнем случае про РАФОС/ФОДОС.
В RSX-11 свои EMT (точнее свой, вроде EMT 377), у БК также свои.
А про EMT в RT-11 лучше почитать оригинальную документацию, ну в крайнем случае про РАФОС/ФОДОС.
Если вообще читать :)
Обычно это не нужно. Разьве что просто представлять себе как системные вызовы работают :)
В RSX-11 свои EMT (точнее свой, вроде EMT 377)
Да, только EMT 377. Есть еще EMT 376 который переключает на системное состояние привилегированную задачу с мапингом на кернел. В RT-11 EMT 376 также зарезервированно, но в доке если не ошибаюсь написано, что результат непредсказуем - видимо имеется в виду, что будет разное поведение в зависимости от того чистый это RT-11, RTEM-11 или еще какой вариант.
но можно глянуть и KBS.MAC
Да в процессе конечно исходники изучать буду,
просто мне сам термин "адрес строки" из хелпа (со странички феликса
описания читаю) сразу в тупик поставил.
Есть ещё вопрос, про ESC последовательности, попробовал сходу
наскоком забабахать выше-где-то-обсужденный вариант UST и вот
поэксперементировав понял такую вещь - работает только
размещение курсора по координатам - ни смена цветов ни формат экрана
не робят ? Это я бестолковый или ньанс какой-то с реализацией на эмуляторе?
На реале я же помню без всяких ухищрений в нужном месте всё работало.
Но это не к спеху, другие процедуры то же время требуют )))
Если вообще читать :)
Обычно это не нужно. Разьве что просто представлять себе как макросы работают :)
Ну макросы надо знать обязательно, да и удобней ими писать. Но иногда какие EMT связаны с каждым макросом знать надо, чтобы представить, что есть с EMT 340 по EMT 357, каждый исполняет свою функцию, а EMT 374 и EMT 375 имеют еще и код функции.
Ну макросы надо знать обязательно, да и удобней ими писать. Но иногда какие EMT связаны с каждым макросом знать надо, чтобы представить, что есть с EMT 340 по EMT 357, каждый исполняет свою функцию, а EMT 374 и EMT 375 имеют еще и код функции.
Я про то и говорю - обычно хватает знания макросов, а знания какие они EMT используют - это уже для более глубокого представления. В этом случае полезнее знать даже не сами коды EMT, а способ передачи аргументов чтобы например не накосячить с выделением буфера в стеке и подстановкой регистра SP в качестве аргумента в макрос который в стеке же аргументы и передает :)
Пользоваться же макросами правильно не только потому, что удобно, но и потому, что макросы могут быть такими же, а система другой без гарантии, что EMT коды там совпадут.
Есть такая система RSTS/E, в ней можно собирать без каких либо переделок программы как для RT-11 так и для RSX (разумеется если это не специфические системные программы). Для RT-11 если не ошибаюсь все совпадает, а вот для RSX - вроде нет. Будет время, посмотрю :)
Просто приятнее будет если прога автоматом работает в другой системе :)
Есть ещё вопрос, про ESC последовательности, попробовал сходу
наскоком забабахать выше-где-то-обсужденный вариант UST и вот
поэксперементировав понял такую вещь - работает только
размещение курсора по координатам - ни смена цветов ни формат экрана
не робят ? Это я бестолковый или ньанс какой-то с реализацией на эмуляторе?
На реале я же помню без всяких ухищрений в нужном месте всё работало.
Но это не к спеху, другие процедуры то же время требуют )))
А каким образом выводятся эти Esc-последовательности? Если в Паскале с помощью WRITE или средствами RT-11, то работать не будет, т.к. в выводимых символах вырезается старший бит. Надо только через регистры терминала 177564/177566.
---------- Post added at 20:27 ---------- Previous post was at 20:24 ----------
Да в процессе конечно исходники изучать буду,
просто мне сам термин "адрес строки" из хелпа (со странички феликса
описания читаю) сразу в тупик поставил.
Вполне нормальный термин. Строка-то ведь в памяти расположена, и адресом строки является адрес в памяти самого первого символа строки.
Вполне нормальный термин. Строка-то ведь в памяти расположена, и адресом строки является адрес в памяти самого первого символа строки.
Не совсем в тему, просто вспомнился смешной случай - человек писал программу для поиска в памяти определенной строки на BASIC, присваивал строку для поиска переменной и потом шарил по всей памяти и надо же - что бы он туда не писал, оно обязательно находилось :)
Не совсем в тему, просто вспомнился смешной случай - человек писал программу для поиска в памяти определенной строки на BASIC, присваивал строку для поиска переменной и потом шарил по всей памяти и надо же - что бы он туда не писал, оно обязательно находилось :)
А искал по первому совпадению или всю память шарил?
Кстати, а сам потом понял, почему все-таки находилось?
А искал по первому совпадению или всю память шарил?
Кстати, а сам потом понял, почему все-таки находилось?
Да, по первому совпадению по всей памяти. Понял через пару дней - я его как раз ассемблеру обучал, а там все сразу становится на места :)
Кстати на похожий прикол можно нарваться и в реальной жизни - например в DOSовских Norton Utilities diskedit умеет работать и с памятью, так там поиск строки раза 4 напорется на написанное тобой :)
А каким образом выводятся эти Esc-последовательности? Если в Паскале с помощью WRITE или средствами RT-11, то работать не будет, т.к. в выводимых символах вырезается старший бит. Надо только через регистры терминала 177564/177566.
Да мне очень нужно курсор гасить и формат экрана менять в игрушеке )))
Такая конструкция работает
function AT(xx,yy: integer):char;
begin
write(chr(27),'Y',chr(32+yy),chr(32+xx));
AT:='';
end;
а вот такая нет
write(chr(33B),chr(246B),chr(62B));
??? :confused_std:
Просто приятнее будет если прога автоматом работает в другой системе
Но в моём случае на голом МАКРО-11 писать у меня не выйдет ничего, я его не знаю.
EМТ и последовательности у Феликса подглядел и сам кое-что вспомнилось со школьных времён,
а так ПАСКАЛЬ+МАКРО ВСТАВОЧКИ для УКНЦ (и для меня!) просто спасает, если программировать
самому что-то захочется например.
а вот такая нет
write(chr(33B),chr(246B),chr(62B));
??? :confused_std:
Дык пояснили же - write может стрипать 7й бит, а 246 - восьмибитное число.
Да, по первому совпадению по всей памяти. Понял через пару дней - я его как раз ассемблеру обучал, а там все сразу становится на места :)
Знание ассемблера должно подразумевать собой и знание архитектуры компьютера и операционной системы, и как все делается и где все хранится. Уж если понял все вкупе, дальше автоматом понимаешь почему строка все время находится.
Кстати на похожий прикол можно нарваться и в реальной жизни - например в DOSовских Norton Utilities diskedit умеет работать и с памятью, так там поиск строки раза 4 напорется на написанное тобой :)
В RT-11 есть DESS, он тоже память смотрит. В ответ на приглашение CSI просто жмется Enter, и мы в режиме просмотра ОЗУ. По <PF1>MA задается строка поиска, а по <PF1>S ищется.
На консоли при 9600 оба теста 960.
На DLV11-J пробовать не стал так как терминал прога не учитывает, а из-за русского текста внутри компилиться не желает (патчить MACRO нет охоты) :)
Пользуясь случаем, поксольку все-равно надо было в руководство по процу зяглянуть. Консоль, 38400:
.RU CPS
CPS - --_ede+e+ie _+-_-_+i +y+-da +a +e_+i+a+
d+- za+e_{e+i- -_-g_a++y - +a++i+e +`b+` ++a+i{+
CPS: 3840
-_-g_a++a za+e_{e+a
.
В приложении - англоязычный вариант CPS.SAV и CPS.MAC
В приложении - англоязычный вариант CPS.SAV и CPS.MAC
Сделай еще чтобы CSR и VEC для DL можно было задавать через GET/D - тогда можно будет тестировать другие линии :)
чтобы CSR и VEC для DL можно было задавать через GET/DВ приложении - изменённый вариант (не проверенный), в котором значения адресов регистров и база векторов прерывания записаны в ячейках 01000-01010:
.GET CPSENG
.E 1000-1010
177560 177562 177564 177566 000060
.ST
CPS - CHECK TERMINAL OUTPUT SPEED
PRESS ANY KEY TO EXIT
CPS: 5741
PROGRAM COMPLETED
.
При абстрактной эмуляции - скорость в порту слегка плавает и всегда немного отличается от абсолютно точного значения.
Значение по адресу 01000 на самом деле нигде в программе не используется - его можно не изменять.
Этот вариант программы можно перезапускать командами START и REENTER.
Если занести ненулевое значение в ячейку 1012 или запустить программу по команде REENTER - программа не будет выводить сообщения:
.GET CPSENG
.E 1000-1012
177560 177562 177564 177566 000060 000000
.REE
CPS: 5736
.
Если пропатчить ячейку 01012 в CPSENG.SAV - программа умолкнет навсегда :)
Если пропатчить ячейку 01012 в CPSENG.SAV - программа умолкнет навсегда :)
У меня для умолкания навсегда есть аппаратный инструмент - PIRQ :)
В приложении - изменённый вариант (не проверенный), в котором значения адресов регистров и база векторов прерывания записаны в ячейках 01000-01010:
Пашет.
В том числе под ZM и многотерминалкой поскольку прога все-равно все нужное перехватывает :)
У меня для умолкания навсегда есть аппаратный инструмент - PIRQВ данном случае "умолкание навсегда" относится только к необязательным сообщениям - вряд ли аппаратные средства смогут отличить их от выводимых результатов тестирования.
В данном случае "умолкание навсегда" относится только к необязательным сообщениям - вряд ли аппаратные средства смогут отличить их от выводимых результатов тестирования.
А-а. Ну PIRQ при неаккуратном пользовании заставит умолкнуть совсем до ближайшего BHALT или BREAK на консоли :)
Хотя есть еще более надежный способ - при невозможности системы по таймеру вернуть терминалы в порядок, записать 1 в 177564 :)
Тогда даже BREAK/BHALT не поможет :)
Ребята, вы уверены, что эта тема относится к программированию на УКНЦ, а не к ДВК и всему, что с ним связано?)
Ребята, вы уверены, что эта тема относится к программированию на УКНЦ, а не к ДВК и всему, что с ним связано?)
На УКНЦ если память мне не изменяет есть некий С2, который ничем от DL11 не отличается? ;)
Ребята, вы уверены, что эта тема относится к программированию на УКНЦ, а не к ДВК и всему, что с ним связано?)Программа CPS.SAV (http://zx.pk.ru/attachment.php?attachmentid=31365) написана (в том числе и) для УКНЦ.
Какие результаты она сообщает при запуске на реальной УКНЦ?
Программа CPS.SAV написана (в том числе и) для УКНЦ.
Какие результаты она сообщает при запуске на реальной УКНЦ?
Кстати интересно померять консоль :)
С С2-то примерно и так ясно :)
Версия 1.1 CPS.SAV для УКНЦ :)
.GET CPSENG
.E 1000-1012
177560 000060 177564 000064 000000 000000
.REE
CPS: 5735
.
Теперь регистры и вектора для ввода и вывода задаются раздельно - это даёт возможность пропатчить CPSENG.SAV значениями TTKS и TTKINT в ячейках 01000, 01002 (если нужные значения отличаются от находящихся там 0177560 и 060) и задавать только значения TTPS и TTPINT тестируемого порта в ячейках 01004, 01006 .
Так же, как и в предыдущей версии - запуск по команде REENTER или с ненулевым значением в ячейке 01012 - приводит к отмене вывода программой необязательных сообщений.
Версия 1.1 CPS.SAV для УКНЦ :)
.GET CPSENG
.E 1000-1012
177560 000060 177564 000064 000000 000000
.REE
CPS: 5735
.
Теперь регистры и вектора для ввода и вывода задаются раздельно - это даёт возможность пропатчить CPSENG.SAV значениями TTKS и TTKINT в ячейках 01000, 01002 (если нужные значения отличаются от находящихся там 0177560 и 060) и задавать только значения TTPS и TTPINT тестируемого порта в ячейках 01004, 01006 .
Так же, как и в предыдущей версии - запуск по команде REENTER или с ненулевым значением в ячейке 01012 - приводит к отмене вывода программой необязательных сообщений.
Для полного счастья - еще одну ячейку сделать патчуемой и в ней держать число тиков в секунду - так, на всякий случай :)
.GET CPSENG
.E 40
001030
.D 500=52737,4000,177520,137,1030
.ST 500
CPS - CHECK TERMINAL OUTPUT SPEED - V1.1
PRESS ANY KEY TO EXIT
CPS: 240
PROGRAM COMPLETED
.
---------- Post added at 19:36 ---------- Previous post was at 19:34 ----------
Ну и таки на живом УКНЦ интересно посмотреть сколько консоль покажет...
Хотя если с силами соберусь - может сам перетащу, только это надо задействовать 386 колмпьютер и контроллер дискет :)
---------- Post added at 20:04 ---------- Previous post was at 19:36 ----------
Кстати о версиях программ. В RESORC как минимум начиная с RT-11 V5.4 (более ранние проверять лень, но в макробиблиотеке поддержка с 5.0 начинается) есть фича, позволяющая показывать версию (версии) модуля.
.RESORC TEST.SAV/V
Release = V01, ID(s): 2
.TY TEST.MAC
.MCALL .MODULE
.MODULE TEST,RELEASE=V01,VERSION=02,COMMENT=<Test module>,AUDIT=YES
START: 104350
.END START
В данном случае версия V01.02 (генерится .IDENT если явно не сказать IDENT=NO, его в MAP файле видно если есть).
Если RELEASE не писать, по умолчанию V05. RELEASE должен быть одинаков во всех файлах которые принимают участие в программе. Это может мешать если используются библиотеки DECовские, но на MACRO походу их никто кроме меня не пользует :)
Может пригодиться чтобы различать SAVы сразу :)
Для полного счастья - еще одну ячейку сделать патчуемой и в ней держать число тиков в секундуВ следующей версии так и сделаем, а пока - единственное на всю программу слово со значением 50. (062) по адресу 01236 - это оно и есть.
Поведение команд, что вспомнилось...
Тут больше чем в УКНЦ влезет, но поди не помешает ;)
Может забыл чего - в частности поведение EIS, но я и сам не особо помню что и как...
Mnem Code N Z V C Mnem Code N Z V C Непредсказуемый
~~~~~~~ ~~~~~~~ ~~~~~~~ ~~~~~~~ ~~~~~~~ ~~~~~~~ результат
HALT 000000 - - - - WAIT 000001 - - - - ~~~~~~~~~~~~~~~~~
RTI 000002 * * * * BPT 000003 * * * * JMP (Rx)+
IOT 000004 * * * * RTT 000006 * * * * JSR Rx,(Ry)+
RESET 000005 - - - - MFPT 000007 - - - - MOV Rx,(Rx)+
SPL 00023L - - - - NOP 000240 - - - - MOV Rx,-(Rx)
CLC 000241 - - - 0 CLV 000242 - - 0 - MOV Rx,@(Rx)+
CLZ 000244 - 0 - - CLN 000250 0 - - - MOV Rx,@-(Rx)
CCC 000257 0 0 0 0 SEC 000261 - - - 1 MOV PC,X
SEV 000262 - - 1 - SEZ 000264 - 1 - - MOV PC,@X
SEN 000270 1 - - - SCC 000277 1 1 1 1 ASH #37,Rx
BR 000400 - - - - BNE 001000 - - - - ASHC #37,Rx
BEQ 001400 - - - - BGE 002000 - - - -
BLT 002400 - - - - BGT 003000 - - - - Прерывание 4 или 10
BLE 003400 - - - - BPL 100000 - - - - ~~~~~~~~~~~~~~~~~~~
BMI 100400 - - - - BVC 102000 - - - - JMP Rx
BVS 102400 - - - - BHI 101000 - - - - CALL Rx
BLOS 101400 - - - - BCC 103000 - - - - HALT в режимах U, S
BCS 103400 - - - - BHIS 103000 - - - -
BLO 103400 - - - - JMP 0001DD - - - - Прерывание 10
EMT 104000 * * * * TRAP 104400 * * * * ~~~~~~~~~~~~~
MARK 0064NN - - - - JSR 004RDD - - - - TSTSET Rx
RTS 00020R - - - - SOB 077RXX - - - - WRTLCK Rx
CSM 0070DD - - - - CLR(B) .050DD 0 1 0 0 CSM в режиме K
COM(B) .051DD * * 0 1 INC(B) .052DD * * * -
DEC(B) .053DD * * * - NEG(B) .054DD * * * *
ADC(B) .055DD * * * * SBC(B) .056DD * * * * На некоторых CPU
TST(B) .057DD * * 0 0 ROR(B) .060DD * * * * SWAB не меняет V.
ROL(B) .061DD * * * * ASR(B) .062DD * * * *
ASL(B) .063DD * * * * WRTLCK 0076DD * * 0 -
TSTSET 0072DD * * 0 * SWAB 0003DD * * 0 0
SXT 0067DD - * 0 - MFPS 1067DD * * 0 -
MTPS 1064DD * * * * MTPD 1066DD * * 0 -
MTPI 0066DD * * 0 - MFPD 1065SS * * 0 -
MFPI 0065SS * * 0 - MOV(B) .1SSDD * * 0 -
CMP(B) .2SSDD * * * * BIT(B) .3SSDD * * 0 -
BIC(B) .4SSDD * * 0 - BIS(B) .5SSDD * * 0 -
ADD 06SSDD * * * * SUB 16SSDD * * * *
MUL 070RSS * * 0 * DIV 071RSS * * * *
ASH 072RSS * * * * ASHC 073RSS * * * *
XOR 074RDD * * 0 -
Поведение команд, что вспомнилось...
Тут больше чем в УКНЦ влезет, но поди не помешает ;)
Может забыл чего - в частности поведение EIS, но я и сам не особо помню что и как...
Что это такое и к чему?
Что это такое и к чему?
К тому, чтобы лучше понимать программы и не городить идиотизм вроде
ERROR: SEC
RETURN
OK: CLC
RETURN
Чем советские (да и не только) программы частенько страдают :)
К тому, чтобы лучше понимать программы и не городить идиотизм вроде
ERROR: SEC
RETURN
OK: CLC
RETURN
Чем советские (да и не только) программы частенько страдают :)
А городить надо так:
OK: TST (PC)+
ERROR: SEC
RETURN
К тому, чтобы лучше понимать программы и не городить идиотизм вроде
ERROR: SEC
RETURN
OK: CLC
RETURN
Чем советские (да и не только) программы частенько страдают :)
Все же твоя таблица напоминает что-то PDP-11, а не ВМ2. Взять те же ASC и ASCH. Никаких непредсказуемых результатов в них нет. Да и в других командах непонятно, чего там непредсказуемого?
Все же твоя таблица напоминает что-то PDP-11, а не ВМ2. Взять те же ASC и ASCH. Никаких непредсказуемых результатов в них нет. Да и в других командах непонятно, чего там непредсказуемого?
В пределах одной отдельно взятой машины вообще непредсказуемых результатов не будет. А если тебе захочется чтобы программа работала не только на УКНЦ, но и еще где-нибудь - надо считаться с возможными вариантами. Взять те же ASH и ASHC которые по разному себя поведут в описанном случае ;)
К тому, чтобы лучше понимать программы и не городить идиотизм вроде
ERROR: SEC
RETURN
OK: CLC
RETURN
Чем советские (да и не только) программы частенько страдают :)Это не идиотизм, поскольку получаемый результат соответствует ожидаемому.
...
Например,
MTPS 0 вместо
MTPS #0 - это гораздо хуже. ( А я именно так и отличился недавно - у половины MTPS забыл решётки к числам добавить и очень потом удивлялся странному поведению программы :)
DEC наверное не случайно ошибку Z пишет почти на все эти команды? ;)
В пределах одной отдельно взятой машины вообще непредсказуемых результатов не будет. А если тебе захочется чтобы программа работала не только на УКНЦ, но и еще где-нибудь - надо считаться с возможными вариантами. Взять те же ASH и ASHC которые по разному себя поведут в описанном случае ;)
Лично я не ставлю себе задачи писать на УКНЦ, чтобы это потом работало на PDP11 каких-нить. На ДВК - куда не шло. Но как справочная таблица отдельных команд, которые работаю по-разному на разных процессорах - полезно.
у половины MTPS забыл решётки к числам добавить и очень потом удивлялся странному поведению программы :)
Ну это просто ошибка - всякое бывает :)
---------- Post added at 02:47 ---------- Previous post was at 02:43 ----------
Лично я не ставлю себе задачи писать на УКНЦ, чтобы это потом работало на PDP11 каких-нить. На ДВК - куда не шло. Но как справочная таблица отдельных команд, которые работаю по-разному на разных процессорах - полезно.
Так для того и есть таблица. Команды собственно даны так, чтобы место заполнить. Кроме ASH и явно косячных JMP на регистр, все остальные компилятор и так посчитает ошибкой :)
Куда важнее таблица признаков, особенно если будешь разбирать чьи-то программы. Далеко не всегда очевидно почему автор так уверен, что вот в этом месте скажем бит C сброшен, а в этом установлен итд. Или к примеру встречал такую ошибку - при 32битном счетчике пытались оперировать командой INC вместо нужного ADD #1.
при 32битном счетчике пытались оперировать командой INC вместо нужного ADD #1.Поэтому, чтобы сэкономить одно слово в обработчике прерывания таймера RT-11 - в PSW его вектора установлен бит C (в чём легко можно убедиться, выполнив в KMON команду "E 102"):
.E 102
000341
.
а сам обработчик выглядит так:
LKINT::
ADC $TIME+2
ADC $TIME
RTI
Поэтому, чтобы сэкономить одно слово в обработчике прерывания таймера RT-11 - в PSW его вектора установлен бит C (в чём легко можно убедиться, выполнив в KMON команду "E 102"):
.E 102
000341
.
а сам обработчик выглядит так:
LKINT::
ADC $TIME+2
ADC $TIME
RTI
Это хорошо когда есть обработчик прерываний, а если это не обработчик прерываний - там все просто: один обработчик на кучу устройств и никаких проблем (всмысле тем же способом). Но далеко не всегда такие вещи используются в прерываниях :)
И здесь опять таки таблица признаков помогает. Можно к примеру сравнить R1,#1, а можно и #1,R1 и мы можем сэкономить на чем-нибудь за счет этого :)
А как на PDP11 реализуются 32-битные сумматоры, чтобы можно было пользоваться флагом арифметического переполнения V?
На тех процессорах, где есть команда ADC R0,R1, понятно. Просто делаешь ADD #low_byte,R0; ADC #high_byte,R1.
А на PDP11 как? И еще раз, я имею ввиду конечный флаг V, а не результат.
А как на PDP11 реализуются 32-битные сумматоры, чтобы можно было пользоваться флагом арифметического переполнения V?
На тех процессорах, где есть команда ADC R0,R1, понятно. Просто делаешь ADD #low_byte,R0; ADC #high_byte,R1.
А на PDP11 как? И еще раз, я имею ввиду конечный флаг V, а не результат.
ADC - базовая команда и есть везде.
Что до флага V, тут он мало поможет ибо переполнение - это переход от 77777 к 100000
И здесь опять таки таблица признаков помогает. Можно к примеру сравнить R1,#1, а можно и #1,R1 и мы можем сэкономить на чем-нибудь за счет этого :)
Это из той же оперы?
CMP R1,#1
ADC R2
ADC R3
Только таблица здесь не поможет, надо знать как признаки формируются.
ADC - базовая команда и есть везде.
На PDP11 она одноперандная. R0 = R0 + C. А нужно R0 = R0 + R1 + C.
Это из той же оперы?
CMP R1,#1
ADC R2
ADC R3
Только таблица здесь не поможет, надо знать как признаки формируются.
Как формаруются знать в принципе надо, а таблица поможет понять будет ли вообще флаг меняться :)
---------- Post added at 03:12 ---------- Previous post was at 03:11 ----------
На PDP11 она одноперандная. R0 = R0 + C. А нужно R0 = R0 + R1 + C.
А-а - вон ты про что.
ADD L1,L2
ADC H2
ADD H1,H2
- это всмысле как 32 бита сложить с 32 битами
а как ты написал - думаю и так понятно
А-а - вон ты про что.
ADD L1,L2
ADC H2
ADD H1,H2
Нет, так получим лишь правильный результат, а не правильный флаг V.
Нет, так получим лишь правильный результат, а не правильный флаг V.
Так получим правильный 32битный флаг V.
Так получим правильный 32битный флаг V.
Нет.
Мы даже не получим правильный флаг C, если, например:
0xFFFF +
0x0001 =
0x0000
Флаг C должен быть установлен, но такой конструкцией из трех команд его не будет. Т.к. команда ADD 0x00,0x00 не установит флаг C.
Нет.
Мы даже не получим правильный флаг C, если, например:
0xFFFF +
0x0001 =
0x0000
Флаг C должен быть установлен, но такой конструкцией из трех команд его не будет. Т.к. команда ADD 0x00,0x00 не установит флаг C.
И в каком месте мы C не получим?
А, ну да, лично проверил командой INC, а таблица признаков нам неинтересна? ;)
И в каком месте мы C не получим?
А, ну да, лично проверил командой INC, а таблица признаков нам неинтересна? ;)
В таком.
При конструкции:
ADD L1,L2
ADC H2
ADD H1,H2
Флаг C будет установлен после команды ADC H2,
и опять сброшен после ADD H1,H2
Нет.
Мы даже не получим правильный флаг C, если, например:
0xFFFF +
0x0001 =
0x0000
Флаг C должен быть установлен, но такой конструкцией из трех команд его не будет. Т.к. команда ADD 0x00,0x00 не установит флаг C.
А с какого перепугу он не установится. Числа складываем 16-разрядные, результат 0, и флаг C установлен. Но складывать с помощью ADD.
В таком.
При конструкции:
ADD L1,L2
ADC H2
ADD H1,H2
Флаг C будет установлен после команды ADC H2,
и опять сброшен после ADD H1,H2
Так он правильно будет сброшен потому что если 32битное число не вылезло за границу - C и не должен быть установлен. А если вылезло - он будет установлен. Или ты хочешь вычислять 32 бита, а флаги на 16 бит?
Так он правильно будет сброшен потому что если 32битное число не вылезло за границу - C и не должен быть установлен. А если вылезло - он будет установлен. Или ты хочешь вычислять 32 бита, а флаги на 16 бит?
Ой, вру. Неправильно написал пример.
Вот числа для примера.
0xFFFFFFFF +
0x00000001 =
0x00000000
В таком.
При конструкции:
ADD L1,L2
ADC H2
ADD H1,H2
Флаг C будет установлен после команды ADC H2,
и опять сброшен после ADD H1,H2
Titus, надо конкретный 32-разрядный пример.
Titus, надо конкретный 32-разрядный пример.
Вывше ты его написал. В этор случае C *будет* установлен.
Вывше ты его написал. В этор случае C *будет* установлен.
Не будет.
ADD L1,L2 L2 = 0xFFFF + 0x0001 = 0x0000 (C установлен)
ADC H2 H2 = 0xFFFF + C = 0x0000 (C установлен)
ADD H1,H2 H2 = 0x0000 + 0x0000 = 0x0000 (C сброшен)
Не будет.
ADD L1,L2 L2 = 0xFFFF + 0x0001 = 0x0000 (C установлен)
ADC H2 H2 = 0xFFFF + C = 0x0000 (C установлен)
ADD H1,H2 H2 = 0x0000 + 0x0000 = 0x0000 (C сброшен)
Да, правда не будет.
В сингере кажется описан вариант решения.
Да, правда не будет.
Я о том и говорю. Это типичная проблема флагов C и V, при отсуствии механизма непрерывного каскадного сложения. Интересно было послушать, как вы выходите из положения. Но, судя по всему, даже не сталкивались)
Я о том и говорю. Это типичная проблема флагов C и V, при отсуствии механизма непрерывного каскадного сложения. Интересно было послушать, как вы выходите из положения. Но, судя по всему, даже не сталкивались)
Да просто обычно не нужно :)
На счет выхода из положения - вроде в сингере про подобное было написано. У Арсения на сайте есть книга.
Чаще требуется сложить 16 битное к 32битному, а тут проблем нет :)
Да просто обычно не нужно :)
На счет выхода из положения - вроде в сингере про подобное было написано. У Арсения на сайте есть книга.
Чаще требуется сложить 16 битное к 32битному, а тут проблем нет :)
Мне было нужно, и посожалел, что на PDP11 нет ADC с двумя аргументами.
Похоже, что нужно делать что-то вроде:
ADD L1,L2
ADC H2
MFPS -(SP)
BIC #177774,(SP)
ADD H1,H2
MFPS -(SP)
BIC #177774,(SP)
BIS (SP)+,(SP)
MTPS (SP)+
MFPS не является обязательной командой - заточка под место :)
Вот он пример из книги:
.MACRO MPADD X,Y ?L1,?L2
MOV X,R1
MOV Y,R2
MOV #10,R0
CLC
L1: MOV R2,-(SP)
MOV R0,-(SP)
L2: ADC -(R2)
SOB R0,L2
BVS ERROR
MOV (SP)+,R0
MOV (SP)+,R2
ADD -(R1),-(R2)
SOB R0,L1
BVS ERROR
.ENDM
Это пример для знаковых чисел. Если BVS заменить на BCS, то это уже будет для беззнаковых.
Вот он пример из книги:
.MACRO MPADD X,Y ?L1,?L2
MOV X,R1
MOV Y,R2
MOV #10,R0
CLC
L1: MOV R2,-(SP)
MOV R0,-(SP)
L2: ADC -(R2)
SOB R0,L2
BVS ERROR
MOV (SP)+,R0
MOV (SP)+,R2
ADD -(R1),-(R2)
SOB R0,L1
BVS ERROR
.ENDM
Это пример для знаковых чисел. Если BVS заменить на BCS, то это уже будет для беззнаковых.
Во! Оно самое - из Сингера :)
Кстати первая книга была по теме и до сих пор считаю лучшей, хоть там и опечатки :)
MFPS не является обязательной командой - заточка под место :)
Если сложение флагов C по OR - правильное решение, то с флагом V - не факт.
Titus, а все-таки интересно, что за многомногоразрядное число Вам понадобилось складывать на УКНЦ, да еще понадобились флаги V и C.
Если сложение флагов C по OR - правильное решение, то с флагом V - не факт.
Я к тому, что команда MFPS не везде есть - не входит она в базовый набор команд. Чтобы не ссылаться на PDP-11, сошлюсь на Электронику 100-25 :)
Titus, а все-таки интересно, что за многомногоразрядное число Вам понадобилось складывать на УКНЦ, да еще понадобились флаги V и C.
Очень просто. Думал над эмуляцией Z80. А там, как известно есть команда ADC с двумя операндами. И хоть она и 8-битная, да только за один раз надо складывать 3 значения, arg1, arg2 и C. И, соответственно, правилзьно выставлять флаги C и V. Получается громоздко.
Если сложение флагов C по OR - правильное решение, то с флагом V - не факт.Почему?
Очень просто. Думал над эмуляцией Z80. А там, как известно есть команда ADC с двумя операндами. И хоть она и 8-битная, да только за один раз надо складывать 3 значения, arg1, arg2 и C. И, соответственно, правилзьно выставлять флаги C и V. Получается громоздко.
Эмуляция Z80 на УКНЦ ????? :o:o:o О, это круто, но зачем, тормозить же будет.
Да и вряд ли это громоздко будет, сложить же три числа, а сложение в PDP-11 только 16-разрядное, так что бит 8 - это и есть бит C, а с V подумать надо, тут его только по алгоритму вычислять надо.
А кстати у Z80 есть 16-разрядный ADC ?
Эмуляция Z80 на УКНЦ ????? :o:o:o О, это круто, но зачем, тормозить же будет.
Да и вряд ли это громоздко будет, сложить же три числа, а сложение в PDP-11 только 16-разрядное, так что бит 8 - это и есть бит C, а с V подумать надо, тут его только по алгоритму вычислять надо.
А кстати у Z80 есть 16-разрядный ADC ?
Интерпретивная эмуляции да, будет. А рекомпилируемая будет примерно на равне. Это даже скорее идея была не эмуляции, я рекомпиляции)
Знаю я этот алгоритм для V.
Есть 16-разрядный тоже.
Titus, а может Вы по примеру эмулятора БК пишете эмулятор Спектрума на УКНЦ?
Titus, а может Вы по примеру эмулятора БК пишете эмулятор Спектрума на УКНЦ?
Не напишу. В БК тот же самый практически проц. А Z80 сильно отличается. А дикие тормоза не нужны.
Если сложение флагов C по OR - правильное решение, то с флагом V - не факт.Почему флаги V нельзя объединять по OR?
Не напишу. В БК тот же самый практически проц. А Z80 сильно отличается. А дикие тормоза не нужны.
Тогда я не понял для чего интерпретивная и рекомпилируемая эмуляции?
Почему флаги V нельзя объединять по OR?
Лень проверять, но интуитивно мне так кажется)
---------- Post added at 00:07 ---------- Previous post was at 00:06 ----------
Тогда я не понял для чего интерпретивная и рекомпилируемая эмуляции?
Интерпретивная - это обычная эмуляция. В данном случае, она бы торомозила раз... в 4 точно.
Рекомпилируемая - это сначала в полу-автоматическом режиме программа перекомпилируется под PDP11, а потом уже этот нативный код запускается.
Но это только идея.
Лень проверять, но интитивно мне так кажется)Полагаю, что это ошибочное ощущение.
Дело в том, что и C, и V - это "циклические" флаги, поэтому механизмы их "наследования" в цепочных операциях не могут быть разными.
Т.е. если "суммарный" признак C двух операций можно и нужно определять по OR - значит и признак V - тоже.
Подагаю, что это ошибочное ощущение.
Дело в том, что и C, и V - это "циклические" флаги, поэтому механизмы их "наследования" в цепочных операциях не могут быть разными.
Т.е. если "суммарный" признак C двух операций можно и нужно определять по OR - значит и признак V - тоже.
Для V достаточно знать самый старший бит до и после операции по идее и ничего больше не нужно.
---------- Post added at 04:15 ---------- Previous post was at 04:14 ----------
Есть впрочем одно исключение - при операции смены знака :)
Признак Z двух операций нужно определять по AND, а признак N - по результату последней (вроде так)..
Полагаю, что это ошибочное ощущение.
Дело в том, что и C, и V - это "циклические" флаги, поэтому механизмы их "наследования" в цепочных операциях не могут быть разными.
Т.е. если "суммарный" признак C двух операций можно и нужно определять по OR - значит и признак V - тоже.
Ну тогда вот вам пример.
Складываем два числа 0x7FFF.FFFF и 0x8001.0001
0x8001.0001 - это -0x7FFEFFFF
Понятно, что в сумме они нам дадут 0x0001.0000
Где флаг V = 0, т.к. арифметического переполнения не было.
Теперь вычисляем каскадно.
ADD L1,L2 L2 = 0xFFFF + 0x0001 = 0x0000
ADC H2 H2 = 0x7FFF + C = 0x8000 (V установлен)
ADD H1,H2 H2 = 0x8000 + 0x8001 = 0x0001 (V установлен)
В итоге, в обоих двух последних каскадах получили флаги V, хотя финально он должен быть сброшен.
Для V достаточно знать самый старший бит до и после операции по идее и ничего больше не нужно.При эмуляции команды ADD X,Y признак V определяется так:
if( ((X < 0 && Y < 0) || (X >= 0 && Y >= 0)) &&
((Res < 0 && Y >= 0) || (Res >= 0 && Y < 0)) )
{
PSW |= V;
}
---------- Post added at 00:31 ---------- Previous post was at 00:25 ----------
В итоге, в обоих двух последних каскадах получили флаги V, хотя финально он должен быть сброшен.Значит, флаг V цикличен с периодом на один бит меньше, чем флаг C, поэтому за один 16-битный цикл прибавлений единицы - флаг C установится один раз, а флаг V - два раза.
Я правильно понял?
Значит, флаг V цикличен с периодом на один бит меньше, чем флаг C, поэтому за один 16-битный цикл прибавлений единицы - флаг C установится один раз, а флаг V - два раза.
Я правильно понял?
Нет, он цикличен с таким же периодом, но со смещением на пол-периода.
Например, для 8-битных чисел, точка перехода для C - это 0xFF, а точка перехода для V - это 0x7F.
---------- Post added at 00:38 ---------- Previous post was at 00:34 ----------
Кстати, смею предположить, что корректно будет брать флаги V с двух последних каскадов сложенные по xor.
Нет, он цикличен с таким же периодом, но со смещением на пол-периода.
Например, для 8-битных чисел, точка перехода для C - это 0xFF, а точка перехода для V - это 0x7F.Получается, что флаг V итоговой операции можно определять через флаг C, но для этого нужно повторить операцию, предварительно сместив биты операндов.
А как нужно сместить операнды, чтобы "суммарный" бит C новой операции соответствовал суммарному биту V "оригинала" ?
Получается, что флаг V итоговой операции можно определять через флаг C, но для этого нужно повторить операцию, предварительно сместив биты операндов.
А как нужно сместить операнды, чтобы "суммарный" бит C новой операции соответствовал суммарному биту V "оригинала" ?
Думаю, что это очень накладно. Есть легче способы. Я предложил один из них.
смею предположить, что корректно будет брать флаги V с двух последних каскадов сложенные по xor.Т.е. C по OR, V по XOR, Z по AND и N по результату - выглядит красиво :)
Т.е. C по OR, V по XOR, Z по AND и N по результату - выглядит красиво :)
А в конце процедуры CCC и наполненный битами ноп-260 :)
В таком случае программа точной имитации 32-разрядного сложения может выглядеть так:
MOV #<NOP>,SETPSW
CLR Cflag
CLR Vflag
CLR Zflag
ADD L1,L2
BNE 1$
BIS #4,Zflag
1$:
ADC H2
BVC 2$
BIS #2,Vflag
2$:
ADC Cflag
ADD H1,H2
BMI 3$
BNE 4$
BVC 5$
BIS #2,SETPSW
5$:
BR DONE
3$:
BVC 6$
BIS #2,SETPSW
6$:
BIS #10,SETPSW
BR 7$
4$:
BVC 7$
BIS #2,SETPSW
7$:
BIC #4,Zflag
DONE:
ADC SETPSW
BIS Cflag,SETPSW
ADD Vflag,SETPSW
BIC #4,SETPSW
BIS Zflag,SETPSW
CCC
SETPSW:
NOP
В таком случае программа точной имитации 32-разрядного сложения может выглядеть так
Лень думать, но как вариант: добавить к приемнику неявную 16битную старшую часть сверх значения и посмотреть что получится :)
Обдумывать сил нет уже - спать хочу :)
Для проверки правильности работы программы имитации 32-разрядного сложения - добавил в эмулятор команду Add32, выполняющую прибавление 32-разрядного числа с адресом в R0 к 32-разрядному числу с адресом в R1:
if( nWord == 040 )
{ // Add_32_32 -- Add32 (R0),(R1)
word addr00 = R0 &(~1);
word addr02 = addr00 + 2;
dword src = WORD(addr02);
src <<= 16;
src |= WORD(addr00);
word addr10 = R1 &(~1);
word addr12 = addr10 + 2;
dword dst = WORD(addr12);
dst <<= 16;
dst |= WORD(addr10);
word flags;
__asm {
mov EAX, dst
add EAX, src
pushf
mov dst, EAX
pop AX
mov flags,AX
}
WORD(addr10) = (word)dst;
WORD(addr12) = (word)(dst>>16);
PSW &= ~(N|Z|V|C);
if( flags & BIT_0 ) { PSW |= C; }
if( flags & BIT_11 ) { PSW |= V; }
if( flags & BIT_6 ) { PSW |= Z; }
if( flags & BIT_7 ) { PSW |= N; }
continue;
}
В приложении - программа тестирования.
Результат запуска:
.RU ADD32
Add32 Test v1.0
******************************
SRC: 0x0000'0000 (0)
DST: 0x0000'0000 (0)
Add32 : 0x0000'0000 (0) ; PSW: 004 : N[0] Z[1] V[0] C[0]
$Add32 : 0x0000'0000 (0) ; PSW: 004 : N[0] Z[1] V[0] C[0]
******************************
SRC: 0x0000'0001 (1)
DST: 0x0000'0000 (0)
Add32 : 0x0000'0001 (1) ; PSW: 000 : N[0] Z[0] V[0] C[0]
$Add32 : 0x0000'0001 (1) ; PSW: 000 : N[0] Z[0] V[0] C[0]
******************************
SRC: 0x0000'0001 (1)
DST: 0x0000'0001 (1)
Add32 : 0x0000'0002 (2) ; PSW: 000 : N[0] Z[0] V[0] C[0]
$Add32 : 0x0000'0002 (2) ; PSW: 000 : N[0] Z[0] V[0] C[0]
******************************
SRC: 0x0000'0001 (1)
DST: 0xFFFF'FFFF (-1)
Add32 : 0x0000'0000 (0) ; PSW: 005 : N[0] Z[1] V[0] C[1]
$Add32 : 0x0000'0000 (0) ; PSW: 005 : N[0] Z[1] V[0] C[1]
******************************
SRC: 0x0000'0002 (2)
DST: 0xFFFF'FFFF (-1)
Add32 : 0x0000'0001 (1) ; PSW: 001 : N[0] Z[0] V[0] C[1]
$Add32 : 0x0000'0001 (1) ; PSW: 001 : N[0] Z[0] V[0] C[1]
******************************
SRC: 0xFFFF'FFFF (-1)
DST: 0x0000'0001 (1)
Add32 : 0x0000'0000 (0) ; PSW: 005 : N[0] Z[1] V[0] C[1]
$Add32 : 0x0000'0000 (0) ; PSW: 005 : N[0] Z[1] V[0] C[1]
******************************
SRC: 0xFFFF'FFFF (-1)
DST: 0xFFFF'FFFF (-1)
Add32 : 0xFFFF'FFFE (-2) ; PSW: 011 : N[1] Z[0] V[0] C[1]
$Add32 : 0xFFFF'FFFE (-2) ; PSW: 011 : N[1] Z[0] V[0] C[1]
******************************
SRC: 0x7FFF'FFFF (2'147'483'647)
DST: 0x8001'0001 (-2'147'418'111)
Add32 : 0x0001'0000 (65'536) ; PSW: 001 : N[0] Z[0] V[0] C[1]
$Add32 : 0x0001'0000 (65'536) ; PSW: 001 : N[0] Z[0] V[0] C[1]
******************************
SRC: 0x8001'0001 (-2'147'418'111)
DST: 0x7FFF'FFFF (2'147'483'647)
Add32 : 0x0001'0000 (65'536) ; PSW: 001 : N[0] Z[0] V[0] C[1]
$Add32 : 0x0001'0000 (65'536) ; PSW: 001 : N[0] Z[0] V[0] C[1]
******************************
SRC: 0x0000'0001 (1)
DST: 0x7FFF'FFFE (2'147'483'646)
Add32 : 0x7FFF'FFFF (2'147'483'647) ; PSW: 000 : N[0] Z[0] V[0] C[0]
$Add32 : 0x7FFF'FFFF (2'147'483'647) ; PSW: 000 : N[0] Z[0] V[0] C[0]
******************************
SRC: 0x0000'0001 (1)
DST: 0x7FFF'FFFF (2'147'483'647)
Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 012 : N[1] Z[0] V[1] C[0]
$Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 012 : N[1] Z[0] V[1] C[0]
******************************
SRC: 0xFFFF'FFFF (-1)
DST: 0x8000'0001 (-2'147'483'647)
Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 011 : N[1] Z[0] V[0] C[1]
$Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 011 : N[1] Z[0] V[0] C[1]
******************************
SRC: 0xFFFF'FFFF (-1)
DST: 0x8000'0000 (-2'147'483'648)
Add32 : 0x7FFF'FFFF (2'147'483'647) ; PSW: 003 : N[0] Z[0] V[1] C[1]
$Add32 : 0x7FFF'FFFF (2'147'483'647) ; PSW: 003 : N[0] Z[0] V[1] C[1]
******************************
Вроде, всё правильно.
Есть ещё какие-то граничные случаи, которые нужно протестировать дополнительно ?
Есть ещё какие-то граничные случаи, которые нужно протестировать дополнительно ?
Для проверки просто перебирают все комбинации, и все)
Для проверки просто перебирают все комбинации, и все)Я не очень силён в арифметике, но 2**32**32 циклов эмуляции полного выполнения подпрограммы тестирования могут (как мне кажется ) занять больше времени, чем хотелось бы :)
Я не очень силён в арифметике, но 2**32**32 циклов эмуляции полного выполнения подпрограммы тестирования могут (как мне кажется ) занять больше времени, чем хотелось бы :)
Да)
Поэтому как вариант, выкидывать перебор бит в диапазоне, допустим, 3..29 бита, таким образом числа редуцируются до 5-6 бит)
Проверил ещё немного входных данных:
.W3232 0000 8000 7fff 8000
.W3232 0002 0000 7ffe 0000
.W3232 0001 0000 7ffe 0000
.W3232 0001 8000 7ffe 8000
.W3232 7fff 0000 7fff 0000
.W3232 8000 0000 7fff 0000
.W3232 8001 0001 7fff ffff
.W3232 7fff ffff 8001 0001
.W3232 8000 0000 8000 0000
.W3232 ffff 0000 8000 0000
.W3232 ffff 8000 8000 8000
Ошибок нет:
.RU ADD32
Add32 Test v1.1
******************************
SRC: 0x0000'8000 (32'768)
DST: 0x7FFF'8000 (2'147'450'880)
Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 012 : N[1] Z[0] V[1] C[0]
$Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 012 : N[1] Z[0] V[1] C[0]
******************************
SRC: 0x0002'0000 (131'072)
DST: 0x7FFE'0000 (2'147'352'576)
Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 012 : N[1] Z[0] V[1] C[0]
$Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 012 : N[1] Z[0] V[1] C[0]
******************************
SRC: 0x0001'0000 (65'536)
DST: 0x7FFE'0000 (2'147'352'576)
Add32 : 0x7FFF'0000 (2'147'418'112) ; PSW: 000 : N[0] Z[0] V[0] C[0]
$Add32 : 0x7FFF'0000 (2'147'418'112) ; PSW: 000 : N[0] Z[0] V[0] C[0]
******************************
SRC: 0x0001'8000 (98'304)
DST: 0x7FFE'8000 (2'147'385'344)
Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 012 : N[1] Z[0] V[1] C[0]
$Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 012 : N[1] Z[0] V[1] C[0]
******************************
SRC: 0x7FFF'0000 (2'147'418'112)
DST: 0x7FFF'0000 (2'147'418'112)
Add32 : 0xFFFE'0000 (-131'072) ; PSW: 012 : N[1] Z[0] V[1] C[0]
$Add32 : 0xFFFE'0000 (-131'072) ; PSW: 012 : N[1] Z[0] V[1] C[0]
******************************
SRC: 0x8000'0000 (-2'147'483'648)
DST: 0x7FFF'0000 (2'147'418'112)
Add32 : 0xFFFF'0000 (-65'536) ; PSW: 010 : N[1] Z[0] V[0] C[0]
$Add32 : 0xFFFF'0000 (-65'536) ; PSW: 010 : N[1] Z[0] V[0] C[0]
******************************
SRC: 0x8001'0001 (-2'147'418'111)
DST: 0x7FFF'FFFF (2'147'483'647)
Add32 : 0x0001'0000 (65'536) ; PSW: 001 : N[0] Z[0] V[0] C[1]
$Add32 : 0x0001'0000 (65'536) ; PSW: 001 : N[0] Z[0] V[0] C[1]
******************************
SRC: 0x7FFF'FFFF (2'147'483'647)
DST: 0x8001'0001 (-2'147'418'111)
Add32 : 0x0001'0000 (65'536) ; PSW: 001 : N[0] Z[0] V[0] C[1]
$Add32 : 0x0001'0000 (65'536) ; PSW: 001 : N[0] Z[0] V[0] C[1]
******************************
SRC: 0x8000'0000 (-2'147'483'648)
DST: 0x8000'0000 (-2'147'483'648)
Add32 : 0x0000'0000 (0) ; PSW: 007 : N[0] Z[1] V[1] C[1]
$Add32 : 0x0000'0000 (0) ; PSW: 007 : N[0] Z[1] V[1] C[1]
******************************
SRC: 0xFFFF'0000 (-65'536)
DST: 0x8000'0000 (-2'147'483'648)
Add32 : 0x7FFF'0000 (2'147'418'112) ; PSW: 003 : N[0] Z[0] V[1] C[1]
$Add32 : 0x7FFF'0000 (2'147'418'112) ; PSW: 003 : N[0] Z[0] V[1] C[1]
******************************
SRC: 0xFFFF'8000 (-32'768)
DST: 0x8000'8000 (-2'147'450'880)
Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 011 : N[1] Z[0] V[0] C[1]
$Add32 : 0x8000'0000 (-2'147'483'648) ; PSW: 011 : N[1] Z[0] V[0] C[1]
******************************
Проверил ещё немного входных данных:
Ошибок нет:
Чтобы точно убедиться в правильности алгоритма, недостаточно умозрительных предположений, относительно поведений флагов. Нужно или же четко обосновать их, либо же сделать тест, который переберет все варианты, либо же все варианты в зоне влияния флагов, что опять же должно быть обосновано.
Чтобы точно убедиться в правильности алгоритма, недостаточно умозрительных предположений, относительно поведений флагов. Нужно или же четко обосновать их, либо же сделать тест, который переберет все варианты, либо же все варианты в зоне влияния флагов, что опять же должно быть обосновано.1. Думаю, что относительно поведения флага N умозрительных предположений вполне достаточно.
Флаг N копирует старший бит результата.
2. Относительно флага Z тоже всё ясно - если хотя бы один бит результата отличен от 0 - флаг сбрасывается, иначе - устанавливается.
3. С флагом C больших проблем также не видно. Если был перенос из старшего разряда - флаг C устанавливается, иначе - сбрасывается.
4. Единственный не вполне очевидный флаг - флаг V.
Но все возможные комбинации влияющих на него операндов я уже протестировал.
Если не все - то какие ещё комбинации нужно протестировать ?
Если не все - то какие ещё комбинации нужно протестировать ?
Я не знаю, меня вопрос этого флага интересовал только вскользь, поэтому единственное, что могу предложить - это обосновать V теоретически, или же перебрать все 4 миллиарда в квадрате значения)
Я не знаю, меня вопрос этого флага интересовал только вскользь, поэтому единственное, что могу предложить - это обосновать V теоретически, или же перебрать все 4 миллиарда в квадрате значения)Теоретическое обоснование (на мой взгляд) несложно.
Флаг V устанавливается, только когда результат меняет знак. Поэтому, если результат меняет знак дважды (четырежды и т.д.) - флаг V сбрасывается.
Отсюда - если при всех операциях со старшим словом приёмника флаг V был установлен нечётное число раз - итоговый флаг V устанавливается, иначе - сбрасывается (что и реализовано).
Флаг V устанавливается, только когда результат меняет знак. Поэтому, если результат меняет знак дважды (четырежды и т.д.) - флаг V сбрасывается.
Нет, флаг V устанавливается, когда результат не просто меняет знак, а меняет знак в связи с тем, что число вышло за пределы разрядности. Тогда как смена знака через ноль, на флаг V не влияет.
Или говоря иначе. Если был перенос в знаковый разряд, но не было переноса во флаг C, или же был перенос во флаг C, но не было переноса в знаковый разряд - флаг V устанавливается.
В описании KDJ11 дается четкое определение (взято из описания ADD):
V: set if there was arithmetic overflow as a result of the operation, that is,
both operands were of the same sign and the result was of the opposite
sign; cleared otherwise
В описании KDJ11 дается четкое определение (взято из описания ADD):
V: set if there was arithmetic overflow as a result of the operation, that is,
both operands were of the same sign and the result was of the opposite
sign; cleared otherwise
Это та же самая логика работы, что и я описал)
Это та же самая логика работы, что и я описал)
Логика та же, просто тут слова проще :)
---------- Post added at 06:30 ---------- Previous post was at 06:20 ----------
А что до логики, я уже раньше говорил, что достаточно знать старший разряд до и после операции, а C мы очень легко не теряем при 32битных операциях :)
Нет, флаг V устанавливается, когда результат не просто меняет знак, а меняет знак в связи с тем, что число вышло за пределы разрядности. Тогда как смена знака через ноль, на флаг V не влияет.Если внимательно прочитать написанное, то можно понять, что именно это и имелось в виду.
Но помимо этого было отмечено, что установка флага V *всегда* означает смену знака результата.
Если флаг V был установлен, значит результат изменил знак.
Следовательно, если результат не изменил знак - флаг V не может быть установлен.
Теперь понятнее..
Если внимательно прочитать написанное, то можно понять, что именно это и имелось в виду.
Но помимо этого было отмечено, что установка флага V *всегда* означает смену знака результата.
Если флаг V был установлен, значит результат изменил знак.
Следовательно, если результат не изменил знак - флаг V не может быть установлен.
Теперь понятнее..
Да. Главное не забыть, что обратное отсюда не следует - если результат сменил знак, отсюда не следует что установлен V :)
Да. Главное не забыть, что обратное отсюда не следует - если результат сменил знак, отсюда не следует что установлен VЭто нас не волнует, поскольку мы используем "готовый" признак V, который процессор формирует именно тогда, когда надо. Наша задача лишь в том, чтобы определить тот случай, когда этот признак устанавливается чётное число раз, а значит - должен быть сброшен, поскольку чётное изменение знака оставляет его НЕИЗМЕННЫМ.
Так ещё понятнее :)
...
Максимальным быстродействием (на мой взгляд) обладает древовидная версия алгоритма, которую предлагаю обсудить:
$Add32:
Add L1, L2
BEq LZ
AdC H2
BVS LV
BCS LC
Add H1, H2
ClZ
Return
LC:
Add H1, H2
SeC
ClZ
Return
LV:
BCS LVC
Add H1, H2
BVS HV
SeV
ClZ
Return
LVC:
Add H1, H2
SeC
BVS HV
SeV
ClZ
Return
HV:
<ClZ>!<ClV>
Return
LZ:
AdC H2
BVS LZV
BCS LZC
Add H1, H2
Return
LZC:
Add H1, H2
SeC
Return
LZV:
BCS LZVC
Add H1, H2
BVS HZV
SeV
Return
LZVC:
Add H1, H2
SeC
BVS HZV
SeV
Return
HZV:
ClV
Return
Думать лень. CLZV требует дополнительного описания.
Можно сделать без описания в виде <CLZ>!<CLV> :)
Для завершения доказательства правильности алгоритма необходимо убедиться в невозможности последовательного возникновения следующих двух событий:
1. Инкремент 16-разрядного приёмника приводит к изменению его знака без установки флага V.
2. Прибавление 16-разрядного источника приводит к установке флага V.
Для завершения доказательства правильности алгоритма необходимо убедиться в невозможности последовательного возникновения следующих двух событий:
1. Инкремент 16-разрядного приёмника приводит к изменению его знака без установки флага V.
2. Прибавление 16-разрядного источника приводит к установке флага V.
Инкремент устанавливает V только в одном случае: 77777 -> 100000.
Другой случай изменения знака дает 0 в результате.
---------- Post added at 08:30 ---------- Previous post was at 08:25 ----------
Ну а прибавление к нулю соответственно V не дает никогда.
Инкремент устанавливает V только в одном случае: 77777 -> 100000.
Другой случай изменения знака дает 0 в результате.Поскольку при 0 в результате никакое каскадное суммирование не сможет установить флаг V - верность алгоритма доказана.
Да, мы ещё забыли случай, когда положительное 16-разрядное число прибавляется к 0100000 с изменением знака приёмника, но такое явно невозможно во всём диапазоне от 0 до 77777.
---------- Post added at 11:29 ---------- Previous post was at 10:37 ----------
сложение в PDP-11 только 16-разрядное, так что бит 8 - это и есть бит C, а с V подумать надо, тут его только по алгоритму вычислять надо.Когда байты, используемые в эмуляторе для хранения 8-разрядных значений источника и приёмника - имеют нечётные адреса, а предыдущие байты с чётными адресами равны нулю - тогда 16-разрядное сложение слов с нечётными адресами будет давать правильный 8-разрядный результат с корректной установкой всех флагов в PSW.
Да, мы ещё забыли случай, когда положительное 16-разрядное число прибавляется к 0100000 с изменением знака приёмника, но такое явно невозможно во всём диапазоне от 0 до 77777.
Каким образом можно прибавить положительное 16-разрядное число к 0x8000 с изменением знака, если самое большое положительное число - это 0x7FFF?
Каким образом можно прибавить положительное 16-разрядное число к 0x8000 с изменением знака, если самое большое положительное число - это 0x7FFF?Если бы такое было возможно - Ваш алгоритм определения признака V не был бы исчерпывающим.
Но такое невозможно, поэтому использованный алгоритм определения признака V предусматривает все возможные варианты результатов операций ADC H2 и ADD H1,H2.
Кстати, поскольку предложенный выше древовидный алгоритм не имеет внутренних состояний (т.е. не использует переменные) - для тестирования его правильности необходимо и достаточно, чтобы однократное выполнение каждой ветви дало правильный результат.
Так..
---------- Post added at 15:22 ---------- Previous post was at 14:23 ----------
Не так - нужно гарантировать исчерпывающий охват всех комбинаций признаков. Иначе даже алгоритм с единственной ветвью может быть признан правильным.
Подскажите пожалуйста, как такую вот конструкцию на МАКРО-11 правильно соорудить?
PROCEDURE TTYOUT(N:INTEGER);
CONST R=200B;
VAR A ORIGIN 177564B, D ORIGIN 177566B:INTEGER;
BEGIN
WHILE (A AND R)=0 DO;
D:=N;
END; /* THIS PROCEDURE WAS COPIED FROM HPIC.PAS */
Спасибо )
---------- Post added at 17:09 ---------- Previous post was at 15:47 ----------
Отвечаю сам себе )))
...
PROCEDURE TTYOUT(N:INTEGER);
CONST R=200B;
VAR A ORIGIN 177564B, D ORIGIN 177566B:INTEGER;
BEGIN
WHILE (A AND R)=0 DO;
D:=N;
END; /* THIS PROCEDURE WAS COPIED FROM HPIC.PAS */
...
1$: CLR @#177564
TST @#177564
BEQ 1$
(вот как эта константа R (ЧТО ЭТО - УСЛОВИЕ?СОСТОЯНИЕ? ? я "тугой-тугой!")
MOVE N(SP), @#177566
КАК ТО ТАК НАВЕРНОЕ?
CONST R=200B;
VAR A ORIGIN 177564B:INTEGER;
WHILE (A AND R)=0 DO;
Эквивалентно:
1$: BIT #200, @#177564
BEQ 1$
Но проще так:
1$: TSTB @#177564
BPL 1$
1$: BIT #200, @#177564
BEQ 1$
Но проще так:
1$: TSTB @#177564
BPL 1$
Спасибо, Patron ! Я просто плаваю в этом откровенно, просто именно такой
вариант работает, а простенький не работает ) То есть сравнение с нулём но с приставкой B и даже значение #200 как бы и не нужно.
То есть получится Макрос можно так оформить
.MACRO .TTT COM
1$: TSTB @#177564
BPL 1$
MOV COM, @#177566
.ENDM
---------- Post added at 18:01 ---------- Previous post was at 17:55 ----------
Тогда ещё вопрос - принципиально что такое параметр COM в данном макрокоманде?
Имею в виду один код или последовательность?
ПРОГРАММИРОВАНИЕ ))) Для меня это просто хобби, поэтому не удивляйтесь,
что какие-то моменты уже обжёванно - пережёванные могут мне не быть явными.
Я уже писал на форуме, что делаю простенькую (символьную, но цветную "смайл"),
игрушку для УК-НЦ. Добился очень правильной "своевременной" реакции на
нажатие кнопок путём подбора задержки внутри цикла.
Всё что сейчас работает, это "непрерывный" цикл (типо пульса)
внутри которого идут в такой последовательности:
repeat /* основной цикл */
секция-= Обновление экрана
-персонаж
-статистика
секция-=(задержка DELAY - для плавности цикла в целом
значение подбирал экспериментально)
секция-=опрос клавиатуры
оформлен так:
(через глобальные переменные (регистры УК-НЦшки)
VAR
INKEY ORIGIN 177560B: INTEGER;
KEY ORIGIN 177562B: INTEGER;
...
IF((INKEY AND 128)<>0) THEN (спасибо form'у ! - сначало
я просто ноль туда писал и был этому рад !)
...
в зависимости от значения нажатой кнопки
УПР+Ц - вызывает процедуру CANCEL (по сути EXIT,
только там можно будет что то ещё подвесить, типа
"ПОКА ПОКА!")
Либо перемещение АВАТАРА, 12346789 - меняет значение
переменной АВАТАР.НАПРАВЛЕНИЕ
5 - это стоять на месте.
секция-=смотрим изменился ли НАПРАВЛЕНИЕ и если да меняем
координаты АВАТАРА.
until 0>0 /* конец тела основного цикла */
http://s4.rimg.info/8e12b96d087ec7ce56313c229be3bf91.gif (http://smayliki.ru/smilie-473528679.html)
Это я всё к тому, что я пытался ввести одного АВАТАРА - которым
управлял бы ИИ, и начинаются беды с плавностью, то есть реакция
на клавиатуру становится немного не чёткой, а это не позволяет
управлять игроком адекватно, а ведь ещё пульки должны летать, да
и вражин лучше бы больше 1-го завести, буду рад любые советы по
оптимизации услышать - вплоть до "ЗАВЯЗЫВАЙ С ПРОГРАММАМИ, ХОБОТ!"
Прилепил недоделку что-бы можно было пощупать в UKNCBTL.
Там файл называется TGAME.SAV, дискета загрузочная.
Это просто рабочая модель. Идея игровая есть и сюжет там
будет и брифинг и всё такое, но сначала математика )))
То есть сравнение с нулём но с приставкой B и даже значение #200 как бы и не нужно.Признаком готовности к передаче байта на экран служит бит 0200 в регистре статуса передатчика.
Конструкция (A AND R)=0 ( так же как и BIT #200,@#177564 ) проверяет на равенство нулю не весь регистр статуса, а только его бит 0200.
TSTB @#177564 проверяет младший байт регистра, для которого бит 0200 является битом знака.
Метки в макросах лучше не использовать, а байт отправлять командой MOVB:
.MACRO .TTT ARG
TSTB @#177564
BPL .-4.
MOVB ARG, @#177566
.ENDM
принципиально что такое параметр COM в данном макрокоманде? Имею в виду один код или последовательность?Да, принципиально.
Чтобы результат вызова .TTT < #'Y #'E #'S > совпал с результатом вызова .TTT #'Y | .TTT #'E | .TTT #'S - макрос должен выглядеть так:
.MACRO .TTT ARGS
.IRP ARG, <ARGS>
.IF NB ARG
TSTB @#177564
BPL .-4.
MOVB ARG, @#177566
.ENDC
.ENDM
.ENDM
Метки в макросах лучше не использовать
Метки можно безопасно использовать в макросах, но нужно указать, что они являются локальными для макроса.
.MACRO XXX,?L1,?L2
L1: ...
...
L2: ...
.ENDM
Уселся попинать игрульку и снова затык с RND,
я в этой теме уже вопрос задавал - но вот дошло по практики:
FUNCTION RND: REAL;
VAR V: 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, V(SP)
*/
RND:=V/32767;
END;
Сразу скажу что функцию взял из старых исходников школьных времён.
Ей можно пользоваться, но данном случае у меня получается "узор"
и "время" для бонусов на уровне одинаковый всё время !
(см. миниатюру)
Я помню, что form, мне советовал использовать GetTime??? Но как это оформить ? Вместо RN - кидать в R1 что то из её параметров? А строка
MOV R1, RN
тогда вообще не нужна?
Хелп!
Неужели в памяти всё время одинаковый рисунок?
Должна же быть какая-то ячейка содержание которой случайно по определению и тогда её содержимое и можно было бы использовать?
Таймер?
Или RN - можно сделать глобальной и ввести дополнительную процедуру
RANDOMIZE которая бы писала туда что-то "случайное" - результат вычислений ???
:confused_std:
Нужно авторитетное мнение для "супер-программиста" hobota!
На самом деле проблема для меня в том, что из хелпа
я не вникаю в главное !!!
ПРИМЕР.
.TITLE .GTIM.MAC
;В ЭТОМ ПРИМЕРЕ ПОЛЬЗОВАТЕЛЬ ПОЛУЧАЕТ ТЕКУЩЕЕ ВРЕМЯ
;В ТИКАХ.
.MCALL .GTIM,.EXIT
START: .GTIM #AREA,#TICKS ;ОПРЕДЕЛИТЬ ТЕКУЩЕЕ
;ВРЕМЯ
.EXIT
TICKS: .WORD 0,0
AREA: .BLKW 2
.END START
Куда в этом примере пишется определённое значение?
Моя "версия", что в #TICKS ?
:confused_std:
---------- Post added at 14:26 ---------- Previous post was at 14:23 ----------
Да и макрос зависит от поддержки таймера монитором?
Может это тупик заведомо?
Если бы не TRAP
Я не большой спец по системным вызовам, поэтому всегда делаю так, как советуют в их описании.
В описании вызова .GTIM написано, что первый аргумент - адрес пустого блока из двух слов ( а не двух байтов ) для системных целей, а второй аргумент - адрес блока из двух слов, куда будет записан результат вызова:
Area: .BlkW 2
Buf: .Word 0
Ticks: .Word 0
START:
.GTIM #Area, #Buf
После вызова в слове Buf будет старшее слово счётчика тиков, а в слове Ticks - младшее ( именно оно инкрементируется 50 раз в секунду ).
В описании вызова .GTIM написано,
хочу просто убедиться, что мы один и тот же документ читаем?
5.3.16. .GTIM
ЗАПРОС .GTIM ПОЗВОЛЯЕТ ПРОГРАММЕ ОПРЕДЕЛИТЬ ТЕКУЩЕЕ
ВРЕМЯ СУТОК. ВЕЛИЧИНА ВРЕМЕНИ ОПРЕДЕЛЯЕТСЯ В ТИКАХ (1
ТИК=1/50 С).
ФОРМАТ МАКРОКОМАНДЫ:
.GTIM AREA,ADDR
ГДЕ AREA - АДРЕС БЛОКА ИЗ 2-Х СЛОВ АРГУМЕНТОВ ЕМТ;
ADDR - АДРЕС БЛОКА ИЗ 2-Х СЛОВ, СОДЕРЖАЩЕГО ЗНАЧЕНИЕ
ВРЕМЕНИ ВО ВНУТРЕННЕМ ФОРМАТЕ; ПЕРВОЕ СЛОВО СОДЕРЖИТ СТАР-
ШИЕ РАЗРЯДЫ, ВТОРОЕ СЛОВО - МЛАДШИЕ.
ФОРМАТ БЛОКА АРГУМЕНТОВ:
AREA: .BYTE 0,21
.WORD ADDR
ПОЛЬЗОВАТЕЛЬ ДОЛЖЕН ПРЕДУСМОТРЕТЬ В СВОЕЙ ПРОГРАММЕ
ОПЕРАЦИЮ ПРЕОБРАЗОВАНИЯ ТИКОВ В ЧАСЫ-МИНУТЫ-СЕКУНДЫ. В
РЕЖИМЕ FB ВЕЛИЧИНА ВРЕМЕНИ АВТОМАТИЧЕСКИ ВОССТАНАВЛИВАЕТСЯ
ПОСЛЕ 24:00:, В РЕЖИМЕ SJ ОПЕРАЦИЯ ВОССТАНОВЛЕНИЯ ВЫПОЛ-
НЯЕТСЯ, ЕСЛИ ПРИ ГЕНЕРАЦИИ СИСТЕМЫ БЫЛА ОПРЕДЕЛЕНА ПОДДЕРЖ-
КА ТАЙМЕРА.
И да, спасибо! Сейчас буду дальше двигаться, нашёл ещё вариант RND
правда он там почти "отдельная программа" - т.е. очень много строчек.
:smile:
Что находится у RT-11 по адресу ОЗУ 170?
Что находится у RT-11 по адресу ОЗУ 170?
Адрес обработчика прерываний по вектору 170 :)
Адрес обработчика прерываний по вектору 170 :)
А что это за прерывание?
---------- Post added at 16:44 ---------- Previous post was at 16:40 ----------
Не, вообще не верно. Не прерывания.
У УКНЦ там, например, число 67776. По этом адресу в ОЗУ ничего нет. Могу предположить, что это, например, число слов ОЗУ. Т.к. это похоже на правду.
А что это за прерывание?
DEC традиционно использовал для второго принтера. А так - SH DEV должен показать кто использует.
---------- Post added at 19:45 ---------- Previous post was at 19:44 ----------
Не, вообще не верно. Не прерывания.
У УКНЦ там, например, число 67776. По этом адресу в ОЗУ ничего нет. Могу предположить, что это, например, число слов ОЗУ. Т.к. это похоже на правду.
Ну вообще-то верно - это вектор прерывания из традиционной области и используется системой исключительно как вектор прерывания. А записаться туда может что угодно пока у тебя нет драйвера, использующего этот вектор.
Хотя вру, не у УКНЦ, а у .sav'ов от НЕМИГИ)
Хотя вру, не у УКНЦ, а у .sav'ов от НИМИГИ)
Область векторов прерывания перекрывается данными из SAV кроме тех, что отмечены в системном битмапе как защищенные (это системные вектора, вектора для загруженных драйверов, SYSCOM итд).
Область векторов прерывания перекрывается данными из SAV кроме тех, что отмечены в системном битмапе как защищенные (это системные вектора, вектора для загруженных драйверов, SYSCOM итд).
Ну вот когда я загружаю на УКНЦ НЕМИГ'овский .sav, по этому адресу оказывается число. И программа сразу с ним делает какие-то действия.
Ну вот когда я загружаю на УКНЦ НЕМИГ'овский .sav, по этому адресу оказывается число. И программа сразу с ним делает какие-то действия.
Возможно, программа для какого-то хитрого устройства, использующего этот вектор. У нас кажется были графические дисплеи с таким вектором, но точно уже не помню - давно это было. На них у нас рисовали печатные платы для разводки :)
Возможно, программа для какого-то хитрого устройства, использующего этот вектор. У нас кажется были графические дисплеи с таким вектором, но точно уже не помню - давно это было. На них у нас рисовали печатные платы для разводки :)
Это обычная игра Диггер.
---------- Post added at 16:53 ---------- Previous post was at 16:51 ----------
Это обычная игра Диггер.
И еще подскажите, что делает команда EMT 345?
Это обычная игра Диггер.
"Обычная" - это для VT11/VS60 итд, а все остальное может быть для конкретной машины (ДВК, УКНЦ) и конкретного железа :)
---------- Post added at 19:53 ---------- Previous post was at 19:53 ----------
Это обычная игра Диггер.
---------- Post added at 16:53 ---------- Previous post was at 16:51 ----------
И еще подскажите, что делает команда EMT 345?
Макрокоманда .CSISPC.
"Обычная" - это для VT11/VS60 итд, а все остальное может быть для конкретной машины (ДВК, УКНЦ) и конкретного железа :)
Обычная для НЕМИГИ)
---------- Post added at 16:54 ---------- Previous post was at 16:54 ----------
Макрокоманда .CSISPC.
...означающая?
Обычная для НЕМИГИ)
---------- Post added at 16:54 ---------- Previous post was at 16:54 ----------
...означающая?
Читает с терминала, командного файла или буфера строку в формате
file1,file2,file3=file1,file2,file3,...,file6
(ненужное можно опустить, выводным добавить размер в формате [размер]), разбирает односимвольные опции и значения (/A, /A:123. /B:ACD, /C:ABC:FED) и после проверки синтакса заполняет блоки данных с готовыми параметрами для .LOOKUP/.ENTER, а опции записывает в стек (с указанием номера файла на котором указаны), при этом наверху стека число опций.
---------- Post added at 20:01 ---------- Previous post was at 19:57 ----------
Чаще используется .CSIGEN которая делает то же самое, только не заполняет блоки, а сразу открывает файлы (подгрузив недостающие драйвера если надо).
А что делает конкретно эта комбинация:
MOV #664,R3
MOV #230,R2
PUSH R2
PUSH #1
PUSH R3
CLR -(SP)
EMT 345
где по адресу 664 находится строка:
16, 162, 115, 125, 17, 77, 40, 200
---------- Post added at 17:16 ---------- Previous post was at 17:11 ----------
И вообще, посмотрел файлы .sav от 4 игр для НЕМИГи, все они начинаются с одинаковых непонятных 'загрузчиков' по адресу 400.
А сами игры, т.е. те части файлов, которые начинают отличаться, начинаются уже с адреса 1000.
А что делает конкретно эта комбинация:
MOV #664,R3
MOV #230,R2
PUSH R2
PUSH #1
PUSH R3
CLR -(SP)
EMT 345
где по адресу 664 находится строка:
16, 162, 115, 125, 17, 77, 40, 200
Странная комбинация.
.CSISPC #0,R3,#0,R2
#0 - блок для заполнения спецификациями файлов (вообще по документации нулевого значения не предусмотрено, в последних версиях SYSMAC даже ругается на это. Возможно (в каких-то переделанных версиях?) просто делается контроль синтакса в этом случае
R3 - 4 слова RADIX 50 - расширения по умолчанию для трех выходных и всех входных файлов (написанное не сильно похоже на что-то вменяемое)
#0 - ввод строки с терминала
R2 - буфер куда помещается проверенная строка
И вообще, посмотрел файлы .sav от 4 игр для НЕМИГи, все они начинаются с одинаковых непонятных 'загрузчиков' по адресу 400.
А сами игры, т.е. те части файлов, которые начинают отличаться, начинаются уже с адреса 1000.
В RT-11 считается, что начиная с 500 адреса идет пользовательская область которую можно использовать и передавать от программы к программе. Область ниже отведена под вектора, но в принципе если нет устройств с такими векторами - тоже можно использовать.
расширения по умолчанию для трех выходных и всех входных файлов (написанное не сильно похоже на что-то вменяемое)
Может поменять байты местами?
Может поменять байты местами?
Да что так что эдок - не сильно удобоворимо.
Это разбор самого .SAV файла или памяти после него оставшейся?
Да что так что эдок - не сильно удобоворимо.
Это разбор самого .SAV файла или памяти после него оставшейся?
Памяти, после загрузки сава.
Вот файл:
Памяти, после загрузки сава.
Вот файл:
Память анализировать муторно. Особенно если загрузка была с запуском или если файл использует оверлеи :)
Память анализировать муторно. Особенно если загрузка была с запуском или если файл использует оверлеи :)
Ничего не муторно. Он запускается с адреса 400, с него же я и ставлю точку останова.
Разобрался еще немного. Из 4-х игр под НЕМИГУ, все запускаются с адреса 400, все имеют по этому адресу одинаковую хитрую функцию, которую я описал выше. А реальный адрес запуска у каждой игры прописан по адресу 166. Интересно зачем так.
Интересно зачем так.
Возможно переделывалось из игр для другой системы (или вообще stand).
Возможно переделывалось из игр для другой системы (или вообще stand).
Однозначно переделывалось. А что такое stand?
Однозначно переделывалось. А что такое stand?
standalone program - грузится сама по себе без всяких систем.
На УКНЦ, к слову, применялись активно :)
---------- Post added at 21:26 ---------- Previous post was at 21:25 ----------
Кстати хинт: IDA PRO умеет дизассемблить RTшные проги с опознанием макрокоманд.
standalone program - грузится сама по себе без всяких систем.
На УКНЦ, к слову, применялись активно :)
Нет, это обычный савчик.
Нет, это обычный савчик.
Ну он может быть переделан из самостоятельной проги.
Ну он может быть переделан из самостоятельной проги.
Может, но не уверен. Попробовал запустить дальше, вроде все корректно системно, только регистров таких на УКНЦ нет)
Titus, http://zx.pk.ru/attachment.php?attachmentid=38417&d=1353758141
в этом описании большой пример в параграфе 5.6.3 Макрокоманда .CSISPC
---------- Post added at 19:04 ---------- Previous post was at 19:03 ----------
Ну он может быть переделан из самостоятельной проги
из магнитофонного файла для БК0010 например )
Что за регистр на PDP11 системах по адресу 177572? При загрузке, RT-11 его проверяет. На НЕМИГЕ там, например, регистр адреса косвенной адресации к расширенной памяти. Но раз обычная RT-11 проверяет его, значит он по стандарту что-то должен значить.
Что за регистр на PDP11 системах по адресу 177572? При загрузке, RT-11 его проверяет. На НЕМИГЕ там, например, регистр адреса косвенной адресации к расширенной памяти. Но раз обычная RT-11 проверяет его, значит он по стандарту что-то должен значить.
Регистр управления MMU (MMR0):
15 - non-resident page
14 - address length error
13 - access violation
6,5 - cpu mode
4 - address space
3,2,1 - page number
^ биты ошибки, устанавливаемые при ее возникновении
0 - enable relocation
---------- Post added at 23:07 ---------- Previous post was at 23:06 ----------
Это я описал полнокровный, полнорежимный 22bit CPU. На процах попроще некоторых битов может не быть.
Заодно и в этой теме спрошу:
Horace пока не работает в связи с тем, что там функция устанавливает 7-й бит в регистре состояния приемника 0, а у меня в УКНЦ в этот бит писать нельзя. Подождем наших профессоров, послушаем, что они скажут по этому поводу)
Можно ли на УКНЦ писать в 7-й бит регистра состояния приемника канала-0 процессора? А на ДВК?
Можно ли на УКНЦ писать в 7-й бит регистра состояния приемника канала-0 процессора? А на ДВК?
Нет.
Это бит состояния, указывающий на то, что есть что брать из регистра данных. Он только для чтения.
---------- Post added at 19:07 ---------- Previous post was at 19:06 ----------
А точно нужен 7й, а не 6й? :)
Нет.
Это бит состояния, указывающий на то, что есть что брать из регистра данных. Он только для чтения.
---------- Post added at 19:07 ---------- Previous post was at 19:06 ----------
А точно нужен 7й, а не 6й? :)
Точно.
Там такая программа.
Идет опрос бита готовности, и если он готов, то программа идет далее, т.к. нажали любую клавишу.
Но! При нажатии клавиши, срабатывает прерывание, в котором читается регистр данных клавиатуры, и таким образом бит готовности сбрасывается. Но чтобы это не повлияло на основную программу, в конце обработчика прерывания этот бит устанавливается принудительно. У меня на УКНЦ в этот бит писать нельзя, поэтому данная методика не прокатывает. Может в НЕМИГЕ можно?
Точно.
Там такая программа.
Идет опрос бита готовности, и если он готов, то программа идет далее, т.к. нажали любую клавишу.
Но! При нажатии клавиши, срабатывает прерывание, в котором читается регистр данных клавиатуры, и таким образом бит готовности сбрасывается. Но чтобы это не повлияло на основную программу, в конце обработчика прерывания этот бит устанавливается принудительно. У меня на УКНЦ в этот бит писать нельзя, поэтому данная методика не прокатывает. Может в НЕМИГЕ можно?
Про немигу ничего не скажу - не знаю. Могу лишь заметить, что не факт, что один и тот же адрес в основной программе и обработчике прерываний - это одно и то же, поскольку уже упоминались регистры MMU :)
---------- Post added at 19:54 ---------- Previous post was at 19:53 ----------
В RT-11 на PRO кстати интерфейс консоли эмулируется в памяти.
Может и тут также.
---------- Post added at 19:58 ---------- Previous post was at 19:54 ----------
Кстати, а с какой стати при работе опросом вообще разрешены прерывания?
Про немигу ничего не скажу - не знаю. Могу лишь заметить, что не факт, что один и тот же адрес в основной программе и обработчике прерываний - это одно и то же, поскольку уже упоминались регистры MMU :)
---------- Post added at 19:54 ---------- Previous post was at 19:53 ----------
В RT-11 на PRO кстати интерфейс консоли эмулируется в памяти.
Может и тут также.
---------- Post added at 19:58 ---------- Previous post was at 19:54 ----------
Кстати, а с какой стати при работе опросом вообще разрешены прерывания?
Нет, MMU у ней нет, просто этот адрес используется для обращения к дополнительной памяти)
Не знаю, разрешены и все)
Не знаю, разрешены и все)
Ну, как бы направление дальнейших действий понятно :)
Может в НЕМИГЕ можно?Регистры терминала там эмулируются в памяти, поэтому всё зависит от эмулятора.
В RT-11 на PRO кстати интерфейс консоли эмулируется в памяти. Может и тут также.У Немиги нет последовательных интерфейсов - всё эмулируется.
Капаюсь в старых исходниках и шпаргалках.
Нашёл вот такой кусок кода
командная строка из программы: !!!
.RADIX 8
MOV #ENDC-STARTC, R1
MOV #STARTC, R1
MOV #ENDC-STARTC, R2
MOV #512, R3
PUK: MOVB (R1)+, (R3)+
SOB R2, PUK
BIS #4000, @#44
CLR R0
EMT 350
STARTC: .ASCIZ "DIR/FU/VOL/BL DK:"
ENDC: .EVEN
Оформлен он был как часть процедуры на ПАСКАЛЕ.
Зачем то R0 чиститься?
В целом не понятно мне (что не удивительно), а главное не работает!
Просто выдаёт CSI молчком и всё. Один раз выдал "ДВОЙНОЕ ЗАВИСАНИЕ".
Я вот смотрю в R1 вроде бы заносится строка команды, так?
Но потом сразу затирается ? Бредятина?
В целом ТЗ такое - возможно ли команду монитора из программы выполнить? Конечно сама программа будет прервана (да и фиг бы с ней!)
Просто ищу замену вызову .CHAIN - хотя в моём случае можно обойтись
и ей - мне нужно запустить с диска SAV файл !
:confused_std:
Нашёл вот такой кусок кодаРабочий вариант выглядит так:
;
.MCall .Exit
START:
Mov #CMD, R3
Mov #512, R1
1$:
MovB (R3)+,(R1)+
BNE 1$
Sub #512, R1
Mov R1, @#510
BiS #4000, @#44
Clr R0
.Exit
CMD: .ASCIZ \$Dir/Fu/Bl/Vol\
.End START
;
Зачем то R0 чиститься?Так надо.
Так надо.
Обьяснить надо)
Обьяснить надо)
А чего объяснять - это в любом описании макрокоманд напиано :)
А чего объяснять - это в любом описании макрокоманд напиано :)
Вам это сделать быстрее, чем мне искать любое описание и перечитывать его)
искать любое описание и перечитывать егоПочему для передачи команды монитору нужно перед выходом очистить R0 - в описаниях не указывается. Просто говорится, что так надо.
Почему для передачи команды монитору нужно перед выходом очистить R0 - в описаниях не указывается. Просто говорится, что так надо.
Тут как бы логика. Очистка R0 - документированный способ выполнить .HRESET по выходу (то есть запретить CLOSE, REENTER, START), что и требуется для запуска внешних команд.
---------- Post added at 18:03 ---------- Previous post was at 18:01 ----------
А в программе выше недоделка - в 510 должна записываться длина команды.
А в программе выше недоделка - в 510 должна записываться длина команды.
Можно подробней?
Вариант Patrona справно выдаёт каталог диска )))
Если например команду пользователь будет вбивать, там длину легко поймать, только
вот как её в ассемблере класть-слать в 510, а самое главное в каком месте - тут я уже увы (((
Можно подробней?
The .EXIT request enables a user program to pass command lines to KMON in the chain information area (locations 500-777) for execution after the job exits. This is performed under the following conditions:
The word (not byte) location 510 must contain the total number of bytes of command lines to be passed to KMON.
The command lines are stored, beginning at location 512. The lines must be .ASCIZ strings with no embedded carriage return or line feed. For example:
.TITLE EEXIT1.MAC
XIT.NU =: 510 ;(.XITDF) char count
XIT.AS =: 512 ;(.XITDF) .Asciz command(s)
.=XIT.NU
.WORD B-A
.=XIT.AS
A: .ASCIZ /COPY A.MAC B.MAC/
.ASCIZ /DELETE A.MAC/
B:
The user program must set SPXIT$ or CHNIF$ in the Job Status Word before
doing an .EXIT, which must be issued with R0 = 0.
which must be issued with R0 = 0.
Действительно, пишут, что ТАК НАДО! )))
первоисточник (откуда у меня эта шпора и кто её писал история умалчивает)
командная строка из программы: !!!
.RADIX 8
MOV #ENDC-STARTC, R1 - вот та самая попытка положить длину???
MOV #STARTC, R1 - а вот эта строка тогда зачем ???
MOV #ENDC-STARTC, R2
MOV #512, R3 - остальное это надо уже систему знать
PUK: MOVB (R1)+, (R3)+
SOB R2, PUK
BIS #4000, @#44
CLR R0
EMT 350
STARTC: .ASCIZ "DIR/FU/VOL/BL DK:"
ENDC: .EVEN
вариант патрона - рабочий (!)
Рабочий вариант выглядит так:
Код:
;
.MCall .Exit
START:
Mov #CMD, R3
Mov #512, R1
1$:
MovB (R3)+,(R1)+
BNE 1$
Sub #512, R1
Mov R1, @#510
BiS #4000, @#44
Clr R0
.Exit
CMD: .ASCIZ \$Dir/Fu/Bl/Vol\
.End START
Легко заметить, что в рабочем варианте в ячейку 510 заносится длина строки.
Легко заметить, что в рабочем варианте в ячейку 510 заносится длина строки.
Именно.
Хотя если команда фиксированная, проще занести все это изначально в образ программы без всяких команд для этого :)
В нерабочем варианте нужно строку
MOV #ENDC-STARTC, R1
заменить на
MOV #ENDC-STARTC, @#510
---------- Post added at 16:00 ---------- Previous post was at 15:33 ----------
Продвинутый вариант - выполняет введённую с клавиатуры команду и снова запускает сам себя ( файл CMD2.MAC ):
;
.MCall .Exit, .TTYIN, .Print
START:
.Print #Prompt
Mov #512, R1
1$:
.TTYIN
CmpB R0, #15
BEq 2$
CmpB R0, #40
BLt 1$
CmpB R0, #177
BEq 1$
MovB R0, (R1)+
Br 1$
2$:
Cmp R1, #512
BNE 3$
.Print #Help
Br START
3$:
ClrB (R1)+
Mov #CMD, R3
MovB (R3)+,(R1)+
BNE .-2.
Sub #512, R1
Mov R1, @#510
.Print #CrLf
BiS #4000, @#44
Clr R0
.Exit
;================================================= ==========
Prompt: .ASCII <015><012><016>\Введите команду >\<017><200>
Help: .ASCII <015><012><016>\Исполнитель команд \<017>\v1.0\
CrLf: .Byte 0
CMD: .ASCIZ \$RU CMD2\
.End START
;
Продвинутый вариант
А зачем ввод команды так сложно делается? :)
Причем реально .TTYIN не будет отдавать символов пока не будет нажат <CR> в данном примере :)
А зачем ввод команды так сложно делается?А как ввести строку из нескольких слов, чтобы она скопировалась в буфер без перестановки слов ?
А как ввести строку из нескольких слов, чтобы она скопировалась в буфер без перестановки слов ?
.GTLIN ничего не переставляет.
Переставляет CCL если ты ввод пишешь прямо в командной строке "progname arg1 arg2" - в этом случае он пытается странслировать в CSI формат.
Вариант с .GTLIN ( файл CMD3.MAC )
;
.MCall .Exit, .GtLin, .Print
START:
.Print #CrLf
Mov #512, R1
Mov #CmdBuf, R3
.GtLin R3, #Prompt
TstB (R3)
BNE 1$
.Print #Help
Br START
1$:
MovB (R3)+,(R1)+
BNE .-2.
Mov #CMD, R3
MovB (R3)+,(R1)+
BNE .-2.
Sub #512, R1
Mov R1, @#510
.Print #CrLf
BiS #4000, @#44
Clr R0
.Exit
;================================================= ==========
Prompt: .ASCII <015><016>\Введите команду >\<017><200>
Help: .ASCII <015><012><016>\Исполнитель команд \<017>\v2.0\
CrLf: .Byte 0
CMD: .ASCIZ \$RU CMD3\
CmdBuf:
.End START
;
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot