Из газеты LPrint #21, Минск, 11.10.97 +----------------------------------------+ | ----------- Программирование --------- | +----------------------------------------+ (C) Space5 Hi, world! Я снова в Lprint'е! (а где бу- рные аплодисменты?) Ну ничего, и без них я смогу написать че- го-нибудь. Итак, сейчас я поделюсь с вами плодами своих извращательств над демкой... А вот название ее не скажу, а то ругаться будете. Вобщем, сами в процессе чтения поймете. 1) Как определить, сколько килобайт у ва- шей тачки: MEMORY ld bc,32765 ld hl,49152 ld de,4113 ;#1011 out (c),d ld (hl),l out (c),e ld (hl),c out (c),d ld a,(hl) or a jr z,128kb С этим легко разобраться, так что идем да- льше: 2) Определение наличия у компа муз. платы: Muzak ld bc,65533 ld a,0 out (c),a ld b,191 ld a,64 out (c),a ld b,255 in a,(c) cp 64 jr z,есть Тут тоже все просто. 3) Если муз. плата все же нашлась предыду- щей процедуркой, то теперь можно опреде- лить ее тип: Tip ld bc,65533 ld a,16 out (c),a in a,(c) cp 255 jr nz,AY-8910/12 jr YAMAHA 2149F 4) А сейчас самое интересное: Определения количества тактов у компью- тера за 1 прерывание. TAKTS org #8055 di ld hl,30720 ;создание про- ld a,121 ;цедуры обра- LABA05 ld (hl),a ;ботки inc l ;прерываний jr nz,LABA05 ; inc h ;Адрес самой ld (hl),a ;процедуры: dec a ;31097 ld i,a ; im 2 ld a,201 ;201=ret ld (31097),a ld hl,LABA07 ld (31098),hl ld de,0 ;счетчик=0 ld hl,LABA06 ld a,195 ;195=jp ei ; halt ;2 раза вхолос- ei ; тую halt ; ei ; ld (31097),a ; поехали! LABA06 inc de ;de=de+1 jp (hl) ;jp LABA06 ;inc de=6тактов ;jp (hl)=4так. LABA07 di ;сюда перейдет ;выполнение ;после подсчета ;тактов ;(со 2-м прер.) pop af ;снимаем со ;стека адрес во- ;зврата inc de inc de ;в de-количество ;тактов,поделен- ;ное на 10 Ну а дальше-дело техники. Для вывода ко- личества тактов можете воспользоваться ал- горитмом все той же демы (имеется в виду вывод в 10тичной системе) 1) Сразу печатаете нуль в последнем разря- де. 2) 4 раза делите de на 10 (остаток - это и будет следующий разряд) 3) Все Но вопрос: как делить? А вот как: Вход:de-число1 (2 байта) :bc-65536-число2 (2 байта) Выход:a-остаток от деления :de=число1/число2 DELENIE ld hl,0 ld a,e add a,a rl d adc hl,hl add hl,bc jr c,NABA57 sbc hl,bc NABA57 rla rl d NABA58 adc hl,hl add hl,bc jr c,NABA60 NABA59 sbc hl,bc NABA60 rla rl d NABA61 adc hl,hl add hl,bc jr c,NABA62 sbc hl,bc NABA62 rla rl d adc hl,hl add hl,bc jr c,NABA63 sbc hl,bc NABA63 rla rl d adc hl,hl add hl,bc jr c,NABA64 sbc hl,bc NABA64 rla rl d adc hl,hl add hl,bc jr c,NABA65 sbc hl,bc NABA65 rla rl d adc hl,hl add hl,bc jr c,NABA66 sbc hl,bc NABA66 rla rl d adc hl,hl add hl,bc jr c,NABA67 sbc hl,bc NABA67 rla rl d adc hl,hl add hl,bc jr c,NABA68 sbc hl,bc NABA68 rla rl d adc hl,hl add hl,bc jr c,NABA69 sbc hl,bc NABA69 rla rl d adc hl,hl add hl,bc jr c,NABA70 sbc hl,bc NABA70 rla rl d adc hl,hl add hl,bc jr c,NABA71 sbc hl,bc NABA71 rla rl d adc hl,hl add hl,bc jr c,NABA72 sbc hl,bc NABA72 rla rl d adc hl,hl add hl,bc jr c,NABA73 sbc hl,bc NABA73 rla rl d adc hl,hl add hl,bc jr c,NABA74 sbc hl,bc NABA74 rla rl d adc hl,hl add hl,bc jr c,NABA75 sbc hl,bc NABA75 rla rl d ld e,a ret Разобрались? Если нет, то думайте. Если же не думается, то разберитесь сначала с про- цедурой умножения из MOVE#10, а потом и с этим все станет ясно. И напоследок скажу, что все это наглым об- разом (а точнее-STS'ом) выдрано из ACTION MEGADEMO, надеюсь, что VAV меня простит,т. к. без его демы я до всего вышенаписанного и не додумался бы. Alex> Прочитал я все вышенаписанное и ре- шил кое что добавить от себя. Сперва я хочу дать небольшой совет SPA- CE5 - переходи в HEX-систему. Я раньше сам писал в DEC, но потом, поняв преимущества HEX, постепенно перешел в нее (между 32765 и #7FFD разницы может и нет, но вот между 4113 и #1011 есть. Или сравни 16384,16640, 16896, 17152, 17408, 17664, 17290, 18176 и #4000, #4100, #4200, #4300, #4400, #4500, #4600, #4700 - что легче запоминается ?). Ну и еще пару слов по поводу теперь уже моих программок. Не все они принадлежат мне, некоторые я так же "дерганул" из де- мок (например ECSTASY). Так же в моих про- граммках вы сможете увидеть комманды типа LD HL,KB_128 и CALL PRINT - это просто об- ращение на подпрограмму печати тескта, но сама эта подпрограмма, а так же и тексты, приведены сдесь не будут (сами напишите - не маленькие :). И последнее. В моих про- гах Вы почти не найдете комментариев - не такие они и сложные. 5,4,3,2,1,0,-1,-2,-3 Старт... Сначала еще одна программа проверка на наличие 128Кб (если Вы желаете проверить наличие большей памяти, и использовать ее в своей проге, то лучше воспользуйтесь процедуркой из приложения к ZX-FORMAT #05 /она же в SPECTROFON #22/). LD HL,#C000 LD BC,#7FFD LD A,#10 OUT (C),A LD (HL),A INC A OUT (C),A LD (HL),A DEC A OUT (C),A CP (HL) LD HL,KB_128 JR Z,$+4 LD HL,KB_48 CALL PRINT А вот еще одна моя оригинальная провер- ка: ORG <#8000 ; адрес должен быть LD BC,#7FFD ; меньше #8000 LD A,#15 OUT (C),A LD (LABEL+#8000),A LABEL RST 0 ; при 48Кб - сброс LD A,#10 ; при 128Кб продол- OUT (C),A ; жаем работу Догадались как она работает ? Так как SPACE5 привел процедуру провер- ки наличия AY в DEC-виде, то я решил при- вести ее еще раз, но уже в HEX-виде (она немного отличается от вышеприведенной, но не существенно, так как я ее сам подсмот- рел в ACTION /Сначала у меня стоял музы- кальный сопроцессор AY-3-8910 и я как то не обращал внимания на то, что ACTION сообщала мне, что у меня стоит 10-ый соп- роцессор. Но однажды я заменил его нa YM2148F и запустив ACTION я с удивлением увидел сообщения, что у меня теперь стоит YMAHA. До этого момента я и не подозревал, что возможно програмно определить тип сто- ящего на компе музыкального сопроцессора. Тогда я тоже влез в ACTION и подсмотрел как это определяется/. LD BC,#FFFD XOR A OUT (C),A LD B,#BF LD A,#40 OUT (C),A LD B,#FF IN A,(C) CP #40 LD HL,ABSENT JR NZ,CONT LD A,#10 OUT (C),A IN A,(C) CP #FF LD HL,AY_3 JR NZ,CONT LD HL,YM2149F CONT CALL PRINT Программа определения наличия теневого ОЗУ (SHADOW RAM). Определяет два типа под- ключения. DI IN A,(#FB) ; включить теневое ОЗУ CALL CHECK IN A,(#7B) ; выключить ОЗУ JR NC,CNT ; если есть - то выход LD BC,#FF3E LD A,#C7 OUT (C),A ; включить теневое ОЗУ PUSH BC CALL CHECK POP BC LD A,#C0 OUT (C),A ; выключить ОЗУ LD HL,ABSENT JR C,EXT CNT CALL CONV ; перевод числа из A в ; символьный вид в HL EXT CALL PRINT ... CHECK LD BC,#7FFD LD DE,#1000 LD HL,0 LD A,(HL) DEC (HL) CP (HL) SCF RET Z ; Возврат если нет ОЗУ OUT (C),E LD A,32 ; 32Кб LD (#3FFF),A OUT (C),D LD A,16 ; 16Кб LD (#3FFF),A RRCA ; 8Кб LD (#1FFF),A RRCA ; 4Кб LD (#0FFF),A RRCA ; 2Кб LD (#07FF),A OUT (C),E LD A,(#3FFF) ; В рег A результат OUT (C),D AND A ; сброс CARRY RET Проверка наличие порта #FF LD HL,#5800 ; заносим в атрибуты LD DE,#5801 ; число #FF LD BC,#02FF LD (HL),#40 LDIR EI LD BC,#0800 ; В BC счетчик HALT LD HL,FF_YES LOOP_0 IN A,(#FF) CP #40 JR Z,LAB_X DEC BC LD A,B OR C JR NZ,LOOP_0 LD HL,ABSENT LAB_X CALL PRINT Данная программа НЕ ОПРЕДЕЛЯТ неверно сделанный порт #FF! Так же повотрю программу для определе- ния количества тактов между прерываниями компьютера. ORG >#7FFF DI LD HL,#FE00 ; Организация режима LD A,H ; IM 2 LD I,A DEC A LD (HL),A INC L JR NZ,$-2 INC H LD (HL),A LD A,#C9 ; Временно блокируем LD (#FDFD),A ; программу возврата LD HL,RETURN ; Заносим адрес возв- LD (#FDFE),HL; рата из подсчета IM 2 LD DE,0 ; Обнуляем счетчик LD HL,CYC LD A,#C3 EI HALT ; холостой прогон EI HALT ; холостой прогон EI LD (#FDFD),A ; Разблок. возврат CYC INC DE ; считаем такты JP (HL) RETURN DI POP AF ; приводим стек в исходное INC DE ; состояние INC DE В регистре DE кол-во тактов деленное на десять (например 7166 это 71660 тактов). Определения наличия медленой памяти (SLOW RAM) т.е. тип машины - однополевая или двухполевая. LD A,3 ; счетчик холостых прерыв. LD HL,INT_1 ; адрес возврата LD (#FDFE),HL LD BC,0 ; обнуляем счетчик EI HALT HALT LOOP_1 LD HL,(#4000) ; работа с SLOW RAM LD (#4000),HL INC BC JR LOOP INT_1 DEC A EI RET NZ ; возврат из холостого INT DI POP HL ; востанавливаем стек PUSH BC ; сохраняем результат LD HL,INT_2 ; адрес возврата LD (#FDFE),HL LD A,3 ; счетчик холостых прерыв. LD BC,0 ; обнуляем счетчик EI HALT HALT LOOP_2 LD HL,(#FE00) ; работа с FAST RAM LD (#FE00),HL INC BC JR LOOP_2 INT_2 DEC A EI RET NZ ; возврат из холостого INT DI POP HL ; востанавливаем стек POP HL ; восстанав. старый резул. XOR A SBC HL,BC ; сверяем оба результата LD HL,ABSENT ; SLOW RAM ABSENT JR Z,$+5 LD HL,PRESENT ; SLOW RAM PRESENT CALL PRINT Ну и последняя прога. Определение CDOS- модема и порта к которому он подключен. Сразу хочу предупредить, что эту прогу я написал для ARS'овского модема и будет ли она определять московские модемы я не знаю Дело в том, что минские модемы подключают- ся с неполной адресацией, к порту номер которого содержит один или два бита сбро- шеных в ноль, а остальные биты равны еде- нице. Поиск начинается с порта #FC и далее вниз. Трубка на модеме должна быть положе- на. LD B,#FC LL_1 LD C,B ;Заносим в C адрес порта IN A,(C) ;читаем значение порта и CP #DF ;сверяем его с #DF JR Z,CL_1 ;если равно, то доп.прв. RL DJNZ LL_1 ;иначе продолжить поиск LD HL,ABSENT ; модем не найден! JR EL CL_1 LD E,0 ;обнуляем счетчик LD B,8 ;кол-во проверяемых битов LD A,C ;в рег. A - адрес порта LL_3 RRA ;проверка бита на ноль JR C,LL_2 INC E ; если бит равен 0, то E=E+1 LL_2 DJNZ LL_3 ; Все биты проверены ? LD B,C ; восстановить регистр B DEC E ; в номере порта один бит ; равен нулю ? JR Z,$+5 ; если да, то модем есть DEC E ; в номере порта два бита ; равны нулю ? JR NZ,RL ; если нет, то продолжить ; поиск LD A,#10 ; стандартная процедура OUT (C),A ; проверки наличия IN A,(C) ; модема из CDOS AND #20 JR Z,EL XOR A OUT (C),A IN A,(C) AND #20 JR NZ,EL LD HL,PRESENT EL CALL PRINT ; модем есть. в рег. C ; номер порта. Вот и все на сегодня. P.S. Если в вышеприведенной программе встретились некоторые недоработки или ошибки, то извините - данный текст набира- лся по памяти.