Просмотр полной версии : Неиспользуемые и редкоиспользуемые команды
В эмуляторе zxzxemul составил статистику выполнения команд при сбросе и PRINT SQR 2.
Неиспользуемые и редкоиспользуемые команды из основного набора:
02 ld (bc),a
0a ld a,(bc)
(15=1) dec d
1d dec e
2c inc l /нужно/
2d dec l
31 ld sp,nn
33 inc sp
39 add hl,sp /нужно/
3b dec sp
40 ld b,b
43 ld b,e
45 ld b,l
(48=2) ld c,b
49 ld c,c
4a ld c,d
(4b=3) ld c,e
50 ld d,b
(51=2) ld d,c
52 ld d,d
55 ld d,l
(58=5) ld e,b
(5a=1) ld e,d
5b ld e,e
5c ld e,h
(60=1) ld h,b
63 ld h,e
64 ld h,h
65 ld h,l
66 ld h,(hl) /нужно для переходов по таблице/
(69=1) ld l,c
6a ld l,d
6c ld l,h
6d ld l,l
6e ld l,(hl)
74 ld (hl),h
75 ld (hl),l
76 halt
7f ld a,a
(80=1) add a,b
82 add a,d
84 add a,h
85 add a,l
(86=1) add a,(hl)
88 adc a,b
8a adc a,d
8b adc a,e
8c adc a,l
93 sub e
94 sub h
(95=1) sub l
96 sub (hl)
97 sub a
98 sbc a,b
99 sbc a,c
9a sbc a,d
9b sbc a,e
9c sbc a,h
9d sbc a,l
9e sbc a,(hl) /sbc a,a нужно для расширения знаковых/
a1 and c
a3 and e
a4 and h
a5 and l
(a6=1) and (hl)
a8 xor b
aa xor d /xor e=#023c/
ac xor h /xor l=#0033/
b0 or b
b4 or h
b5 or l
b7 or a /and a=#179d/
ba cp d
bb cp e
bc cp h
bd cp l
c7 rst #00
cf rst #08
d4 call nc,nn
dc call c,nn
de sbc a,n
e0 ret po
e2 jp po,nn
e4 call po,nn
e8 ret pe
ea jp pe,nn
ec call pe,nn
f0 ret p
f4 call p,nn
f7 rst #30
(f9=1) ld sp,hl /нужно/
fc call m,nn
ff rst #38
Совсем не используется 80 из 252 команд основного набора, редко используется 13. Интересно, что из 63 направлений ld reg,reg активно используется только 35. Редко происходят копирования между младшими и старшими частями регистровых пар и копирования из b,c в h,l,d,e (обычно бывает только ld b,h:ld c,l).
По уму из списка ненужных надо убрать inc l, add hl,sp, ld sp,hl и ld h,(hl) и добавить daa (выполнилось 28 раз), cp a (выполнилось 4 раза) и nop (выполнилось 78 раз).
40 ld b,b
Для чего эта команда, и тому подобные ? :)
Для чего эта команда, и тому подобные ?
Аналог nop :)
У меня другой вопрос- какова цель исследования и какие практические выводы можно сделать из результатов?
Одни сначала убирают ненужные команды, а потом фанаты PDP11 ворчат об ортогональности :)
На лишние команды повесить "новые" нужные, наверное
1. Если последовательно выдерживать какую-то определённую стратегию программирования, то будет использоваться ещё меньше команд, и программы будут лучше паковаться.
2. Можно задуматься о наборе команд для регистровой виртуальной машины с учётом того, что не все регистры равнозначны.
3. Таки да, кое-что можно перехватывать железом, если это не касается состояния регистров процессора. Например, ld b,b и т.п. могут быть префиксами сегментной адресации (как на Спринтере).
4. Наверняка кто-то имеет что-то сказать насчёт того, что он сам не использует. Например, я знаю, что многие не используют условные CALL, а некоторые вообще пишут без JR.
скоро под zx-evo перестанет еще много чего работать или режим будет выключаемым?
Если последовательно выдерживать какую-то определённую стратегию программирования,
вот именно, используемые и не используемые команды впервую очередь идут от личного стиля програмиста, от написания компилятора (если говорить о С, etc.), от конкретно решаемой задачи и "тонкостей": размер кода, размер временных данных, размер стека, скорость, "сжимаемость".
1. Если последовательно выдерживать какую-то определённую стратегию программирования, то будет использоваться ещё меньше команд, и программы будут лучше паковаться.
2. Можно задуматься о наборе команд для регистровой виртуальной машины с учётом того, что не все регистры равнозначны.
3. Таки да, кое-что можно перехватывать железом, если это не касается состояния регистров процессора. Например, ld b,b и т.п. могут быть префиксами сегментной адресации (как на Спринтере).
1. Паковать код занятие почти "бесполезное" на данном этапе развития, потому что он занимает и так мало по сравнению с данными, потому что паковщик распаковщик требуют скорость и память и потому что внешние накопители очень жирные.
2. Виртуальная машина должна работать как типический интерпритатор (где есть 1 указатель на область с состоянием), т.е. исключительно с памятью а не с регистрами потому что неизвестно сколько регистров нужно будет для той или иной задачи и потому что при переключении на другую работу ненужно будет сохранять контекст.
3. Данный подход как я понимаю заменяет ld a, page_num; out (page_port), a ? По-моему это не серьезная помощь, такая доработка в теории может дать немного более скоростной доступ к данным в других страницах но ничего ощутимого. Вот что реально могло бы помочь тут так это MMU такого плана как в PDP-11 с 22bit физической шиной, НО еще круче чтобы после того как в память загруженны все куски данных и кода оно САМО (без участия OS-a) понимало какие куски физической памяти нужно включить под какие адреса при передаче управления тому или иному куску кода.
Andrew771
11.04.2012, 10:15
используемые и не используемые команды впервую очередь идут от личного стиля програмиста, от написания компилятора (если говорить о С, etc.), от конкретно решаемой задачи и "тонкостей": размер кода, размер временных данных, размер стека, скорость, "сжимаемость".
тоже согласен.
Я не использую команды:
ld x,x (x - один и тот же регистр)
ld a,r
ld r,a
jr всех видов
jp p,addr
jp m,addr
jp po,addr
jp pe,addr
call p,addr
call m,addr
call po,addr
call pe,addr
ret p
ret m
ret po
ret pe
rrd
rld
lddr
cpdr
ldd
cpd
ini
inir
ind
indr
outi
otir
outd
outr
все команды с регистром IY
Но не факт, что они не понадобятся. :)
А вот такие команды хотелось бы, чтобы были:
ld bc,(hl)
ld de,(hl)
ld hl,(hl)
ld ix,(hl)
ld (hl),bc
ld (hl),de
ld (hl),hl
ld (hl),ix
ld hl,pc (pc = счетчик команд)
rrd с временем выполнения 4-8 тактов
rld с временем выполнения 4-8 тактов
add hl,nn
adc hl,nn
sub hl,bc
sub hl,de
sub hl,nn
sbc hl,nn
jp (hl) (переход на адрес, заданный в памяти по адресу в hl, а не как сейчас)
jp (ix) (переход на адрес, заданный в памяти по адресу в ix, а не как сейчас)
djnz bc
sla hl
sla bc
sla de
sla ix
srl hl
srl bc
srl de
srl ix
скоро под zx-evo перестанет еще много чего работать или режим будет выключаемым?
В ZX-Evo работает всё и будет работать всё. Естественно, имеется в виду baseconf, а не прошивка TS-Labs - там может появиться или исчезнуть что угодно.
Andrew771
11.04.2012, 10:29
Еще неудобно, что команда djnz работает с регистром B (старшим в регистровой паре BC), а не с регистром C (младшим). Т.к. чаще всего в результате расчетов счетчик для цикла получается в младшем регистре. Либо при выполнении цикла должен быть в младшем регистре, чтобы сделать старший равным нулю и использовать в дальнейшем команды типа add hl,bc.
Данный подход как я понимаю заменяет ld a, page_num; out (page_port), a ? По-моему это не серьезная помощь, такая доработка в теории может дать немного более скоростной доступ к данным в других страницах но ничего ощутимого.
Нет. Данный подход реализует полноценные сегменты по 64К. Можно держать в одном сегменте код, в другом одни данные, в третьем другие данные, в четвёртом стек.
Интересная мысль - это расширить разрядность регистров до 32-х бит. И добавить префикс, разрешающий командам с ними работать. То есть будут пары команд:
JMP4 - загрузить в PC 32 бита.
MOV R, R - переместить 8 бит данных, остальные 24 бита обнулить.
MOV4 R, R - переместить 32 бит данных.
PUSH4 B- сохранить в стек 32 бита.
ADD4 A - сложение 32 бита.
И в этом случае отказаться от регистровых пар:
MOV [HL], A
MOV4 [H], A
Таким образом легко сможет выполняться два кода - старый и новый. Причем новый может безопасно лежать в верхней памяти (>64k).
А вот такие команды хотелось бы, чтобы были:
А как насчёт этих?
ld8 (NN),N
ld16 (NN),NN
ld8 (NN),(NN)
ld16 (NN),(NN)
ld8 r,(NN)
ld16 rp,(ii+N)
ld16 (ii+N),rp
add/sub r,N
ldsigned rp,r
ld16 rp,rp
neg16 rp
sub16 rp,rp
ld8 a,(NN+a)
call (NN+a*2) //switch
ld16 hl,NN+a*k
ld16 rp,(hl):hl+=2
ld16 (hl),rp:hl+=2
inc (NN)
dec (NN)
rp*=2
rp/=2
push bc,de,hl
pop hl,de,bc
Если на рестартах, то можно сделать:
farcall (с обычным ret)
switch (как #3d13)
[fastswitch (0..255)] //switch с диапазонами делается через call range_to_code:fastswitch
startcritical
endcritical
[cin > a]
[cout < a (как RST 16)]
Что ещё? Рестартов всего 8 штук.
Andrew771
11.04.2012, 10:40
А как насчёт этих?
мне кажется, это уже слишком большой уход от Спектрума. :)
---------- Post added at 10:40 ---------- Previous post was at 10:38 ----------
rp*=2
rp/=2
здесь лучше сделать сдвиг rp.
inc (NN)
dec (NN)
лучше тада inc16 (hl) и dec16 (hl)
ld16 rp,(ii+N) - вместо ld l,(ix+N):ld h,(ix+(N+1)) (6 байт)
ld16 (ii+N),rp - вместо ld (ix+N),l:ld (ix+(N+1)),h (6 байт)
ldsigned rp,r - вместо ld l,a:rla:sbc a,a:ld h,a (4 байта)
neg16 rp - вместо xor a:sub l:ld l,a:sbc a,h:sub l:ld h,a (6 байт)
если так хочется свой комп
зачем делать его спектрум совместимым и какой в этом смысл ?
Кто тут говорит про свой комп?
А как насчёт этих?
Это всё реализовано давным давно в z-380. Читайте доки.
alone, а про что тут речь?
Я не использую команды:
Это не то, чем можно было бы гордиться, не так ли? Может получше почитать описания команд и всё же некоторые, не все, применять? Может код сократится?
jr - нужна для релоцируемых программ, уменьшает пересчитываемое кол-во кода
все команды с регистром IY
Да, бесполезный регистр! Вот IX - гораздо лучше!
Команды с флагами po/pe, p/m - может стоит описания почитать?
Andrew771
11.04.2012, 17:39
Это не то, чем можно было бы гордиться, не так ли? Может получше почитать описания команд и всё же некоторые, не все, применять? Может код сократится?
Ну пока не пригодились. Собстно я это и написал, что возможно в будущем пригодятся.
jr - нужна для релоцируемых программ, уменьшает пересчитываемое кол-во кода
Релоцируемых прог я не писал. Переходы очень короткие у jr, а такты не экономятся. Их количество в программе не так велико, так что экономия памяти мизерная.
Да, бесполезный регистр! Вот IX - гораздо лучше!
IY не бесполезный регистр, если не использовать подпрограммы ПЗУ. Но мне это не пригодилось. IX хватает.
Команды с флагами po/pe, p/m - может стоит описания почитать?
Стараюсь не писать проги с отрицательными числами, а вот четность пока тоже некуда было прикрутить.
Error404
11.04.2012, 18:14
Реально не хватает 16 и 32 битной целочисленной арифметики (сложение/вычитание/умножение/деление/сдвиг). Без остального как-то обхожусь.
Переходы очень короткие у jr, а такты не экономятся
Экономится место. Зачем ставить JP, если нет разницы 10 тактов или 12 будет в итоге? Если не критично - то ставим jr.
---------- Post added at 20:24 ---------- Previous post was at 20:24 ----------
а вот четность пока тоже некуда было прикрутить.
Например узнать текущее состояние прерываний, запрещены они или нет.
---------- Post added at 20:25 ---------- Previous post was at 20:24 ----------
IY не бесполезный регистр, если не использовать подпрограммы ПЗУ. Но мне это не пригодилось. IX хватает.
полезность появляется, когда нам нужна индексная адресация. И данных много.
NEO SPECTRUMAN
11.04.2012, 18:52
В эмуляторе zxzxemul составил статистику выполнения команд
Проект zxzxemul не был заброшен и продолжает свое развитие?
Больше половины приведенных "неиспользуемых" комманд используются в защитах всевозможных. Или все должно быть белым и пушистым, или работать не будет.
Проект zxzxemul не был заброшен и продолжает свое развитие?
Только теоретическое. У меня есть пара идей, как его ускорить. А вообще он глобально встрял на эмуляции дисковода. Ну, и на отсутствии практического применения :)
NEO SPECTRUMAN
12.04.2012, 23:22
У меня есть пара идей, как его ускорить.
Переписать под NGS.
Ну, и на отсутствии практического применения
надо делать эмуль арм. потом запустить на нем линукс (или что поинтереснее, андроид например) и сильно пропиариться, мол, не на какой-то там вражеской ардуине заэмулили враги, а на нашем народном компе (лол), наши народные умельцы!
все команды с регистром IY
Да, бесполезный регистр! Вот IX - гораздо лучше!
Скажи это alone coder`у и его текстуратору, да и многим другим кто писал демки)
бесполезными командами являются ld a,a и подобные...
и кстати jp p, jp pe и т.п. тоже являются сверхофигенными для конкретной задачи, например в зависимости от битов регистра А делать или нет call:
классически
pop af // или ld a,(HL): inc HL
rra
jp z,L1
ret1 rra
jp z,L2
ret2 rra
...
L1 do something
jp ret1
L2 do something
jp ret2
а вот еще один метод (Griv мне показал идею)
храним не в рег А а в рег F битовые данные, тогда
pop af
jp z,L1
ret1 jp p,L2
ret2 jp p,L3
так что все дело в том под какие задачи какие регистры и команды нужны а под какие нет, в контексте конкретной задачи можно найти применение абсолютно любым командам и регистрам... будь то ret c; ld a,r для задержек или регистр IY для цикла текстуринга...
Andrew771
13.04.2012, 10:30
Вопрос немного не по теме: правда ли, что сброс CY флага можно делать одной командой AND A вместо SCF; CCF ?
Вопрос немного не по теме: правда ли, что сброс CY флага можно делать одной командой AND A вместо SCF; CCF ?
Или OR A. Как побочный эффект- флаг Z устанавливается при нулевом значении аккумулятора.
Извращенный мозг демокодера использует практически все команды, лишь бы поиметь максимум
Особенно если по тактам меньше жрет
Кстати команды типа ld b,b были бы намного полезнее если ld b',b и т.п.
Andrew771
13.04.2012, 23:25
Кстати команды типа ld b,b были бы намного полезнее если ld b',b и т.п.
да, было бы супер
но тогда бы вы захотели бы еще:
a,b'
b,c'
c,d'
и т.д.
Или OR A. Как побочный эффект- флаг Z устанавливается при нулевом значении аккумулятора.
Всегда когда кодил, использовал замену
or a,a ;вместо cp 0
and a,a ;для сброса CY
(хоть команды аналогичны)
т.е. установка Z - это фича (;
Экономится место. Зачем ставить JP, если нет разницы 10 тактов или 12 будет в итоге? Если не критично - то ставим jr.
Кроме того, JP ест на 1 байт больше.
Ещё влияет контекст будет или нет переход.
IY не бесполезный регистр, если не использовать подпрограммы ПЗУ. Но мне это не пригодилось. IX хватает.
В своих программах никогда не использовал IX/IY. Может разве что пару раз.
Их всегда имел ввиду, но без них программы получались более быстрыми и требующими меньше памяти. Всегда.
IX и IY неудобные регистры. Они каждое свое использование едят 1 байт памяти, + 4..12 тактов каждое использование (по сравнению с HL), разбить их на старший-младший проблематично и т.д.. Все что можно с ними делать, делается с помощью HL.
Неиспользуемые и редкоиспользуемые команды из основного набора
Думаю следует просмотреть список на использование недокументированных команд (с префиксами FD, DD). Например
defb #FD
or l
не сделает ли случаем OR с младшей частью IY?
IX и IY неудобные регистры.
Если нужна индексная адресация, то они весьма удобны. Через HL сделать конечно можно (имитировать индексную адресацию), но нужно будет потратить куда больше тактов, чем использовать IX or IY, например, заменяем команду or (ix+10h)
push hl
push bc
ld bc,10h
add hl,bc
or (hl)
pop bc
pop hl
Ну как? Это в смысле функционала - эквивалент, если не учитывать прерывание, которое может прийти во время отработки процедуры. Сколько тактов? То-то и оно!
не сделает ли случаем OR с младшей частью IY?
Сделает. Этот как раз "проблематичная" реализация разбития на старший-младший. Во всех нормальных ассемблерах этой порнографии есть замена:
or ly
Т.е. IY=HY+LY
Если нужна индексная адресация, то они весьма удобны. Через HL сделать конечно можно (имитировать индексную адресацию), но нужно будет потратить куда больше тактов, чем использовать IX or IY, например, заменяем команду or (ix+10h)
В том то и дело, что в реальных программах индексная адресация нужна крайне редко, и все эти редкие случаи успешно решаются основными регистрами.
Конечно можно придумать кучу примеров в вакууме, работающих только в вакууме. В реальности же в IX нужно сначала что-то записать, потом с ним работать. Если программа маленькая, то обычные регистры свободны, и делается все быстро без IX. Если большая, то IX используется часто, и тоже подлежит замене.
Та же адресация (ix+10h) не используется просто так. Никто не пишет
ld ix,NN
or (ix+10h)
все пишут
ld hl,NN+#10
or (hl)
аналогично, если адрес используется, и используется смещение
ld ix,NN
or (ix+0)
or (ix+#10)
то
ld hl,NN
or (hl)
ld hl,NN+#10
or (hl)
Если смещение используется несколько раз, то это говорит о том, что оно в цикле. Такое использование решается выводом обращения через другой регистр с его сохранением (из-за цикла сохранение становится в разы дешевле).
Если хочется дергать значения многих переменных, то обращение напрямую через
ld a,(NN)
быстрее и эффективнее.
и т.д.
IX представляет зачастую только академический интерес. Может быть полезен для более наглядного кода. Но для быстродействующего и занимающего мало памяти кода его применение крайне редкое.
NovaStorm
25.06.2012, 08:46
А что насчёт реэнтерабельности и переменных на стеке?
Куда тут без IX/IY?
Куда тут без IX/IY?
Не говорю о том, что IX и IY нельзя использовать. Но в абсолютном большинстве случаев их использовать накладно по ресурсам.
Пример успешного использования IX:
; внешний цикл. 100 раз.
; внутренний цикл. 100 раз.
; что-то делается со всеми регистрами общего назначения
; 100 раз.
; конец внутреннего цикла
; результат - в BC. Его нужно суммировать где-то.
;
add ix, bc
; конец внешнего цикла
Т.е. иметь регистр надо ввиду, но его использование срабатывает редко.
Такая же ситуация с командами работы с битами (set, bit, res). Их использование крайне ограничено по тем же причинам. Можно сколько угодно говорить что например
set 4, d
можно заменить только на какую-нибудь душераздирающую конструкцию вида
push af
ld a,d
or #10
ld d,a
pop af
но на практике зачастую серия команд программы может быть преобразована так, что регистр пройдет через аккумулятор и в нужное время будет установлен нужный бит.
Но например если работаем с (hl), то такая конструкция
set 7,(hl)
выгодней, нежели
ld a,(hl)
or #80
ld (hl),a
аналогично, если адрес используется, и используется смещение
ld ix,NN
or (ix+0)
or (ix+#10)
то
ld hl,NN
or (hl)
ld hl,NN+#10
or (hl)
несколько не соглашусь. тут либо пример плохой либо одно из двух. выполнение ld ix,nn = 14тактов. ld hl,nn 10тактов. + каманда or жрёт 10 тактов (если я верно понял содержание таблицы). т.е. получается в вашем примере 30тактов на выполнение простого куска. тут в данном случае ld ix,nn or (ix+n) будет безусловно быстрее. и воо многих других случаях. когда нужно пересохранять основные регистры и потом восстанавливать, индексные спасают.
несколько не соглашусь. тут либо пример плохой либо одно из двух. выполнение ld ix,nn = 14тактов. ld hl,nn 10тактов. + каманда or жрёт 10 тактов (если я верно понял содержание таблицы). т.е. получается в вашем примере 30тактов на выполнение простого куска. тут в данном случае ld ix,nn or (ix+n) будет безусловно быстрее. и воо многих других случаях. когда нужно пересохранять основные регистры и потом восстанавливать, индексные спасают.
в моем справочнике:
or (hl) - 7 тактов
ld hl,NN - 10
or (ix+s) - 19
ld ix, NN - 14
итого: 19+19+14=42 vs 10+7+10+7=34
и память 11 vs 8
В том то и дело, что в реальных программах индексная адресация нужна крайне редко
В каких реальных программах? Вы знакомы со всеми программами? Я вот успешно применяю и IX и IY. И мне удобно. Когда мы обрабатываем, например описатель FCB файла или иной блок с инфой о файле. На начало блока ставим индексный регистр и вуаля! Без них пришлось бы весьма туго. И ещё много много примеров можно сказать, где они нужны.
---------- Post added at 11:18 ---------- Previous post was at 11:15 ----------
Но в абсолютном большинстве случаев их использовать накладно по ресурсам.
Смотря что считать абсолютным большинством. Если как замену HL - то да. Но иногда и в этом плане он полезен, когда HL занят и сохранять/восстанавливать накладно. Регистры индексные! Они нужны для индексной адресации. Если вы не в курсе зачем её применяют - не повод этим гордиться. Наоборот, есть повод подучиться, узнать. Что и как.
всё вопрос отпал...проверил, вариант с hl быстрее. каманда or (ix+n) жрёт 19 тактов...извиняюсь!
Если хочется дергать значения многих переменных, то обращение напрямую через
Да? А если у нас не один набор переменных, а несколько? Что прикажете делать?
Когда мы обрабатываем, например описатель FCB файла или иной блок с инфой о файле. На начало блока ставим индексный регистр и вуаля! Без них пришлось бы весьма туго. И ещё много много примеров можно сказать, где они нужны.
Где на это можно посмотреть?
аналогично, если адрес используется, и используется смещение
ld ix,NN
or (ix+0)
or (ix+#10)
то
ld hl,NN
or (hl)
ld hl,NN+#10
or (hl)
Пример безусловно, когда ix накладно использовать. Некорректный. IX и IY используют, например, когда у нас есть некие наборы данных, которые мы упорядочиваем по смещениям. Достаточно установить на начало область индексный регистр - как мы получаем доступ к структуре. И можем моментально менять адреса разных структур. Иначе, придется заниматься вычислениями и сохрананениями восстановлениями. Индексы ведь не используют, когда надо обратиться к одной переменной. Смысла нет, так что пример некорректный.
---------- Post added at 11:28 ---------- Previous post was at 11:25 ----------
Где на это можно посмотреть?
Например - файловый коммандер. У нас 2 панели. Так? Нужно хранить параметры для левой и правой панели, по сути одни и те же. Можно завести переменные, и работать с ними. 2 набора процедур или вычислять адреса переменных, а можно на переменные указывать индексным регистром и при вызове процедуры ставить в него нужное значение.
---------- Post added at 11:30 ---------- Previous post was at 11:28 ----------
Ведь есть много случаев, когда компактность и понятность кода важнее скорости. Если мы не демках говорим. Пусть будет на 10-30 тактов дольше, но без сумасшедших сохранений, перемещений и восстановлений. Т.е. не надо путать время-критичный код от логики.
Andrew771
25.06.2012, 09:50
Массив записей, в котором нужно периодически выдирать конкретное поле, попробуйте без ix сделать. :)
Вот развели флейм... Все же можно посчитать!
Возьмем за базу такую реализацию:
ld hl,xx
and/or/xor (hl)
Суммарный размер таких вот конструкций будет 4*N (N- количество обращений), время на выполнение- 17*N.
Альтернатива:
ld ix,xx
and/or/xor (ix+idx)
Размер будет 7+3*(N-1), время 14+19*(N-1).
Считаем, когда индексные регистры будут выгоднее по памяти:
4N > 7+3(N-1) => N > 4
Считаем, когда индексные регистры будут выгоднее по времени:
17N > 14+19(N-1) => N < 3
Отсюда простой вывод, что индексные регистры удобее для следующих ситуаций:
- нечастый доступ к полям структур в случайном порядке (при последовательном обращении проще inc/dec hl/l)
- доступ к структурам глобальных переменных (другие регистры обычно заняты)
Andrew771
25.06.2012, 10:15
ld hl,xx
and/or/xor (hl)
Проблема в том, что этот xx в массиве записей нужно сначала получить расчетом в зависимости от индекса в массиве и смещения в записи.
Проблема в том, что этот xx в массиве записей нужно сначала получить расчетом в зависимости от индекса в массиве и смещения в записи.
ld bc,xx*sizeofRecord
add ix,bc
Думаю, можно согласиться, что ld b,b и т.п. пустышки вроде nop бесполезны, но лишь как издержка архитектуры данного процессора. Однако практически все команды используются, а какие где чаще или реже - смотря какие задачи решаются.
p.s. Кстати, Эллочка обходилась всего 30 словами. Так что, не стоит демонстрировать свое неумение пользоваться всеми возможностями процессора, а лучше расширять свой "словарный запас" :)
Пример безусловно, когда ix накладно использовать. Некорректный. IX и IY используют, например, когда у нас есть некие наборы данных, которые мы упорядочиваем по смещениям. Достаточно установить на начало область индексный регистр - как мы получаем доступ к структуре. И можем моментально менять адреса разных структур. Иначе, придется заниматься вычислениями и сохрананениями восстановлениями. Индексы ведь не используют, когда надо обратиться к одной переменной. Смысла нет, так что пример некорректный.
Замечу, что с передачей структур в функцию конкурирует другой метод. А именно - копирование необходимой информации в ту область памяти, на которую настроена функция.
Например - файловый коммандер. У нас 2 панели. Так? Нужно хранить параметры для левой и правой панели, по сути одни и те же. Можно завести переменные, и работать с ними. 2 набора процедур или вычислять адреса переменных, а можно на переменные указывать индексным регистром и при вызове процедуры ставить в него нужное значение.
В общем случае я согласен с этим примером. Могу добавить ещё один. Если мы делаем игру для двух игроков, поведение каждого из которых одинаково, то можем создать две области памяти, в каждой из которых одинаково хранится информация каждого из игроков. И впоследствии, если хотим обработать игрока X, то устанавливаем в нужное значение индексный регистр и запускаем.
Для большинства же рабочих функций (которые влазят "на экран") если мы передаем более 4-х параметров (A, BC, DE, HL) с помощью структур (IX/IY или каким-то другим способом) является серьезным поводом задуматься о том, правильно ли мы разработали функцию.
Кроме того замечу, что IX/IY - это "аналоги" глобального пространства имен в языках высшего уровня. Другими словами, если мы задействовали где-то IX, и где-то у нас есть другая процедура, использующая IX, то это переменное использование нужно контролировать, и в случае проблем это стоит долгих часов отладки.
Ведь есть много случаев, когда компактность и понятность кода важнее скорости. Если мы не демках говорим. Пусть будет на 10-30 тактов дольше, но без сумасшедших сохранений, перемещений и восстановлений. Т.е. не надо путать время-критичный код от логики.
С этим согласен.
Только у меня речь идет о компактности и быстроте реализации, а не о понятных программах, которые занимают столько места и времени, сколько им позволяет пользователь.
Для большинства же рабочих функций (которые влазят "на экран") если мы передаем более 4-х параметров (A, BC, DE, HL) с помощью структур (IX/IY или каким-то другим способом) является серьезным поводом задуматься о том, правильно ли мы разработали функцию.
А как быть если это необходимо? Например тот же дисковый ввод вывод. Int13 на ПЦ, расширенные функции, номер сектора (32 бит или более) передают уже в дескрипторе, там же адрес DTA, кол-во секторов и код операции. Немалое кол-во операндов? Но ведь или мы их расположим в регистрах или в дескрипторе, иначе никак. Ну либо разложим в ряд вызовов, который "рассуют" параметры по нужным местам, но тогда проигрываем в скорости.
судя по всему, bsivko никогда не работал со структурами... о чем тут говорить?
А как быть если это необходимо? Например тот же дисковый ввод вывод. Int13 на ПЦ, расширенные функции, номер сектора (32 бит или более) передают уже в дескрипторе, там же адрес DTA, кол-во секторов и код операции. Немалое кол-во операндов? Но ведь или мы их расположим в регистрах или в дескрипторе, иначе никак. Ну либо разложим в ряд вызовов, который "рассуют" параметры по нужным местам, но тогда проигрываем в скорости.
There are many ways to skin a cat (;
Мастерство инженера тем и определяется, чтобы видеть большое количество способов и использовать тот, который наиболее подходящий к ситуации.
Так, например тут не назван случай, когда проект сдавать надо прямо сейчас, и времени на оптимизацию без индексов нет.
---------- Post added at 11:17 ---------- Previous post was at 11:16 ----------
судя по всему, bsivko никогда не работал со структурами... о чем тут говорить?
Судя по всему, вы переходите на личности. Высказывайтесь по существу и уважайте мнение и опыт других людей.
Высказывайтесь по существу
а я высказался вообще-то, по существу. со структурами вы не знакомы, поэтому у вас возникают вопросы, зачем нужен индексный регистр. когда у вас будет куча структур байт по 100 и 30 разных подпрограмм использующих/меняющих отдельные поля - тогда будет видно, дороже будут IX/IY или дешевле. вам уже привели примеры с FCB и прочим, вас это не устраивает. о чем дальше-то дискуссию вести? это вы здесь не уважаете опыт и мнение других людей, я лишь обобщил это.
psb, повяторяю. Вы обсуждаете меня, а не тему и суть вопроса. Обо мне вы ровным счетом ничего не знаете. Поэтому не нужно говорить о том, в чем вы не разбираетесь.
С ровно таким же успехом я могу сказать, что вы не умеете использовать регистры общего назначения и не умеете структурировать программы так, чтобы не передавать в функции кучу параметров.
Вам нравится такое общение? Общайтесь так с кем-нибудь другим.
Мое мнение: в абсолютном большинстве случаев работы с индексными регистрами можно избежать на Speccy, обеспечив при этом большую скорость и меньший расход памяти, вполне возможно в ущерб читаемости и сопровождаемости кода.
Speccy не предназначен для работы с большими структурами данных. Ни в 80-х, ни в 90-х, ни сейчас. Для работы с большими структурами данных были и есть более мощные и более приемлемые машины. В связи с этим использование структур для передачи в функции на ZX несут зачастую академический и спортивный интерес.
Это - мое мнение. Такая же имха, как и ваша.
вам уже привели примеры с FCB и прочим, вас это не устраивает.
Что меня устраивает и что нет - читайте выше. Внимательно.
Andrew771
25.06.2012, 13:23
Сообщение от Andrew771
Проблема в том, что этот xx в массиве записей нужно сначала получить расчетом в зависимости от индекса в массиве и смещения в записи.
ld bc,xx*sizeofRecord
add ix,bc
наверно, ты имел в виду hl?
ну а дальше в bc задавать смещение внутри записи, и опять add hl,bc?
Потом, допустим, рядом или через один-два байта еще нужно что-то считать, писать inc hl по несколько раз?
:)
---------- Post added at 13:23 ---------- Previous post was at 13:22 ----------
к тому же портятся регистры hl и bc, а они нужны под рукой часто, особенно hl.
Вы обсуждаете меня, а не тему и суть вопроса.
вы не видите сути, к тому же вы вбили в себе в голову, что спек для чего-то предназначен, для чего-то не предназначен - это ваши личные тараканы. вы можете даже утверждать, что достаточно аккумулятора и одного лишь HL, и в принципе будете правы. но на практике, как вам уже сказали (тема про практику, верно?), IX бывает очень полезен. сядьте, напишите OS или хороший гибкий менеджер окон, после этого расскажете всем нам, как у вас все здорово и понятно (расширяемо, поддерживаемо) получилось:)
в абсолютном большинстве случаев работы с индексными регистрами можно избежать
в каком таком абсолютном большинстве? вы задачу тогда уточняйте. в большинстве случаев для оси и оконного менеджера эти регистры будут очень полезны (и в плане понятности, и в плане скорости, и в плане гибкости). а для демок наоборот, в большинстве случаев вредны. игры тоже могут разделиться 50/50 в зависимости от типа игры. какое такое у вас большинство - я хз.
В связи с этим использование структур для передачи в функции на ZX несут зачастую академический и спортивный интерес.
это ваши личные тараканы, этот вывод сделан неизвестно исходя из чего (предполагаю, вы просто не представляете себе таких программ, когда уровень вложенности подпрограмм больше одного:) заколебетесь передавать в верхнюю всю кучу параметров).
Alex Rider
25.06.2012, 16:21
в абсолютном большинстве случаев работы с индексными регистрами можно избежать
ftp://ftp.worldofspectrum.org/pub/sinclair/books/CompleteSpectrumROMDisassemblyThe.txt
А мужики-то не знали...
P.S. Попробуй заоптимизировать без IX LD-BYTES, SAVE-ETC, к примеру :)
наверно, ты имел в виду hl?
Полагаю Vitamin имеет ввиду недокументированную команду (http://zx.pk.ru/showpost.php?p=2616&postcount=2) ADD IX,BC (defb #DD, #09).
P.S. Попробуй заоптимизировать без IX LD-BYTES, SAVE-ETC, к примеру
Сейчас нет фтп-доступа. Как только, обязательно посмотрю.
Полагаю Vitamin имеет ввиду недокументированную команду (http://zx.pk.ru/showpost.php?p=2616&postcount=2) ADD IX,BC (defb #DD, #09).
Когда она стала недокументированной?
Для справки, вывод текста во фреймовых листалках делают через индексные регистры (текст - в DE, графика букв в BC, HL, генерируемый код в IX, IY).
Мое мнение: в абсолютном большинстве случаев работы с индексными регистрами можно избежать на Speccy, обеспечив при этом большую скорость и меньший расход памяти, вполне возможно в ущерб читаемости и сопровождаемости кода.
Не пойму, о чем вообще спор. IX и IY - это фича Z80 для поддержки языков высокого уровня. Точка.
Полагаю Vitamin имеет ввиду недокументированную команду ADD IX,BC
Читая некоторые спек. журналы в конце 90-х, с удивлением обнаружил, что нормальные команды z80 вдруг стали записывать в "недокументированные". Такие как set 7,(ix+d), bit 0,(iy+d), add ix,rw (rw=bc,de,ix) и т.д. и т.п. Документацию на проц авторы тех текстов явно не читали. А начиная с проца Z-180 стали "легальными" и обращения к половинкам индексных регистров. Zilog предложила написание YH, YL, XH, XL. Хотя конечно сути это не меняет, в конкретном трансляторе можно использовать любое написание.
Такие как set 7,(ix+d), bit 0,(iy+d), add ix,rw (rw=bc,de,ix) и т.д. и т.п.
Они еще не видели LD A,SRL (ix+d); LD A,SET 7,(IX+d) :)
Они еще не видели LD A,SRL (ix+d); LD A,SET 7,(IX+d)
Ну вот эти, действительно незадокументированы.
А клоны команд по кодам ED XX - я не считаю недок. Это издержки неполной дешифрации, а в Z-180 280 по кодам "двойников" появились новые команды. И ED 00-3F задействовали.
Alex Rider
26.06.2012, 10:26
Сейчас нет фтп-доступа. Как только, обязательно посмотрю.
http://freestuff.grok.co.uk/rom-dis/csrd-rtf.zip
:)
IX и IY - это фича Z80 для поддержки языков высокого уровня.
То-то я смотрю, что мне IX понадобился когда я писал 42-символьный редактор, а оказывается, я не сообразил просто - если есть редактор, значит я уже пишу язык высокого уровня! Все гениальное просто. :)
http://freestuff.grok.co.uk/rom-dis/csrd-rtf.zip
Предложенная процедура весьма специфична.
Во-первых ПЗУ. Здесь применить мета-программирование не получится. Плюс афаик, совсем не приветствуется использование ячеек памяти ОЗУ для хранения каких-либо данных. Завуалированный переход от фон-неймана к гарварду..
Во-вторых, загрузка и запись на ленту не требуют быстродействия. Например задержка LD-DELAY может, IIRC, варьиороваться ~ от 70 до 500 тактов. В связи с этим оптимизировать тут можно только память. А судя по объединению LOAD и VERIFY память очень даже экономили. Несмотря на то, что в конце 16к осталось много места.
Для оптимизации в любом случае придется переписать процедуру.
Alex Rider
26.06.2012, 23:37
Однако это есть еще один пример подходящей для использования индексных регистров задачи, которая не есть язык высокого уровня и не использует шлобальное пространство имен. В LB-BYTES/SA-BYTES IX используется как альтернатива HL - указатель текущей ячейки памяти, а сам HL - как пара обычных 8-битных РОН. А вот в SAVE-ETC IX используется как полноценный индексный регистр в динамической памяти, и используется грамотно и красиво. Так что IX нужен, кто не умеет использовать - подтягивайтесь, учитесь. Меня он сильно выручает когда не хватает регистров и не хочется писать в стек.
То-то я смотрю, что мне IX понадобился когда я писал 42-символьный редактор, а оказывается, я не сообразил просто - если есть редактор, значит я уже пишу язык высокого уровня!
Ключевые слова выделены. Про понятие о том, что такое поддержка микропроцессорами языков высокого уровня - третий выделенный блок ключевых слов.
Alex Rider
30.06.2012, 02:41
Гм... Чего это я завелся-то... Никто никому же не запрещает считать, что по-настоящему IX и IY нужны только для поддержки ЯВУ, а использование их в других целях - изврат, непрофессионализм, непотребный расход памяти и/или тактов и признак лоха.
Barmaley_m
06.07.2012, 15:02
Индексная адресация - мощное средство для поддержки объектно-ориентированного программирования. Да, объектно-ориентированно можно программировать и на ассемблере. Тут уже говорили о структурах - это частный случай объектов.
Когда программа должна обслуживать одновременно много однотипных объектов - тогда и нужна индексная адресация. Например, она часто используется в музыкальных плеерах. Почти все AY-, биперные и цифровые плееры ее используют. В музыкальном плеере объект - это состояние канала. Поскольку каналы однотипные, то логично их обслуживать одной программой. А поскольку состояние каждого канала занимает несколько байт - то естественно использование индексной адресации. Подпрограммам обслуживания канала в одном из индексных регистров передается адрес в памяти, где хранится состояние этого канала. Подпрограммы обращаются к состоянию канала только посредством индексной адресации. При изменении логики работы плеера нужно менять меньше кода, чем если бы подпрограммы обслуживания каналов не использовали индексной адресации, а дублировались для каждого канала. Также достигается универсальность: одни и те же подпрограммы могут обслуживать любое количество каналов, ограниченное только объемом памяти под состояние.
В играх тоже часто возникает необходимость обслуживать одновременно несколько однотипных объектов. Например, это могут быть монстры и другие независимые персонажи. Если состояние каждого объекта занимает больше, чем два-три байта - то и здесь естественным и выгодным в плане скорости является использование индексной адресации.
Операционные системы работают с объектами. Если одновременно открыто несколько файлов - то состояние каждого файла (FCB) должно храниться где-то в памяти, а подпрограммы работы с этим состояниям естественно используют индексную адресацию. Кроме файлов, операционные системы работают со многими другими объектами, такими как потоки (Threads), объекты синхронизации (Event, Mutex, Semaphor) и др.
Менеджеры окон работают с окнами - это тоже объекты. И даже когда я писал свой первый менеджер окон - то использовал в нем индексную адресацию, хоть я тогда и не знал точно, что это такое - "объектно-ориентированное программирование".
Современная тенденция такова, что индексная адресация добавляется в те микроконтроллеры, где ее раньше не было. Например, новые 8-битные микроконтроллеры семейства PIC16 и даже "маленькие" PIC12 в последние годы получили новые команды индексной адресации, что существенно расширяет возможности этих контроллеров.
В этом свете удалять индексную адресацию оттуда, где она уже была - верх безумия.
Наличие двух индексных регистров тоже важно, так как позволяет работать одновременно с двумя объектами. Это важно в тех случаях, когда происходит взаимодействие объектов. Если бы был только один индексный регистр - то для реализации взаимодействия объектов его либо приходилось бы постоянно переключать с одного объекта на другой, либо копировать состояние одного из объектов. Обе названные альтернативы вызывают лишние затраты процессорного времени.
Вопрос не о полезности индексной адресации, она безусловно полезна и без всякого ООП (которое я, кстати, очень не люблю, но это дело вкуса). Вопрос о корявости индексной адресации и ее тормознутости в Z80. Понятно, что добавлена она была в процессор, как надстройка, посему ни с точки зрения экономии места, ни с точки зрения скорости не дает особых преимуществ относительно ее реализации несколькими командами.
В том же процессоре 6502, она заложена изначално и очень быстра и экономична.
Вот.
Barmaley_m
06.07.2012, 20:29
без всякого ООП (которое я, кстати, очень не люблю, но это дело вкуса).
Тут дело не во вкусе, а в необходимости. Вот представь себе: игра, в ней враги, их много, и у каждого свое состояние. Как писать код, обслуживающий врагов, без ООП (в явном или неявном виде)?
Какие другие парадигмы программирования ты используешь? Вот, например, из этого списка:
http://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D1%80%D0%B0%D0%B4%D0%B8%D0%B3%D0%BC%D 0%B0_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0 %BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8 F
Вопрос о корявости индексной адресации и ее тормознутости в Z80. Понятно, что добавлена она была в процессор, как надстройка, посему ни с точки зрения экономии места, ни с точки зрения скорости не дает особых преимуществ относительно ее реализации несколькими командами.
Позволь не согласиться. Если твоя программа работает с некоторой структурой данных, причем доступ к ее членам происходит не последовательно - то индексная адресация существенно быстрее, чем ее замена косвенной адресацией. Так, например, команда:
LD A,(IX+n) занимает 3 байта и выполняется за 19 тактов, тогда как ее замена в общем случае (без ограничений на расположение структуры в памяти) требует двухбайтового сложения:
LD BC,n ; 10 тактов
ADD HL,BC ; 11 тактов
LD A,(HL) ; 7 тактов
Всего 5 байт и 28 тактов, места больше на 67%, по времени дольше на 47%, к тому же, требуются две хорошие регистровые пары (HL,BC), тогда как при использовании индексной адресации они свободны.
Можно ли было сделать лучше? Да, но ненамного. Сохраняя общую структуру Z80, теоретически можно убрать только префикс (DD/FD) и связанные с ним 4 такта. Остальные 19-4=15 тактов неизбежно останутся: они нужны для выборки кода команды, смещения, 16-битного сложения и обращения в нужную ячейку памяти.
В том же процессоре 6502, она заложена изначално и очень быстра и экономична.
Быстра и экономична? Это смотря с чем сравнивать. Учитывая, что у 6502 нет 16-битных регистров и 16-битного сложения, затраты на "обход" косвенной адресации очень значительны. А по машинным циклам, думаю, получается примерно то же самое. В самом деле, для выполнения команды 6502:
LDA (0x36),Y
требуется:
1) считать код команды (1 байт)
2) считать адрес косвенного обращения (1 байт)
3) считать байт по адресу 0x36 (младший байт базового адреса обращения)
4) считать байт по адресу 0x37 (старший байт базового адреса обращения)
5) 16-битное сложение базового адреса обращения и индексного регистра (как правило, 2 машинных цикла)
6) считать содержимое памяти по адресу обращения.
Итого 7 машинных циклов - против 5 у Z80. Ну или ладно, зачтем Z80 6 циклов, потому что один из них длинный (5 тактов). Что-то не вижу большого выигрыша.
---------- Post added at 18:29 ---------- Previous post was at 18:21 ----------
Добавлю. Приведенная выше косвенно-индексная адресация требует, при обращении к элементам структуры в произвольном порядке, установки регистра Y каждый раз перед обращением, что еще больше повышает затраты.
Если же вести речь о простой индексной адресации вида:
LDA addr,X
то такая индексная адресация не совсем полноценная, потому что индексный регистр однобайтовый. Это не позволяет хранить структуру в произвольном месте памяти: подпрограммы ее обслуживания должны хотя бы приблизительно знать ее местонахождение.
Я видел хитрые приемы построения программ для организации массива структур с использованием простой индексной адресации. Эти приемы накладывают на программу существенные ограничения. Универсальность кода страдает очень сильно. Впрочем, для игр Atari или NES этого было вполне достаточно. Я анализировал атариевский плеер музыки - именно там использовались эти приемы. Музыка, 4 канала - и известно, что больше не будет. Тогда, конечно, ограничения индексной адресации не играют большой роли.
Итого 7 машинных циклов - против 5 у Z80. Ну или ладно, зачтем Z80 6 циклов, потому что один из них длинный (5 тактов). Что-то не вижу большого выигрыша.
5 или 6 циклов в зависимости от того, есть ли переход через страницу при сложении с Y. И у 6502 1 цикл это 1 такт.
Тут дело не во вкусе, а в необходимости. Вот представь себе: игра, в ней враги, их много, и у каждого свое состояние. Как писать код, обслуживающий врагов, без ООП (в явном или неявном виде)?
Конечно, враги - это обьекты. Но я не люблю не работу с обьектами (структурами данных), а работу методами ООП. Когда идет наследование чего-то от кого-то, а ты видишь только верхушку айсберга при взаимодействии с обьектом. Любая абстракция от железа и, тем более, четкого понимания всех элементов массива данных, мне претит. Для ООП это нормально. Но мне такое программирование не интересно. Мне нравится программировать на низком уровне, с чувством железа, каждого байтика и битика. Там, где я все сделал сам, и понимаю в деталях, как, зачем и почему это работает. Тут для меня большое поле для творчества. Тут можно выжать из железа или алгоритма невозможное. А кому-то нравится ООП. Дело вкуса и склада мышления.
---------- Post added at 23:28 ---------- Previous post was at 23:25 ----------
LD A,(IX+n) занимает 3 байта и выполняется за 19 тактов, тогда как ее замена в общем случае (без ограничений на расположение структуры в памяти) требует двухбайтового сложения:
LD BC,n ; 10 тактов
ADD HL,BC ; 11 тактов
LD A,(HL) ; 7 тактов
Всего 5 байт и 28 тактов, места больше на 67%, по времени дольше на 47%, к тому же, требуются две хорошие регистровые пары (HL,BC), тогда как при использовании индексной адресации они свободны.
Это если делать в лоб и универсально.
А если:
LD L,#nn ; 7 тактов
LD A,(HL) ; 7 тактов
То это гораздо быстре.
Что? Нет универсальности? Любая универсальность раздувает код, замедляет скорость и заставляет лениться)
Andrew771
07.07.2012, 20:28
А если:
LD L,#nn ; 7 тактов
LD A,(HL) ; 7 тактов
То это гораздо быстре.
И чего? Мне теперь делать первый адрес каждого объекта с HL кратным 256?
А если:
LD L,#nn ; 7 тактов
LD A,(HL) ; 7 тактов
То это гораздо быстре.
быстрее, но применимо тока в демах, когда в большинстве случаев пофиг на память.
И чего? Мне теперь делать первый адрес каждого объекта с HL кратным 256?
именно что.
Andrew771, сколько у тебя будет обьектов?
в Валкере Рома делал именно так
Andrew771
09.07.2012, 00:06
Andrew771, сколько у тебя будет обьектов?
в Валкере Рома делал именно так
около 2000.
Andrew771, тогда тебе нужно использовать индекс
в валкере было около 200 обьектов
и структуры формировались следующим образом
L-номер обьекта
H-различные поля обьекта
Andrew771
09.07.2012, 09:57
Andrew771, тогда тебе нужно использовать индекс
да, я так и делаю, очень удобно. Тем более, быстродействие в моей игре не так важно.
в валкере было около 200 обьектов
и структуры формировались следующим образом
L-номер обьекта
H-различные поля обьекта
О, а это классная идея! Возьму на вооружение на будущее.
ну и нафлудили... тогда уж поспорьте о том что стек нужен исключительно для call и передачи параметров или что там оно еще в оригинале должно делать...
Это ограниченное железо и любой команде (большинству из них можно найти применение). Ведь используют же стек для вывода графики или в качестве более выстрой альтернативе ldi
И тут также... начав по теме вы ушли влево начиная обсуждать ООП и нужность индексной адресации. А забыли что IX и IY это два дополнительных 16-битных сумматора?
Да и просто курим исходники tmap`а от alone codera и пробуем сделать быстрее и короче без использования ix,iy.
Barmaley_m
10.07.2012, 23:51
Вообще разработка системы команд процессора - это очень тонкое дело. Например, меня всегда бесила система команд Microchip PIC16: мало команд, один регистр, переключение банков. По сравнению с этим так стройно и красиво смотрелась система команд Atmel AVR: много команд, много регистров, линейное адресное пространство. А на поверку, редко какой критичный кусок кода мне удавалось запрограммировать для AVR быстрее (по количеству машинных циклов), чем на PIC16. Обычно получалось даже наоборот. Вот такой вот парадокс. Красота архитектуры - еще не значит эффективность.
у эффективности критериев очень много разных.
Andrew771
12.07.2012, 21:40
Еще не хватает команды ex bc,hl. Несколько раз нужна была, приходится извращаться.
А еще непонятно, почему есть add ix,rp, а sbc ix,rp нет.
А еще непонятно, почему есть add ix,rp, а sbc ix,rp нет.
sbc hl,rp - это расшерение набора 0xED, а он не умеет работать с индексными регистрами.
Еще не хватает команды ex bc,hl. Несколько раз нужна была, приходится извращаться.
PUSH BC
EX (SP),HL
POP BC
ld a,b,b,h,h,a
ld a,c,c,l,l,a
Так быстрее :)
---------- Post added at 12:49 ---------- Previous post was at 12:32 ----------
Да и просто курим исходники tmap`а от alone codera и пробуем сделать быстрее и короче без использования ix,iy.
С помощью весьма экстремальных техник можно ускорить отрисовку в два раза. Но на сложных объектах отрисовка занимает только 10-20% времени. Математика и c2p кушают больше.
ld a,b,b,h,h,a
ld a,c,c,l,l,a
Так быстрее :)
Вариант хорош когда используется стек, но запарывает регистр А :) Я всегда ищу компромисc :)
Evgeny Muchkin
01.02.2013, 16:26
XOR A совершенно ненужная команда, ведь есть SUB A! :D
ZXZXEmul наконец собран в виде бейсика и получил описание. Требует ATM Turbo 2 (можно перекомпилировать под Pentagon 1024): http://alonecoder.nedopc.com/zx/zxzxem02.zip
Andrew771
15.10.2013, 09:59
Еще вот есть предложение по новой команде. Она требуется, когда в одном байте хранится несколько однобитовых флагов: определение количества включенных битов в байте.
А зачем знать, сколько флагов включено? Я читал про такие команды, но они вроде как использовались для определения числа ведущих нулей при упаковке в плавающую точку.
Andrew771
16.10.2013, 11:05
А зачем знать, сколько флагов включено?
Иногда нужно в играх:
1. Если просматриваются соседние 8 клеток от клетки игрока и ставятся для них флаги при наличии чего-либо в этих клетках.
2. Если флаги в байте показывают наличие/отсутствие каких-либо полей в текущей записи (например, ресурсы юнита).
А какая разница, врагов вокруг 1 или 3?
Andrew771
16.10.2013, 13:26
А какая разница, врагов вокруг 1 или 3?
смотря что за игра. :)
В Эйфории учитывается сила всех окружающих врагов для определения бегства или атаки.
---------- Post added at 13:26 ---------- Previous post was at 13:23 ----------
Еще при выводе нужного спрайта дороги или оборонительной стены нужно учитывать окружающие клетки, т.к. на карте в памяти хранится только ID клетки без указания конкретного спрайта.
В Эйфории учитывается сила всех окружающих врагов для определения бегства или атаки.
Если важно только количество бит, то можно по 256-байтной таблице посчитать их количество. Но если ещё важна и сила для ИИ или расположение соседних тайлов для рисования дорожек и стен, то не получится. Команда не спасёт.
Andrew771
16.10.2013, 16:47
Команда только упростит задачу, код станет нагляднее, но понятно, что полностью не спасет. А сейчас приходится ковырять сдвигом через CY флаг и проверять его.
Было бы очень хорошо если бы команды SET n,reg (и RES n,reg) влияли на флаг Z (или С) запихивая туда состояние бита перед установкой (сбросом).
Было бы очень хорошо если бы команды SET n,reg (и RES n,reg) влияли на флаг Z (или С) запихивая туда состояние бита перед установкой (сбросом).
чтобы сэкономить байт/такт?
Andrew771
17.10.2013, 13:51
Было бы очень хорошо если бы команды SET n,reg (и RES n,reg) влияли на флаг Z (или С) запихивая туда состояние бита перед установкой (сбросом).
можь лучше сразу новое значение? :)
чтобы сэкономить байт/такт?
Чтобы выполнялся сразу BIT n,reg и SET(RES).
Т.е. сейчас SET/RES флаги не трогает, а лучше бы выставлял их как-бы если это BIT (проверка что там в бите) а уж потом сбрасывал (или устанавливал).
Много раз я уже такого желал в разных моих прогах такое помогло бы избавится от лишних проверок, ведь очень часто после проверки бита - с ним надо гарантированно что-то делать, сбросить или наоборот (при том что ветвление по состоянию состоится чуть позже)
---------- Post added at 17:52 ---------- Previous post was at 17:45 ----------
можь лучше сразу новое значение?
Зачем, если оно и так известно?
Чтобы выполнялся сразу BIT n,reg и SET(RES)
Такие команды были ещё в DEC процах. Проверка и установка, проверка и сброс. В ПЦ процах я не помню, когда они появились, но есть (насколько я помню). В DEC системе команд было и ещё много полезного, хотя некоторое, например загрузка в регистр меняющая флаги, мне неприятна. Но это - идеология. У DEC была своя система команд, у Intel - своя.
---------- Post added at 22:01 ---------- Previous post was at 21:58 ----------
PUSH BC
EX (SP),HL
POP BC
Ответ некорректен. Это - программа - последовательность команд, да ещё и влияющая на ОЗУ. Конечно, при определённых условиях она заменяет желаемую команду, но если ОЗУ использовать нельзя - то нет.
---------- Post added at 22:05 ---------- Previous post was at 22:01 ----------
чтобы сэкономить байт/такт?
При программировании бывают моменты, когда это действительно надо, и экономится не байт и не такт, а 10 байт и 40-50 тактов. Т.к. при их отсутствии, нам надо делать ветвление по условию и установку или сброс битов и ещё переход в противном случае.
---------- Post added at 22:10 ---------- Previous post was at 22:05 ----------
Еще не хватает команды ex bc,hl. Несколько раз нужна была, приходится извращаться
На самом деле, не хватает и всех остальных ex. Не только с 16-и битными парами. 8-и битные тоже бы пригодились, а что касается например SP. так там вообще минимум команд, а те, которые есть или жрут много или недостаточны. К примеру, совсем бы не помешал индексный режим адресации ко всем 16-и битным регистрам, когда можно было бы взять значение (SP-10h) или (SP+5). Как извратиться в Z80? Может знаток psb ответит? Без массы команд?
Vadim, не бузи. твой метеорит седня достали.
твой метеорит седня достали.
И?)))) Нет, по существу ответь? Ведь нужны-же команды, а?
Нет, по существу ответь?
по существу можно долго трепаться на тему, что z80 - уг. оно надо? какой есть, такой есть, а улучшать можно бесконечно. мне вот однотактовые команды подавай и регистров побольше и поширше.
Ну ведь есть оно (расширение) в том же Z-380. Там все EX есть, всё что пожелаешь и за разумную цену (имею ввиду совместимость и производительность). Да, 380 тоже УГ, по определённым причинам, но никто не мешает нам взять информационную модель, т.е. систему команд, к примеру, ещё её и улучшив, сделать новый проц. Для нашего нового любительского компа.
---------- Post added at 22:52 ---------- Previous post was at 22:49 ----------
Ведь мы это делаем только как "just fun". Не так ли? А не как коммерческий продукт, так почему бы и нет? А как коммерческий продукт, я не знаю... Уже ПЦ, как бы многие вендоры ставят его в угол. Типа ему пришёл конец. Я это услышал впервые 2 года назад. Всё, что нужно 99% пользователям планируют перенсти в "облако", а для доступа, сами знаете что.
NovaStorm
17.10.2013, 20:53
а что касается например SP
Вот кстати напомнил, сохранять SP можно только в память =(
А так хотелось в IY.
Представители HP мне официально заявили, что по их мнению эре ПЦ приходит конец. Что компы, как мы их видим умрут через 10, максимум через 15 лет. Останутся рабочие станции, т.е. компы те же, но на предприятиях. На которых будут крутиться приложения типа Solid Works, Acad, Catia, Unigraphix и т.д. И их PDM системы на серверах, пользователи же, будут юзать нечто вроде iPAD или подобных устройств, для доступа к своим данным и приложениям.
---------- Post added at 22:57 ---------- Previous post was at 22:57 ----------
Вот кстати напомнил, сохранять SP можно только в память =(
LD HL,0
ADD HL,SP
Ответ некорректен. Это - программа - последовательность команд, да ещё и влияющая на ОЗУ. Конечно, при определённых условиях она заменяет желаемую команду, но если ОЗУ использовать нельзя - то нет.
т.е. процедуры ПЗУ не используют стек? :) При отсутствии команд каждый извращается как может. Но лучше всего обходить такое заранее, чтобы потом глупо не получилось. Я в своём коде вообще Push/Pop не стараюсь не использовать в процедурах.
NovaStorm
17.10.2013, 21:29
Vadim, Увы оно тормознее LD SP,(nn) и уж тем более гипотетического LD HL,SP.
т.е. процедуры ПЗУ не используют стек?
Я пишу ПЗУ для Профика, в самом старте использовать ОЗУ нельзя, что бы его не портить, что бы была возможность чистого перехода в желаемый режим. И оно возможно.
Увы оно тормознее LD SP,(nn) и уж тем более гипотетического LD HL,SP.
При отсутствии ОЗУ, это единственная альтернатива. И при не желательности использовании оного. Или если мы не хотим привязываться к конкретным ячейкам. Кстати, в ПЗУ TRDOS это используется.
Ещё, как секрет, который на самом деле не секрет, могу сказать, что в ПЗУ мы можем использовать заранее заданный стек, который нам может помочь, в определённых моментах.
NovaStorm
17.10.2013, 21:58
У меня другая крайность - самомодифицирующийся код и SP скачет по всей памяти =)
но никто не мешает нам взять информационную модель, т.е. систему команд, к примеру, ещё её и улучшив, сделать новый проц.
так делают, например на фпга. только вот лично мне спек с 100мгц з80 (и тем более гибридом) не интересен. если мне нужна будет скорость, я просто возьму современный проц.
Представители HP мне официально заявили, что по их мнению эре ПЦ приходит конец.
они ошибаются. либо он приходит для них самих в этой сфере. а моё имхо - оно будет трансформироваться, но пк не исчезнут.
Barmaley_m
18.10.2013, 00:07
Ещё, как секрет, который на самом деле не секрет, могу сказать, что в ПЗУ мы можем использовать заранее заданный стек, который нам может помочь, в определённых моментах.
У Z80 на самом деле настолько много регистров, что на одних только регистрах можно делать довольно сложные программы. Существует множество тестов ОЗУ, рассчитанных на прошивку в ПЗУ. Они тестируют память и выводят на экран диагностические сообщения, даже если ОЗУ полностью неисправно, т.е. нет ни одной рабочей ячейки. Например, поскольку для реализации каждого из 8 бит оперативной памяти обычно используется отдельная микросхема - то при выходе из строя одной-двух таких микросхем ни одна ячейка ОЗУ не будет работоспособна, но прочитать с экрана диагностику все еще возможно. Также в таких тестах бывает вывод диагностики на бордюр или бипер.
Я сам делал такой тест. Очень увлекательная задача. Кстати, использовал и "заранее заданный стек", на котором хранилась цепочка возвратов из подпрограмм. Перед вызовом подпрограммы только приходилось устанавливать SP каждый раз на новую табличку. Таким образом возможно было вызывать даже вложенные подпрограммы.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot