Ассемблер UASM начал понимать Intel8080. Тестовый код. Спойлер Код (ASM): ;; include intel8080.asm .model tiny .data foo db 77h doo db 99h zoo dw 1234h .code org 100h start: $NOP $CALLPO M1 $MOV A,C $MOV A, [HL];,22 ;; $MOV [HL], [HL] $ADD A,D $ADD A, 0FFh $MOV BC, 01234h $MOV [DE], A $MOV A, doo $MOV foo, A $MOV HL, zoo $MOV zoo, HL $INC A $INC HL $INC SP $DEC A $DEC HL $DEC SP $PUSH AF $PUSH DE $POP AF $POP HL $ADD HL, DE $ADD HL, SP $RST 7 $JNZ M1 $NOP M1: $MOV SP, HL $XCHG HL, DE $XCHG DE, HL $XCHG HL, [SP] $XCHG [SP], HL $ROL A $ROR A $SHL A $SHR A db 08h, 10h, 18h, 38h, 0 db 0CBh, 0D9h, 0DDh, 0,0 db 0EDh, 0FDh, 0,1 $RET $JMP HL $LET HL:=zoo, A++, DE--, HL+=SP end start Просто пример, как UASM может понимать не только х86.
Это просто пример правильного понимания реализации ассемблера вообще. Ассемблер - это, структурный, процедурный, с элементами ООП, язык программирования. И он может быть универсальный как сам Си. --- Сообщение объединено, 26 дек 2020 --- Правильно реализованный ассемблер может заменить даже С++.
Intro, > Ассемблер - это, структурный, процедурный, с элементами ООП, язык программирования. Прежде такое тут никто не утверждал. Какое отношение имеет ооп к асм не понятно.
ООП - Объектно Ориентированное Программирования. И хороший ассемблер может его частично поддерживать. Прежде всего это вызов процедур по ссылке в виртуальной таблице. В UASM реализовано, эээ... Да хреново реализовано. Например, если в OpenGL это просто функции, то в DirectX это уже виртуальные функции COM. И для нормальной работы надо реализовать возможность эффективного вызова функций по ссылке в таблице. Вот и всё. Больше от ассемблера и не надо.
Где можно найти онлайн ассемблер 8080? С отладчиком и чтобы метки данные поддерживал, пару страниц Яндекс выдал какую-то хрень. То метки данных не понимает, то отладочных команд нет.
Ладно, вот код на моём ассемблере, решает задачку "Счастливые билеты" оптимизация = 0 Код (ASM): ; задача "Счастливые билеты" оптимизация = 0 ; (с) НаноБот 5.11.2023 .model tiny include ../intel8080.asm ;Используется мой ассемблер с синтаксисом intel x86 .data count dw 0 .code org 100h start: $MOV HL, 0 $MOV count, HL $MOV H, 10 ;L1 CYCLE1: $MOV L, 10 ;L2 CYCLE2: $PUSH HL $MOV B, 10 ;L3 CYCLE3: $MOV C, 10 ;R1 CYCLE4: $MOV D, 10 ;R2 CYCLE5: $MOV E, 10 ;R3 CYCLE6: $LET A:=H, A+=L, A+=D, H:=A ;H=L1+L2+L3 $LET A:=C, A+=D, A+=E ;A=R1+R2+R3 $CMP A, H $JNZ M1 ;if (H==A) $LET HL:=count, HL++, count:=HL M1: $INC E $JNZ CYCLE6 $INC D $JNZ CYCLE5 $INC C $JNZ CYCLE4 $INC B $JNZ CYCLE3 $POP HL $INC L $JNZ CYCLE2 $INC H $JNZ CYCLE1 $MOV HL, count $CALL 0FB78H ;печать HL с пробелом //монитор РАДИО-86РК $RET end start Проверить пока не получилось, но при 2МГц где-то 30-40 сек должно проработать. И да, там в intel8080.asm нашёл ошибку, я её исправил.
Так а ты глянь в виртуалке под досом, на 32х-битной винде (она умеет запускать 16-битные бинарники) или в досбоксе
HoShiMin, это intel8080 какой ещё досбокс?! По идеи надо на эмуляторе радио-86рк запустить, хотя это медленный БК, партнёр 01.01 быстрей, 2МГц и нет задержек по видеоконтролеру.
А, он же восьмибитный... Глянул, их ни Qemu, ни Bochs не умеет... Ну тогда да, только искать эмуляторы
Онлайн эмулятор радиошки. https://rk86.ru Только почему-то клава не работает. --- Сообщение объединено, 5 ноя 2023 --- Ошибок полно, вот версия точно должна работать. Код (ASM): ; задача "Счастливые билеты" оптимизация = 0 ; (с) НаноБот 5.11.2023 v0.01 .model tiny include ../intel8080.asm ;Используется мой ассемблер с синтаксисом intel x86 .data count dw 0 .code org 100h start: $MOV HL, 0 $MOV count, HL $MOV H, 10 ;L1 CYCLE1: $MOV L, 10 ;L2 CYCLE2: $MOV B, 10 ;L3 CYCLE3: $MOV C, 10 ;R1 CYCLE4: $MOV D, 10 ;R2 CYCLE5: $MOV E, 10 ;R3 CYCLE6: $PUSH HL $LET A:=H, A+=L, A+=D, H:=A ;H=L1+L2+L3 $LET A:=C, A+=D, A+=E ;A=R1+R2+R3 $CMP A, H $JNZ M1 ;if (H==A) $LET HL:=count, HL++, count:=HL M1: $POP HL $DEC E $JNZ CYCLE6 $DEC D $JNZ CYCLE5 $DEC C $JNZ CYCLE4 $DEC B $JNZ CYCLE3 $DEC L $JNZ CYCLE2 $DEC H $JNZ CYCLE1 $MOV HL, count $CALL 0FB78H ;печать HL с пробелом //монитор РАДИО-86РК $RET end start --- Сообщение объединено, 5 ноя 2023 --- Код (ASM): ; задача "Счастливые билеты" оптимизация = 0 ; (с) НаноБот 5.11.2023 v0.02 .model tiny include ../intel8080.asm ;Используется мой ассемблер с синтаксисом intel x86 .data count dw 0 .code org 100h start: $MOV HL, 0 $MOV count, HL $MOV H, 10 ;L1 CYCLE1: $MOV L, 10 ;L2 CYCLE2: $MOV B, 10 ;L3 CYCLE3: $MOV C, 10 ;R1 CYCLE4: $MOV D, 10 ;R2 CYCLE5: $MOV E, 10 ;R3 CYCLE6: $PUSH HL $LET A:=H, A+=L, A+=B, H:=A ;H=L1+L2+L3 $LET A:=C, A+=D, A+=E ;A=R1+R2+R3 $CMP A, H $JNZ M1 ;if (H==A) $LET HL:=count, HL++, count:=HL M1: $POP HL $DEC E $JNZ CYCLE6 $DEC D $JNZ CYCLE5 $DEC C $JNZ CYCLE4 $DEC B $JNZ CYCLE3 $DEC L $JNZ CYCLE2 $DEC H $JNZ CYCLE1 $MOV HL, count $CALL 0FB78h ;печать HL с пробелом //монитор РАДИО-86РК $CALL 0F86CH ;выход в ОС end start Заработал код(в 0.01 была ошибка), там эмулятор немного странно работает, но код я запустил. Вернуло D7D4, а проработало 54 сек, ну Партнёр 01.01 побыстрей бы подсчитал, может за 40 сек бы справился.
Я бы к A сперва L сложил, а R бы вычитал, так на команду сравнения и перекладок будет меньше. Инкремент count тоже тоже сделал бы однобайтовыми LD A,(count): INC A: LD,(count): JNZ skip_high_count_incr: ... тогда push/pop не нужно будет в ядре цикла наматывать, вроде должно стать быстрее. В восьмибитках чем восьмибитестее, тем бывает лучше.
aa_dav, count у нас word, т.е. unsigned short. Возможно этот алго можно и быстрей скомпилировать в 8080, но как есть. Оптимизация = 1 Код (ASM): $LET HL:=0, count:=HL, B:=0 ;sum_l $LET HL:=&L1, [HL]:=10 CYCLE1: $LET HL:=&L2, [HL]:=10 CYCLE2: $LET HL:=&L3, [HL]:=10 CYCLE3: $LET HL:=&R1, [HL]:=10, C:=0 ;sum_r CYCLE4: $MOV D, 10 ;R2 CYCLE5: $MOV E, 10 ;R3 $MOV A, B CYCLE6: $CMP A, C $JNZ M1 ;if (sum_l==sum_r) $LET HL:=count, HL++, count:=HL M1: $INC C $DEC E $JNZ CYCLE6 $LET A:=C, A-=9, C:=A $DEC D $JNZ CYCLE5 $LET A:=C, A-=9, C:=A $LET HL:=&R1, [HL]-- $JNZ CYCLE4 $LET B++, HL:=&L3, [HL]-- $JNZ CYCLE3 $LET A:=B, A-=9, B:=A $LET HL:=&L2, [HL]-- $JNZ CYCLE2 $LET A:=B, A-=9, B:=A $LET HL:=&L1, [HL]-- $JNZ CYCLE1 $MOV HL, count $CALL 0FB78h ;печать HL с пробелом //монитор РАДИО-86РК $CALL 0F86CH ;выход в ОС Этот код проработал уже 26 секунд, опять немного переделал intel8080.asm
В этом и прикол - мы сперва увеличиваем нижний байт пары, и если в результате не получился 0, то пропускаем инкремент верхней пары. Если же получился 0, то значит надо перенести флаг переноса в верхнюю пару и тогда один раз на 256 инкрементов запускается код по инкременту верхней пары (я его не приводил целиком, а обозначил через JNZ skip_high_count_incr). Эта стратегия неизбежна на таком монстре 8-битности как MOS 6502, но и в тяготеющем к указателям и 16-битным сложениям i8080/Z80 она продолжает быть актуальной во многих случаях. Изначальный код легко избавляется от push/pop таким образом и становится 8-битным без значимых пенальти, а наоборот с выгодой.
8080 частично 16 битный процессор, есть советский КР580ВМ1, там кроме DAD есть ещё HL-=reg16 и CMP HL, reg16 что здорово помогает с 16 битной арифметикой, так же подобные расширения есть в 8085 и Z80. Код (ASM): ;sum_l:B, sum_r:C $LET HL:=0, count:=HL, B:=0 $LET HL:=&L1, [HL]:=10 CYCLE1: $LET HL:=&L2, [HL]:=10 CYCLE2: $LET HL:=&L3, [HL]:=10 CYCLE3: $LET C:=0 CYCLE4: $LET A:=B, A++, A-=C $JM M1 $JZ M1 ;if(a>0) $CMP A, 20 $JP M1 ;if(a<20) $LET HL:=count, E:=A, D:=0, HL+=DE, A-=10 $JM M2 $JZ M2 ;if(a>0) $LET A+=A, A^=0FFh, E:=A, D:=0FFh, HL+=DE, HL++ M2: $LET count:=HL M1: $LET C++, A:=C $CMP A, 10 $JM CYCLE4 $LET B++, HL:=&L3, [HL]-- $JNZ CYCLE3 $LET A:=B, A-=9, B:=A $LET HL:=&L2, [HL]-- $JNZ CYCLE2 $LET A:=B, A-=9, B:=A $LET HL:=&L1, [HL]-- $JNZ CYCLE1 Этот код уже меньше секунды. Хорошо бы формат rkp разобрать, чтобы ассемблер UASM сразу мог их генерировать, новою версию Emu80 скачал. Давно мечтал сделать похожий ассемблер, ещё лет 25-30 назад.
Про то из каких корней вырос i8080 писал и тут тоже: https://wasm.in/threads/kratkij-obz...mikroprocessorov-semejstvo-intel-zilog.34395/ А вот какими наследниками оброс Z80 уже сюда не перетаскивал, но тоже есть: https://hype.retroscene.org/blog/964.html 24-битные АЛУ это всё-таки прикольно...
Ещё немного забавного кода. Код (ASM): $LET HL:=0 $PUSH HL $LET A:=0, H:=10 ;L1 CYCLE1: $MOV L, 10 ;L2 CYCLE2: $MOV B, 10 ;L3 CYCLE3: $MOV C, 10 ;R1 CYCLE4: $MOV D, 10 ;R2 CYCLE5: $MOV E, 10 ;R3 CYCLE6: ;if (A==0){ $AND A, A $JNZ M1 $LET HL~~[SP], HL++, [SP]~~HL M1:;} $LET A--, E-- $JNZ CYCLE6 $LET A+=9, D-- $JNZ CYCLE5 $LET A+=9, C-- $JNZ CYCLE4 $LET A+=1+10, B-- $JNZ CYCLE3 $LET A-=9, L-- $JNZ CYCLE2 $LET A-=9, H-- $JNZ CYCLE1 $POP HL Использую все регистры, и только count на верхушке стека. Оператор ~~ это у меня обмен. На радиошке 32 сек, партнёр должен 20 сек управиться. В Аккумуляторе сумма L1+L2+L3-R1-R2-R3 intel8080.asm потом выложу.
aa_dav, команды и тайминги 8080 таковы что для word'ов лучше использовать эти 16 битные команды. А то смотришь на это. Код (ASM): MOV A,E ;Заносим младшую часть множимого в аккумулятор ORA A ;Сбрасываем флаг С RAL ;Сдвигаем младшую часть множимого влево MOV E,A ;Возвращаем ее на место MOV A,D ;Заносим старшую часть множимого в аккумулятор RAL ;Сдвигаем старшую часть множимого влево MOV D,A ;Возвращаем ее на место И понимаешь можно сделать так. $LET HL~~DE, HL+=HL, DE~~HL ;DE*=2 Не задействован аккумулятор, и выполняется довольно быстро 4+10+4=18 тактов. А код выше 5+4+4+5+5+4+5=32 такта. Нормально так, и что, 8080 разве не частично 16 битный? У КР580ВМ1 есть ещё DSUB и DCMP для сравнения BC/DE, что ещё больше делает его 16 битным.
Это если они чисто технически не начинают портить другие регистры и мешаться поэтому под ногами. В коде который я комментировал в центре цикла безусловно крутились два push/pop чтобы обеспечивать в том числе этот инкремент. Но инкремент происходит далеко не каждую итерацию и вынос его в байтовые команды мог наоборот помочь ускорить код - опять таки действительно надо по тактам смотреть, но по моим прикидкам так бы и было (сами однобайтовые команды, напомню, инкрементируя нижний байт только в одном из 256 случаев производят инкремент верхнего байта, т.е. их растактовка опять таки очень редко делает двойное обращение к памяти). Впрочем вынос count в вершину стека через ex hl,(sp) действительно еще круче.