Вход

Просмотр полной версии : Разбираюсь с ассемблером К1801ВМ1



darkstar
12.11.2013, 10:42
Народ, ковыряюсь в системе управления одного радиоприёмника, а именно вот:
http://www.radioscanner.ru/forum/topic46843.html

Считал ПЗУ-шку, дизассемблировал, но вот практики программирования, особенно в ассемблере не хватает.
Помогите осмыслить подпрограмму.
Правильно ли я дал комментарии и что же происходит в цикле?


016 304: MOV R1,-(SP) ; занести значение регистра R1 в стек; SP=SP-2
016 306: MOV R2,-(SP) ; занести значение регистра R2 в стек; SP=SP-2
016 310: MOV R3,-(SP) ; занести значение регистра R3 в стек; SP=SP-2

016 312: MOV 000 006(SP),R3 ; занести в R3 содержимое ячейки по адресу SP+6, т.е. адрес возврата из подпрограммы
016 316: MOV (R3)+,R1 ; R1 = R3, R3 = R3+2; занести в R1 адрес второй команды после возвращения из подпрограммы
016 320: MOV (R3)+,R2 ; R2 = R3, R3 = R3+2; занести в R2 адрес третьей команды после возвращения из подпрограммы
Цикл:
016 322: MOV (R3)+,R3 ; R3 = R3, R3 = R3+2; занести в R3 адрес четвёртой команды после возвращения из подпрограммы

016 324: ADD #000 006,000 006(SP) ; сдвинуть адрес возврата из подпрограммы на +6
016 332: MOV (R1)+,(R2)+ ; R2 = R1, R1 = R1+2, R2 = R2+2;
016 334: SOB R3,016 332 ; R3 = R3-1; если R3 не равно 0, то перейти к 016 332

016 336: MOV (SP)+,R3 ; восстановить значение регистра R3 из стека; SP=SP+2
016 340: MOV (SP)+,R2 ; восстановить значение регистра R2 из стека; SP=SP+2
016 342: MOV (SP)+,R1 ; восстановить значение регистра R1 из стека; SP=SP+2
016 344: RTS PC ; вернуться из подпрограммы

ПЗУ-шка во вложении

esl
12.11.2013, 11:55
по идее так
вызов этой подрограммы должен выглядеть как-то так


jsr pc,_COPY
dw _FROM
dw _TO
dw _SIZE (в словах?)
next_cmd:


кратнокое описание
сохранили регистры,
вытянули параметры,
переместили адрес возврата в правильное место
скопировали
восстановили регистры
выход

весь смысл в строчках


016 332: MOV (R1)+,(R2)+
016 334: SOB R3,016 332 ; R3 = R3-1; если R3 не равно 0, то перейти к 016 332
[code]

а коментарий не верный,
не " ; R2 = R1, R1 = R1+2, R2 = R2+2;"
это взять слово по адресу на который указывает R1, поместить его по адресу на который указывает R2
после чтения/записи увеличиваем значение регистров на 2 (по словам).

собственно т.к. C писался как "супер макро для DEC"
то в сишной нотации это
*(R2++)=*(R1++)


в вашем роме это так
[code]
RAM:001016 ; ---------------------------------------------------------------------------
RAM:001020 word_1020: .word 12 ; DATA XREF: sub_1030+4o
RAM:001022 .word 15
RAM:001024 .word 0
RAM:001026 .word 40
RAM:001030
RAM:001030 ; =============== S U B R O U T I N E =======================================
RAM:001030
RAM:001030
RAM:001030 sub_1030: ; CODE XREF: RAM:loc_444P
RAM:001030 ; RAM:000466P
RAM:001030 call @#_COPY ; DW _From,_TO,_Size
RAM:001030 ; ---------------------------------------------------------------------------
RAM:001034 .word word_1020
RAM:001036 .word word_114740
RAM:001040 .word 4
RAM:001042 ; ---------------------------------------------------------------------------
RAM:001042 mov #-63012, R3
RAM:001046 clr -(R3)



p.s. давненько с PDP11 асм не возился, все больше с Intel
но вроде порядок операндов не напутал

darkstar
12.11.2013, 12:35
Блин, точно!
Проглядел скобочки... а также проглядел адрес цикла... ё-маё, блин!
А у меня уж мозг переклинило - думал на адрес 016 322 возвращаемся...
Спасибо!

Ага, значит это константы....

Вызов такой:
001 030: JSR PC,@#016 304
001 034: 001 020
001 036: 114 740
001 040: 000 004
001 042: MOV #114 766,R3
001 046: CLR -(R3)

ну и так далее

esl
12.11.2013, 12:41
я там выше добавил пример как вызов выглядит у вас в ROM

и там это достаточно любимый способ, как показалось
имхо IDA тут рулит и бибикает,
с ее поиском, xref, b прочими плюшками

само просится TRAP XX - сделать с разумными именами а не цифрами :)

---------- Post added at 10:41 ---------- Previous post was at 10:38 ----------

не такой


RAM:001030 004737 016304 call @#_COPY ; DW _From,_TO,_Size
RAM:001034 001020 bne loc_1076
RAM:001036 114740 movb -(PC), -(R0)
RAM:001040 000004 iot
RAM:001042 012703 114766 mov #-63012, R3
RAM:001046 005043 clr -(R3)
RAM:001050 012704 000005 mov #5, R4
RAM:001054 012705 000060 mov #60, R5 ; '0'


а такой


RAM:001016 ; ---------------------------------------------------------------------------
RAM:001020 000012 word_1020: .word 12 ; DATA XREF: sub_1030+4o
RAM:001022 000015 .word 15
RAM:001024 000000 .word 0
RAM:001026 000040 .word 40
RAM:001030
RAM:001030 ; =============== S U B R O U T I N E =======================================
RAM:001030
RAM:001030
RAM:001030 sub_1030: ; CODE XREF: RAM:loc_444P
RAM:001030 ; RAM:000466P
RAM:001030 004737 016304 call @#_COPY ; DW _From,_TO,_Size
RAM:001030 ; ---------------------------------------------------------------------------
RAM:001034 001020 .word word_1020
RAM:001036 114740 .word word_114740
RAM:001040 000004 .word 4
RAM:001042 ; ---------------------------------------------------------------------------
RAM:001042 012703 114766 mov #-63012, R3
RAM:001046 005043 clr -(R3)

darkstar
12.11.2013, 12:49
Ага, кажется начинаю понимать.
Идёт вызов подпрограммы,
а за ним следом три слова с параметрами.

То есть тут подпрограмма перемещает кусок данных длинной 4 слова с адреса 1020 на адрес 114740.

И ещё вопрос - а как Вы в IDA просматриваете одновременно адрес, восьмеричный код команды и мнемонику команд?
У меня там в окне только мнемоника и стрелочки переходов...

esl
12.11.2013, 13:41
И ещё вопрос - а как Вы в IDA просматриваете одновременно адрес, восьмеричный код команды и мнемонику команд?
У меня там в окне только мнемоника и стрелочки переходов...

в меню

Options -> Disassembly -- Display disassembly line parts -- Number of opcode bytes (0 -> 3)

Ал-р
13.11.2013, 05:14
Вызов такой:
001 030: JSR PC,@#016 304
001 034: 001 020
001 036: 114 740
001 040: 000 004
001 042: MOV #114 766,R3
001 046: CLR -(R3)
ну и так далее
=
Процессор 16-разрядный и в PDP-шном Ассемблере адреса и числа пишутся без дырки-пробела в середине.

darkstar
13.11.2013, 06:20
Да это я для себя пишу, а то разряды в глазах сливаются...
Там скобку не заметил, тут в адресе ошибся - вот тебе и пожалуйста :)

Ал-р
13.11.2013, 07:28
...
имхо IDA тут рулит и бибикает,
с ее поиском, xref, b прочими плюшками
само просится TRAP XX - сделать с разумными именами а не цифрами :)
---------- Post added at 10:41 ---------- Previous post was at 10:38 ----------


...
а такой


RAM:001016 ; ---------------------------------------------------------------------------
RAM:001020 000012 word_1020: .word 12 ; DATA XREF: sub_1030+4o
RAM:001022 000015 .word 15
RAM:001024 000000 .word 0
RAM:001026 000040 .word 40
RAM:001030
RAM:001030 ; =============== S U B R O U T I N E =======================================
RAM:001030
RAM:001030
RAM:001030 sub_1030: ; CODE XREF: RAM:loc_444P
RAM:001030 ; RAM:000466P
RAM:001030 004737 016304 call @#_COPY ; DW _From,_TO,_Size
RAM:001030 ; ---------------------------------------------------------------------------
RAM:001034 001020 .word word_1020
RAM:001036 114740 .word word_114740
RAM:001040 000004 .word 4
RAM:001042 ; ---------------------------------------------------------------------------
RAM:001042 012703 114766 mov #-63012, R3
RAM:001046 005043 clr -(R3)


=
... Много лишних буковок для програмки из нескольких строк ... И прикалывает число #-63012 при том что слева оно в нормальном виде 114766

darkstar
14.11.2013, 10:12
Добрался до TRAP-диспетчера.
Написал несколько комментариев и запутался.
Не пойму, какое число получается после очистки битов и сдвига
И куда в конечном счёте происходит переход?

Аргументы у TRAP-а видел такие:
11, 12, 13
20, 22, 23, 25, 27
32, 33, 36,
44
50, 53, 55


TRAP-диспетчер:
---------------------
Сохраняем регистры:
004 504: MOV R3,-(SP) ; SP=SP-2; занести значение регистра R3 в стек
004 506: MOV R4,-(SP) ; SP=SP-2; занести значение регистра R4 в стек
004 510: MOV 000 004(SP),R3 ;записать в R3 содержимое ячейки по адресу SP+4, т.е. адрес возврата из прерывания
004 514: MOV R3,R4 ; R4 = R3 = адрес возврата из прерывания
004 516: MOV -(R3),R3 ; R3 = (R3-2) ; достали команду TRAP, вызвавшую прерывание, и положили в регистр R3
004 520: BIC #177 600,R3 ; обнулить все разряды команды TRAP, кроме младших 7 бит - достали аргумент TRAP-а
004 524: MOV R3,-(SP) ; полученный аргумент кладём в стек
004 526: CMP #000 010,R3 ; сравниваем 000 010 - R3
004 532: BMI 004 540 ; если R3 меньше 10, то перейти на 004 540
004 534: CLR R3 ; очистить R3
004 536: BR 004 544 ; перейти на 004 544
004 540: SUB #000 010,R3 ; вычесть 10 из R3
004 544: MOVB 004 600(R3),-(SP); положить в стек значение 004 600+(R3)
004 550: BIC #177 400,(SP) ; очистить старший байт ячейки стека
004 554: ASL R3 ; сдвинуть R3 влево
004 556: JSR PC,@004 646(R3) ; перейти к подпрограмме по адресу 004 646+(R3)
004 562: MOV (SP)+,R3
004 564: ADD R3,000 006(SP)
004 570: TST (SP)+
004 572: MOV (SP)+,R4
004 574: MOV (SP)+,R3
004 576: RTI
004 600: RTI
004 602: HALT

b2m
14.11.2013, 11:36
000010-R3 будет меньше, если R3 больше восьми, т.е. для номеров функции 8 и меньше будет вызвана функция номер ноль (хотя в стеке будет передан первоначальный номер). Иначе вычитаем 8, кладём в стек байт из таблицы по адресу 004600, очищая при этом старший байт в стеке, чтобы не мешался (судя по тому, что полученное число добавляется потом к адресу возврата, это количество аргументов после команды TRAP). Далее сдвигаем номер функции влево, т.е. умножаем на 2, чтобы получить смещение в таблице адресов функций. После чего вызываем функцию по адресу из таблицы 004646. После вызова достаём из стека количество аргументов и добавляем к адресу возврата. Выкидываем из стека реальный номер функции и восстанавливаем регистры. Всё, возврат из прерывания.

Ал-р
14.11.2013, 15:35
Добрался до TRAP-диспетчера.
Написал несколько комментариев и запутался.
Не пойму, какое число получается после очистки битов и сдвига
И куда в конечном счёте происходит переход?
Аргументы у TRAP-а видел такие:
11, 12, 13
20, 22, 23, 25, 27
32, 33, 36,
44
50, 53, 55

=
Для TRAP 11 получится число 2 (11-10)x2
для TRAP 12 получится число 4 (12-10)x2
и т.д.
С адреса 4650 расположена таблица переходов (адреса подпрограмм) для обработки соответсвуещего TRAP
... и значит сможете разбираться с каждой подпрограммой поотдельности.

esl
14.11.2013, 15:44
=
... Много лишних буковок для програмки из нескольких строк ... И прикалывает число #-63012 при том что слева оно в нормальном виде 114766

не много, при роме 16к все полезно
коды команд по умолчанию выключены, специально включили
#-63012 одним нажатием клавиши превращается в 114766

зато всё удобство IDA не сравнить с любимы редакторами ;)

darkstar
18.11.2013, 09:53
Спасибо, немного отлучался...
Для более полного понимания процессов решил воспользоваться логическим анализатором (который ещё нужно собрать).

darkstar
19.12.2013, 11:38
Так, разобрал работу диспетчера.
Алгоритм прилагаю.
При вызовах TRAP 0... TRAP 10 получим указание на адрес в таблице 004 646, т.е. переход на 037 366. при этом в стеке будет лежать число 200.
команда - адрес в таблице -> адрес перехода - SP
TRAP 11 - 004 650 -> 011 264 - 201
TRAP 12 - 004 652 -> 011 100 - 202
TRAP 13 - 004 654 -> 016 620 - 203

TRAP 20 - 004 666 -> 005 064 - 210
TRAP 22 - 004 672 -> 004 352 - 212
TRAP 23 - 004 674 -> 004 362 - 213
TRAP 25 - 004 700 -> 011 112 - 215
TRAP 27 - 004 704 -> 007 576 - 217

darkstar
20.12.2013, 06:50
Опять прошу помощи.
Что за команда такая BPT ?
В описании сказано "командное прерывание для отладки".
Что за прерывание?
По какому вектору оно сидит?

Похоже, это прерывание по вектору 14:
16 -> РСП
14 -> СК

Но дело в том, что в ПЗУ по этому адресу - нули...
Куда перейдёт программа? На начало?

hobot
20.12.2013, 08:55
Что за команда такая BPT ?
Это тупо по классике из описания

BPT ПЕРЕЙТИ К ЛОВУШКЕ ТОЧКИ ПРЕРЫВАНИЯ .
000003
BPT
КОДЫ УСЛОВИЙ ЗАГРУЖАЮТСЯ ИЗ ВТОРОГО СЛОВА ВЕКТОРА ЛОВУШКИ .
ВЫПОЛНЯЕТ ПЕРЕХОД К ЛОВУШКЕ ПО ЯЧЕЙКАМ ПАМЯТИ 000014-000016 .

Ал-р
20.12.2013, 09:07
... Считал ПЗУ-шку, дизассемблировал,
...
ПЗУ-шка во вложении
А дизасемблерный текст? (Для разбора полётов нужно видеть Старт и подпрограмму начальной инициализации с установкой векторов)

darkstar
22.12.2013, 17:29
hobot, к сожалению, у меня нет такого подробного описания.
Ал-р, весь код не дизассемблировал, т.к. большая его часть - это таблицы данных, и разобрать где данные, а где код нелегко.
Сам код начинается с адреса 000 400, там определяется позиция стека.

Таблица векторов вот такая:
000 004 - подпрограмма обработки ошибки связи с внешним устройством.
Если ЦП не получил сигнал /RPLY в ответ на /DIN, /DOUT в течении 64 тактов ("зависание"), то возникает это прерывание.
Или же если была выполнена команда "HALT".
(или если поступил сигнал IRQ1, но в нашем случае IRQ1 не используется).
000 010 - подпрограмма обработки ошибки неверной команды.
Если полученная команда не опознана, возникает это прерывание.
000 034 - подпрограмма TRAP-менеджера.
Возникает при программном выполнении команды TRAP.
000 100 - подпрограмма обработки внешнего прерывания IRQ2.
Сигнал "ГОТОВ" = 0 В вызывает это прерывание.
Но чтобы сигнал сформировался, нужно записать 000 001 по адресу 060 340.
000 270 - подпрограмма обработки внешнего прерывания IRQ3.
Возникает, когда ИРПС принял очередной байт.
000 340 - подпрограмма обработки прерывания от клавиатуры и валкодера.
Как только нажимаем клавишу или поворачиваем валкодер, блок Б10-38 формирует сигнал "VIRQ кл" или "VIRQ кпн". Эти сигналы получает блок Б10-82, и сам формирует запрос на прерывание для ЦП (сигнал "VIRQ").
Если прерывание разрешено, то ЦП отвечает сигналами "IAKO" и "DIN".
При поступлении этих сигналов, блок Б10-82 выставляет адрес прерывания 000 340.

Пока не ясно, откликается ли какое-либо устройство на шине при обращении к адресу 177 716...

Ал-р
22.12.2013, 19:20
А ПЗУ в каких адресах - с какого адреса начинается? Таблицу векторов, указатель стека и др. начальные установки выполняет подпрограмма сброса-пуска-инициализации при включении питания - нужно идти по цепочке которая после подсчёта контрольной суммы.
- - -
Посмотрел ссылку на первой странице http://www.radioscanner.ru/forum/topic46843.html
Основная ошибка там - адрес начала ПЗУ на самом деле не равен 0. (BR 400 это в относительной адресации, на самом деле это может быть к примеру переход на адрес 100400 (BR 100400) если ПЗУ со 100000). С нуля начинается ОЗУ с векторами, стеком и рабочими ячейками программы, ПЗУ где-то вдали, например со ... нужно смотреть по схеме адрес начального пуска и вот эту часть описания (= блоки памяти с селектором адреса).

darkstar
23.12.2013, 05:17
Ал-р, во вложении схема блока с описанием.
А также мои домыслы по поводу работы некоторых узлов этого блока :)
РПЗУ идёт как раз с 000 000. ОЗУ где-то вдали...

Судя по установленным на блоке перемычкам (установлены все, кроме А4), РПЗУ находится в адресах 000 000 ... 037 776.
ОЗУ - в адресах 110 000 ... 117 776.

Ал-р
23.12.2013, 10:14
Важный Рис.2 из документации с распределением адресного пространства очень информативен. Область векторов в ПЗУ и стек в середине адресного пространстранства на мой взгляд БК-шника выглядят странно. Интересная схема с использованием 588ВГ2 - просьба сделать скан листа со списком микросхем.

darkstar
23.12.2013, 10:36
Список микросхем идёт дальше в b10-37_txt.zip
на двух последних листах

Что такое "скрытое" ОЗУ и РПЗУ мне не вполне понятно.
Видимо при какой-то сервисной комбинации перемычек их адреса смещаются в эти области

Ал-р
23.12.2013, 14:53
Так "обрадовался" рис.2 что дальше и не пролистал :)
В тексте описания указано что скрытые области используются при отладке - на начальном этапе нет смысла с ними разбираться.
Предлагаю дальше идти по ПЗУ в последовательности которая происходит при включении: что там происходит после BR 400, какие подпрограммы выполняются и что они делают ...
(и постепенно формировать дизассемблерный текст с програмными блоками и блоками данных)

darkstar
24.12.2013, 05:23
Мозги уже сносит этот ассемблерный код :)
Там со старта идёт экспресс-проверка, какие блоки подключены и правильно ли они функционируют.
Поскольку точно не известны адреса регистров блоков, и что они должны отвечать, то приходится буквально распутывать код.
Результат распутывания с комментариями пишу на форуме http://www.radioscanner.ru/forum/topic46843-3.html
Параллельно составляю дизассемблированный текст в Excel :)
http://zx.pk.ru/attachment.php?attachmentid=44701&stc=1&d=1387852516

Хорошо.
Уточняющие вопросы ещё будут :)

---------- Post added at 04:23 ----------

Вот хотел ещё спросить - правильно ли я понимаю действие этих команд:
011 340: MOV -(R1),@(SP)+ ; R1=R1-2. Число из ячейки с адресом R1 скопировать ячейку по адресу, который указан в ячейке с адресом из стека. SP=SP+2
011 342: MOV @-(R3),013 300(R4) ; R3=R3-2. Число из ячейки, адрес которой указан в ячейке с адресом R3 скопировать в ячейку по адресу 013 300+R4
011 346: MOV @(R0)+,(SP) ; число из ячейки, адрес которой указан в ячейке с адресом R0 скопировать ячейку по адресу из стека. R0=R0+2
011 350: MOV (R3),@020 037(SP) ; число из ячейки по адресу R3 скопировать в ячейку по адресу 020 037+(SP)
011 354: MOVB -(R3),(R4)+ ; R3=R3-2. Число из ячейки по адресу R3 скопировать в ячейку по адресу R4, для приёмника (R4) все биты старшего байта устанавливаются равными старшему биту младшего байта. R4=R4+2

001 514: JSR PC,@001 524(R4) ; вызов подпрограммы по адресу 001 524, адрес возврата записывается в R4 (или адрес возврата взять из R4 ?)

И ещё:
001 264: JMP 000 764; переход на 000 764 ? Смущает отсутствие "@#". Или же это означает взять адрес перехода из ячейки 000 764 ?

darkstar
24.12.2013, 07:31
И вот ещё, что делает эта команда:
032 060: JSR R4,PC
Зачем переходить по адресу из PC?
Единственное объяснение - это сохранить в R4 адрес 032 060+2
Так?

И опять же, по адресации:
032 104: BIT #000 002,110446 ; проверить состояние битов ячейки по адресу 110446 с маской 000 002 ?
код вот такой:
032 104: 032 767
032 106: 000 002
032 110: 056 334

и снова:
032 126: MOV #000 203, 111 012 ; положить число 000 203 в ячейку 111 012 ?

Ал-р
24.12.2013, 11:08
001264: JMP 000764; переход на 000 764 ? Смущает отсутствие "@#". Или же это означает взять адрес перехода из ячейки 000 764 ?
JMP 000764 относительная адресация типа BR 000764 но так не получится, для BR это большое расстояние, поэтому поставили JMP
= взять адрес перехода из ячейки 000764 было бы JMP (000764)

---------- Post added at 10:08 ---------- Previous post was at 09:58 ----------


Таблица векторов вот такая:
000 004 - подпрограмма обработки ошибки связи с внешним устройством.
Если ЦП не получил сигнал /RPLY в ответ на /DIN, /DOUT в течении 64 тактов ("зависание"), то возникает это прерывание.
Или же если была выполнена команда "HALT".
(или если поступил сигнал IRQ1, но в нашем случае IRQ1 не используется).
000 010 - подпрограмма обработки ошибки неверной команды.
Если полученная команда не опознана, возникает это прерывание.
000 034 - подпрограмма TRAP-менеджера.
Возникает при программном выполнении команды TRAP.
000 100 - подпрограмма обработки внешнего прерывания IRQ2.
Сигнал "ГОТОВ" = 0 В вызывает это прерывание.
Но чтобы сигнал сформировался, нужно записать 000 001 по адресу 060 340.
000 270 - подпрограмма обработки внешнего прерывания IRQ3.
Возникает, когда ИРПС принял очередной байт.
000 340 - подпрограмма обработки прерывания от клавиатуры и валкодера.
Как только нажимаем клавишу или поворачиваем валкодер, блок Б10-38 формирует сигнал "VIRQ кл" или "VIRQ кпн". Эти сигналы получает блок Б10-82, и сам формирует запрос на прерывание для ЦП (сигнал "VIRQ").
Если прерывание разрешено, то ЦП отвечает сигналами "IAKO" и "DIN".
При поступлении этих сигналов, блок Б10-82 выставляет адрес прерывания 000 340.
-
Пока не ясно, откликается ли какое-либо устройство на шине при обращении к адресу 177 716...
Какие там адреса подпрограмм ?
=
В подпрограмме есть обращение к 177716, этот регистр (или его часть, возможно отдельные разряды) должен быть.
Регистр начального пуска (которого нет, т.е. читается 0) это не совсем 177716, можно считать что это два разных регистра.

darkstar
24.12.2013, 11:16
Ал-р, а почему бы не написать просто:
JMP @#000 764
или это эквивалентно JMP 000 764?

Смотрю описание. С Вашими пояснениями немного разобрался.
Отличие в способе записи кода.
@#000 764 - это абсолютная адресация. Тут всё понятно - жёстко указан адрес перехода = 000 764.
000 764 - это относительная адресация. 000 764 получили, прибавив число после команды (смещение) к текущему адресу команды.
Второе полезно, если кусок кода может быть использован в другой области адресов, т.к. ссылка относительная.



---------- Post added at 10:16 ---------- Previous post was at 10:10 ----------


адреса подпрограмм:

000 000: 000 577 (BR 000 400)
000 002: 000 000
000 004: 037 036
000 006: 000 200
000 010: 036 754
000 012: 000 200
*** нули ***
000 034: 004 504
000 036: 000 200
*** нули ***
000 100: 034 414
000 102: 000 200
*** нули ***
000 270: 002 266
000 272: 000 200
*** нули ***
000 340: 001 142
000 342: 000 200
*** нули ***
000 360: 177 777
000 362: 177 777
*** нули ***

Ал-р
24.12.2013, 12:40
Вот эти подпрограммы и нужно рассмотреть для начала ...

darkstar
24.12.2013, 16:45
Да.
Их и рассматриваю.
Но эти подпрограммы вызывают другие подпрограммы, а те в свою очередь вызывают функции, которые завязаны с другими функциями и подпрограммами...
И все они передают друг другу данные через системные регистры и стек. По ходу дела меняются какие-то данные в ОЗУ, что-то заносится в регистры блоков...
Пытаюсь распутать этот клубок с разных концов.

В общем, пока что остался вопрос, в чём смысл вот этой команды:
032 060: JSR R4,PC

Ал-р
24.12.2013, 20:18
Команда противоположная 001514: JSR PC,@001524(R4) :)
типа возврата из подпрограммы, но лучше спросите на БК-шном форуме http://bk0010.org/forum/

darkstar
09.01.2014, 05:03
Ещё одно уточнение:
Например команда TSTB R0, или другие команды с буковкой B.
Они ведь производят действие только над младшим байтом?

MM
09.01.2014, 05:43
Я как человек, порядка 29 лет работающий плотно с 1801ВМ1 скажу - по инструкции - так точно, а в реале - бабка надвое сказала - не менее 1% процессоров - невменяемые по этому параметру ( ИМХО - и побольше даже ).

Patron
12.01.2014, 13:50
Ещё одно уточнение:
Например команда TSTB R0, или другие команды с буковкой B.
Они ведь производят действие только над младшим байтом?Если аргумент регистр, то ДА ( кроме того MOVB в регистр - размножает старший бит младшего байта на старший байт ). Если аргумент - адрес памяти, то работает с тем байтом, который находится по указанному адресу ( например TSTB @#0 тестирует байт по адресу 000000, а TSTB @#1 - по адресу 000001 ).

darkstar
17.01.2014, 16:53
Спасибо за разъяснения! Очень помогло.
Ещё вопрос:
Команда RESET ведь не сбрасывает сам процессор? Только дёргает какие-то внешние линии на манер инициализации? Т.е. сбрасывает внешние устройства, и продолжает выполнение команды по слеующему адресу?
Если так, то какие линии дёргаются и в каком порядке?

MM
18.01.2014, 02:51
Команда 000005 - она подает сигнал INIT на МПИ, причем оччень долго.
Для более серьезных процессоров - сбрасывает все внутренние регистры, но там есть хитрые варианты - впрочем, к ВМ1 это не относится.

Patron
18.01.2014, 03:20
какие линии дёргаются и в каком порядке?Только линия INIT ( типа, у 1801ВМ1 по команде RESET сигнал INIT устанавливается на 200 тактов и потом ещё 500 тактов процессор ничего не делает ).

darkstar
19.01.2014, 01:18
Всё понял. Спасибо.
Хорошо, что внутренние регистры не сбрасываются :)

darkstar
20.01.2014, 07:25
Уже спрашивал на второй странице, но требуются пояснения.
Есть команда BPT. Она вызывает программное прерывание по вектору 14.
Но в таблице векторов (она находится в ПЗУ, так же, как и вся программа) такая картина:
000 000: 000 577, т.е. BR 000 400 - переход к выполнению основной программы
000 002: 000 000
000 004: 037 036
000 006: 000 200
000 010: 036 754
000 012: 000 200
000 014: 000 000
000 016: 000 000
Что в этом случае произойдёт?
В PSW запишется 000 000 и программа будет выполняться с адреса 000 000, пока не встретит команду RTT?
А вернётся ли из этого прерывания по команде RTI?
Или возникнет что-то типа HALT (т.е. IRQ1)?
Или случится прерывание по вектору 10?

И вообще, прерывание BPT - маскируемое? Т.е. к примеру, оно игнорируется, если PSW = 000 200?

Patron
21.01.2014, 01:08
Что в этом случае произойдёт?По команде BPT в стек будут записаны PSW и PC, в PSW будет помещено содержимое ячейки 016, а в PC будет помещено содержимое ячейки 014.

Никаких "обязательств" по последующему выполнению команд RTI / RTT команда BPT не накладывает - только совершает действия, описанные выше.

---------- Post added 21.01.2014 at 00:08 ---------- Previous post was 20.01.2014 at 23:59 ----------

Также и команду RTI можно использовать когда угодно, а не только для завершения обработки прерывания. Например, чтобы записать в PSW биты, которые невозможно изменить командой MTPS - можно сделать так:



MOV #NewPSW, -(SP)
MOV #Next, -(SP)
RTI
Next:

darkstar
21.01.2014, 04:33
Patron, хитро!
Спасибо!
Значит, программа перейдёт на 000 000 с адресом возврата и PSW в стеке :)

darkstar
28.01.2014, 10:54
Опять вопрос:
- в каком случае может возникнуть прерывание 000 360 ?

Patron
28.01.2014, 16:23
в каком случае может возникнуть прерывание 360 ?Это вектор приёмника порта 176560 ( резервный адрес последовательного порта на плате ДВК ).

Последовательный порт ДВК может быть настроен или на основной адрес 177560 ( вектор 60 ), или на резервный адрес 176560 ( вектор 360 ). Настройка на резервный адрес осуществляется для совместимости с КЦГД, который занимает основной адрес/вектор терминала ДВК.

darkstar
29.01.2014, 04:42
Бр-р-р! Ничего не понял :)
Думалось мне, что это происходит так:
1. по сигналу VIRQ происходит векторное прерывание.
2. если прерывание разрешено, то на шину выдаётся вектор. Например 360.
3. процессор идёт выполнять программу, адрес которой лежит в ячейке 360.
Как-то так.

Patron
30.01.2014, 13:28
Думалось мне, что это происходит так:
1. по сигналу VIRQ происходит векторное прерывание.
2. если прерывание разрешено, то на шину выдаётся вектор. Например 360.
3. процессор идёт выполнять программу, адрес которой лежит в ячейке 360.Значит, на вопрос: "В каком случае может возникнуть прерывание 360 ?" - правильным ответом будет: "Когда устройство, пославшее сигнал VIRQ, выставляет на шину вектор 360".

Мне известно только одно устройство, использующее вектор 360 - это приёмник последовательного порта 176560. Но в принципе - любое устройство, пославшее сигнал VIRQ, может выдать на шину любой вектор.

darkstar
31.01.2014, 07:10
Сорри за корявый вопрос.
Просто я подумал - а вдруг за этим номером жёстко что-нибудь закреплено в самой структуре процессора.
По типу как есть свои номера прерываний по случаю аварии питания или прихода сигнала IRQ и прочее...

Тогда другой вопрос:
Возможно ли занять область памяти, предназначенную для векторов прерываний, какими-нибудь сторонними процедурами?
Если точно известно, что прерываний с такими векторами не возникнет?
Просто в штатном чипе очень мало свободного места. И прерываний используется всего ничего... а в самом начале свободные ячейки пустуют...

Patron
31.01.2014, 12:17
Возможно ли занять область памяти, предназначенную для векторов прерываний, какими-нибудь сторонними процедурами?Да, можно вообще всю область векторов заполнить своим кодом, перепрыгивая через ячейки "работающих" векторов.

darkstar
10.02.2014, 04:33
Записал команды в таблицу векторов.
Работает :)

Patron
11.02.2014, 13:39
Процессор PDP-11 ничего не знает про "таблицу векторов", точно также как и про "память" или "регистры устройств" - для него это совершенно однотипные адреса на шине.

Если у какого-то устройства на шине достаточно много регистров с последовательными адресами - можно записать код небольшой программы прямо в эти регистры и передать туда управление.

darkstar
19.02.2014, 11:21
Такой вопрос. Есть команда:
CMPB R0,(R3)+
после выполнения этой команды куда укажет R3?

У меня есть два варианта:
А. Как во всех других командах R3 = R3 + 2, поскольку адреса команд бывают только чётные
или
Б. R3 = R3 + 1, поскольку команда байтовая.

Какой вариант верный?
Интуитивно склоняюсь к Б :)

Patron
19.02.2014, 20:49
куда укажет R3?При байтовых командах с автоинкрементом/автодекрементом содержимое регистров R0 .. R5 увеличивается/уменьшается на 1, а регистров R6 и R7 ( SP и PC ) - на 2.

darkstar
20.02.2014, 05:10
Вот спасибо!

darkstar
21.02.2014, 04:30
Ещё вопрос по скорости работы.

Судя по ТТХ, процессор К1801ВМ1 на частоте 5 МГц имеет производительность 500.000 простых регистровых операций в секунду.
Простая регистровая операция это вроде MOV R1,R2.
То есть, одна регистровая операция занимает 10 тактов.

Хотелось бы знать, сколько тактов занимают другие операции?
Есть где-нибудь такая информация?
Пока я знаю, что самой тормозной является команда RESET - 700 тактов.
Как насчёт например CMP? BR? CLR? RTS PC?

Patron
22.02.2014, 13:32
Хотелось бы знать, сколько тактов занимают другие операции? Есть где-нибудь такая информация?Про это есть специальная тема: Расчёт точного времени выполнения команд различными процессорами архитектуры PDP-11 (http://zx.pk.ru/showthread.php?p=345024).

darkstar
21.10.2014, 11:39
Опять уткнулся в трудное место.
Вопрос по выводам SEL1, SEL2.
В описании сказано, что это "выборка регистров ввода-вывода" и они как-то связаны с адресами 177 714, 177 716.
В каком случае задействуются эти сигналы?
Например, если в программе встречается обращение к адресу 177 716, то активируется вывод SEL1 ?
Или же наоборот - при поступлении внешнего сигнала на вывод SEL1 возникает переход на адрес 177 716 ?

Сами сигналы у меня не используются, но в программе есть обращение по адресу 177 716.

P.S.
SEL1, SEL2 - это выходы.
Кажется начинаю понимать :)

b2m
21.10.2014, 15:13
В описании сказано, что это "выборка регистров ввода-вывода" и они как-то связаны с адресами 177 714, 177 716.
В отличие от обычного обмена по магистрали, когда сначала передаётся адрес (и ожидается ответ, что адрес принят), а затем значение, обращение к SEL1, SEL2 не требует передачи адреса, т.е. это упрощённый доступ. Реализация этих регистров в железе - тривиальна.

Patron
21.10.2014, 16:50
в программе есть обращение по адресу 177 716В старшем байте по адресу 177 716 находится старший байт адреса перехода по включению питания, а содержимое младшего байта зависит от конкретной архитектуры. У ДВК там отображается состояние переключателей режима начального пуска, а биты 2 и 3 динамически управляют подключением системного ПЗУ в адресное пространство.

CodeMaster
21.10.2014, 19:20
обращение к SEL1, SEL2 не требует передачи адреса

Т.е. процессор выставляет SEL1 и читает данные с шины которые отдаёт некое устройство на которое этот SEL1 заведён?

Ал-р
21.10.2014, 21:17
Т.е. процессор выставляет SEL1 и читает данные с шины которые отдаёт некое устройство на которое этот SEL1 заведён?
Читает с устройства или записывает в него (если там есть куда) как в обычном цикле чтения или записи в память - SYNC и адрес на шину всё равно выставляются (но в данном случае дешифрация этого адреса 177716 не нужна потому что это сделано внутри процессора в виде сигнала SEL1)

b2m
21.10.2014, 21:36
адрес на шину всё равно выставляется.
Пардон, а сколько тактов ждётся подтверждение, прежде чем будут выданы данные?

Vslav
21.10.2014, 21:38
Читает с устройства или записывает в него (если там есть куда) как в обычном цикле чтения или записи в память - адрес на шину всё равно выставляется.
И не только адрес, при обращении по SEL1 и SEL2 еще и RPLY внутри процессора формируется, то есть ножка RPLY начинает еще работать как выход, недаром на схеме БК там резистор стоит. Ну и напоминаю что адреса SEL1 и SEL2 зависят еще и от номера процессора, а не являются фиксированными 177714 и 177716.

Ал-р
22.10.2014, 07:04
Пардон, а сколько тактов ждётся подтверждение, прежде чем будут выданы данные?
У ВМ1 нет входа для подтверждения приёма адреса, данные на внешнее устройство выдаются как в обычном цикле обмена за исключением того что RPLY от внешнего устройства не нужен, он формируется внутри процессора.

---------- Post added at 06:04 ---------- Previous post was at 05:57 ----------


И не только адрес, при обращении по SEL1 и SEL2 еще и RPLY внутри процессора формируется, то есть ножка RPLY начинает еще работать как выход, недаром на схеме БК там резистор стоит. Ну и напоминаю что адреса SEL1 и SEL2 зависят еще и от номера процессора, а не являются фиксированными 177714 и 177716.
Реальных схем где ВМ1 с другими адресами этих регистров нет.

darkstar
22.10.2014, 07:13
Так. Стоп.
Рассмотрим ещё раз процесс запуска процессора.
1. /DCLO = LOW, /ACLO = LOW.
2. Включаем питание +5 В. Проц устанавливает /INIT = LOW.
3. Допустим, через 8,5 мс внешняя схема переводит сигнал /DCLO = HIGH. Проц поднимает /INIT = HIGH.
4. Допустим, что внешняя схема через 85 мс переводит сигнал /ACLO = HIGH.
5. Похоже, что далее проц обращается по адресу 177 716. Видимо тут и сигнал SEL1 появляется...
6. Информация, считанная с адреса 177 716, загружается в счётчик команд процессора. Затем младший байт в счётчике обнуляется.
В регистр состояния процессора загружается константа 000 340.
7. Проц проверяет незамаскированные прерывания. Если их нет, то начинается выполнение программы с адреса, загруженного в счётчик команд.
Иначе сначала выполняется прерывание.

Так?

P.S.
По поводу номера процессора в системе. Видел такую информацию:
Он определяется состоянием выводов 26 (РА1) и 27 (РА0).
Соответственно, меняются адреса регистров SEL1, SEL2:
00 - 177716, 177714
01 - 177736, 177734
10 - 177756, 177754
11 - 177776, 177774.

Ал-р
22.10.2014, 09:33
...
Рассмотрим ещё раз процесс запуска процессора.
5. Похоже, что далее проц обращается по адресу 177 716. Видимо тут и сигнал SEL1 появляется...
6. Информация, считанная с адреса 177 716, загружается в счётчик команд процессора. Затем младший байт в счётчике обнуляется.
В регистр состояния процессора загружается константа 000 340.
..
P.S.
По поводу номера процессора в системе. Видел такую информацию:
Он определяется состоянием выводов 26 (РА1) и 27 (РА0).
Соответственно, меняются адреса регистров SEL1, SEL2:
00 - 177716, 177714
01 - 177736, 177734
10 - 177756, 177754
11 - 177776, 177774.
=
Пункты 5 и 6 нужно уточнить (Режим начального пуска):
Да, выдаются сигналы SEL1 и DIN, но на самом деле НЕТ обращения по адресу 177716 (такой адрес на шине не выставляется и сигнал SYNC неактивен). Эта комбинация SEL1, DIN, неактивный SYNC может проходить дешифрацию внешней схемой для выставления адреса начального пуска, при её отсутствии с шины читается 0.

darkstar
22.10.2014, 10:10
Вот теперь всё понятно!
Спасибо!

darkstar
23.10.2014, 10:29
Ещё прошу пояснить логику работы вот такого куска кода:

010 756: 022 711 CMP #000 001,(R1)
010 760: 000 001
010 762: 100 402 BMI 010 770

Я понимаю так, что переход на 010 770 произойдёт, если (R1) > 1.
Так ли это?

Titus
23.10.2014, 12:15
Ещё прошу пояснить логику работы вот такого куска кода:

010 756: 022 711 CMP #000 001,(R1)
010 760: 000 001
010 762: 100 402 BMI 010 770

Я понимаю так, что переход на 010 770 произойдёт, если (R1) > 1.
Так ли это?

Если ((1 - (R1)) < 0), то переход.

Иными словами, если содержимое (R1) в диапазоне от 0x0002 до 0x8001, то будет переход.

darkstar
23.10.2014, 12:50
Не понял, почему именно до 0х8001?
У нас что, все числа - со знаком?

Titus
23.10.2014, 13:12
Не понял, почему именно до 0х8001?
У нас что, все числа - со знаком?

Числа таковы, какие методы анализа к ним применяются. Тестирование флага знака - это лишь тестирование 15-го бита анализруемого регистра. Таким образом, все числа от 0x0000 до 0x7FFF - это положительные, а числа 0x8000 до 0xFFFF - отрицательные.

Ал-р
23.10.2014, 14:19
У нас никаких 8 нет и Fe тоже нет ... :)

Titus
23.10.2014, 14:56
У нас никаких 8 нет и Fe тоже нет ... :)

Да, ваша восьмиричная система жутко извращенская, поэтому я явно пишу префикс 0x перед шестнадцатиричными числами, которыми я легко оперирую, чтобы PDP-шники поняли, что это НЕ ВОСЬМЕРИЧНОЕ число)

hobot
23.10.2014, 19:30
Да, ваша восьмиричная система жутко извращенская,
Ты флиртуешь? )
http://www.lyceum95.ru/inform/ss_8.htm

NovaStorm
26.10.2014, 20:56
Он режет правду-матку, хексы рулят!

darkstar
30.10.2014, 05:21
Ещё один вопрос.
Не вполне понимаю вот такой кусочек кода:

022 414: 020 127 CMP R1,#011 000
022 416: 011 000
022 420: 103 504 BCS 022 632
Команда BCS осуществляет переход по адресу 022 632, если в результате сравнения случился перенос единицы из старшего разряда результата, т.е. бит С=1.
При сравнении выполняется операция R1 минус 011 000.
Теперь вопрос - в каком случае случится перенос (и произойдёт переход)?
И то же самое, но в случае с командой BCC.
Плохо у меня с математикой ...

Так, по этим командам происходит сравнение чисел как беззнаковых.
Например, R1 = 012 000.
Тогда для двухбайтовых чисел мы получим: 012 000 - 011 000 = 001 000. Заимствования из старшего разряда не было. C=0.
Если же, R1 = 010 000, то: 010 000 - 011 000 = 177 000. Произошло заимствование из старшего разряда. C=1.

Полагаю, что переход по BCS произойдёт если R1 < 011 000,
а для BCC - если R1 >= 011 000.

MM
30.10.2014, 07:25
Для ознакомления с кодом программы для 1801ВМ1 рекомендую поставить эмуль ДВК господина Patron - там есть пультовый режим, в котором можно набрать эти команды с клавы и проверить точно, при каких содержимых источника и приемника команды сравнения идет ветвление, и куда.

Titus
30.10.2014, 07:45
Полагаю, что переход по BCS произойдёт если R1 < 011 000,
а для BCC - если R1 >= 011 000.

Будет все наоборот, т.к. (на сколько я помню) при вычитании и сравнении флаг переноса используется инверсный, в отличие от того же Z80.


C – очищается, если был перенос из старшего разряда результата, в противном случае устанавливается. Перенос может произойти в том случае, если операнд источника был больше или равен нулю, а операнд приёмника – меньше нуля, или если операнды источника и приёмника были одного знака, а результат получился меньше нуля.

darkstar
30.10.2014, 09:05
MM, можно по-подробнее про пультовый режим?
DVK Emulator уже стоит.
Как можно напрямую ввести команды и просмотреть содержимое флагов?

MM
30.10.2014, 12:59
В эмуле ДВК надо выйти в пульт и набрать циферками машкод. Например, такой текст :
022727 123456 012345 -
сравнить число "123456" и число "012345"
Далее поставить необходимую команду ветвления, например ( вообще ) :
001004
012737 000100 177566 000000
012737 000101 177566 000000
Команда ( пример ) 001004 - ветвление на 4 слова вперед, если выполнится какое-то условие, в данном конкретном случае - неравенство в команде сравнения.
Запись числа "100" в регистр "177566" означает вывод символа "@", а числа "101" - знака "А".