Привет, спектрумисты,
Вы читаете очередной номер дискмагазина Restore и, наверное, удивляетесь, что общего у него с трёхрегистровым процессором 6502. Когда-то в 2004 году я сделал эмулятор Apple I для ZX Spectrum. Частью этого эмулятора были и дизассемблер, и простой ассемблер кода для процессора 6502. О нём я написал серию статей ещё в 2005 году. А что насчёт самого ядра эмулятора? Код и исходник открыты. Если поймёте его так, что сможете использовать в собственной программе, — пользуйтесь: ничто и никто вам в этом не мешает.
Почти двадцать лет, однако, ушло на то, чтобы достать исходник со старого ноутбука. Он был написан в русском ассемблере ZXASM 3.0 для Betadisk в эмуляторе X128 под MS-DOS.
Теперь у нас есть исходник в человекочитаемом виде — правда, как у меня было принято с Prometheus, комментариями я особо не баловался, и понять его было бы, пожалуй, трудновато. Поэтому снабжаю его поясняющим текстом.
Большая часть кода не зависит от hardware, так что эмулятор сравнительно легко переносим на разные Z80-платформы. От hardware зависит менеджер отдельных эмулируемых процессорных циклов. А именно: после вызова выполнения одного процессорного цикла (CALL INSTRUCTION) он читает клавиатуру, прыгает в меню, эмулирует нажатие аппаратных кнопок — RESET, а у Apple I ещё и аппаратную очистку экрана. Также при необходимости вызывает вывод содержимого регистров и обслуживает его включение или выключение. Вызывает внешнюю рутину INKEY, которая читает клавиатуру, и рутины в модуле MONITOR, который содержит главное меню эмулятора с уже упомянутыми ассемблером и дизассемблером. Содержит и рутину MONITOR для вывода содержимого регистров. Та начинается перезаписываемой инструкцией — либо RET, когда вывод регистров не выполняется, либо NOP, когда рутина вывода исполняется.
========================
| 6502 Virtual Machine |
; CYCLE MANAGER HW dependent
; INSTR. CYCLE HW independent
; 6502 CORE HW independent
; REGISTERS HW independent
======================
| 6502 CYCLE MANAGER |
; HW dependent ;uses keyboard ;uses monitor
cycle call instruction
call inkey or a:jp z,nomkey cp 8:jr z,oneinstr cp 9:jr z,cycleinstr cp 15:jr z,hwclrscr cp 7:jp z,reset cp 4:jr z,monitoroff cp 5:jr z,monitoron cp 10:jp z,menudown cp 11:jp z,menuup cp 6:call z,caps nomkey retmonitor call monitor ld a,(iy+48):ld (23232),a ;CAPS jp cycle
monitoron xor a:ld (monitor),a ld hl,23264:ld de,23265 ld (hl),%001111:ld bc,31:ldir jr retmonitor monitoroff ld a,201:ld (monitor),a ld hl,23264:ld de,23265 ld (hl),%001001:ld bc,31:ldir jr retmonitor hwclrscr res 5,(iy+1) call clearscreen jr retmonitor
oneinstr ld a,201:ld (instruction),a res 5,(iy+1) call step jp monitoron cycleinstr xor a:ld (instruction),a res 5,(iy+1) jp retmonitor
Теперь мы в части, которая сама по себе была аппаратно независимой, но вызывает две внешние аппаратно зависимые рутины, которые я ещё подробнее опишу. К тому же я уже начал не вполне системно добавлять в неё рутины, хоть и независимые от hardware, но специфичные для данного эмулируемого компьютера: по адресам C170, C18D и C163 находятся входы в рутины обслуживания магнитофона на Apple I. То есть если эмулируемый регистр PC содержит значения C170, C18D или C163, выполняются переходы на рутины TAPEW для записи, TAPER для чтения, а TAPEEOL — выходная точка.
Первая инструкция обработки инструционного цикла — NOP или RET. Эту инструкцию меняет уже описанный менеджер процессорных циклов. Если здесь NOP, эмулируемые процессорные циклы выполняются нормально. Если здесь RET, ничего не выполняется: эмулируемый процессор стоит, и менеджер лишь читает управляющие клавиши. Вызовом с адреса STEP каждый раз выполняется эмуляция одной инструкции.
В первой части — декодирование инструкции: если не выполняется код из ROM кассетного интерфейса, с адреса, заданного эмулируемым регистром PC, читается код инструкции, и в таблице TABLE ищется адрес, по которому лежит рутина выполнения инструкции с прочитанным кодом.
=====================
| 6502 INSTR. CYCLE |
; HW independent
;uses memory manager
instruction nop ;RET disables run step ld a,(regpc+1):cp #c1 call z,tapepoints call step1 jp param ;inc PC step1 ld hl,(regpc):call loada ld de,table:ld h,0:ld l,a add hl,hl add hl,de ld a,(hl):ld (jump+1),a inc hl:ld a,(hl):ld (jump+2),a jump jp 0
tapepoints ld a,(regpc) cp #70:jp z,tapew cp #8d:jp z,taper cp #63:jp z,tapeeol ret
Пора упомянуть о рутинах LOADA и STOREA, которые, по сути, служат эмулируемому процессору для общения с окружающим миром. Обе аппаратно зависимы и не входят в эту распечатку. В чём суть? Они обслуживают виртуальное адресное пространство эмулируемого процессора 6502. У него нет разделённых портов и памяти: по сути все периферии «отображены в память» в общем 64 КиБ пространстве.
Обрабатываемый адрес — в регистре HL процессора Z80, записываемое или прочитанное значение — в аккумуляторе A процессора Z80. LOADA и STOREA могут быть, в зависимости от сложности hardware эмулируемого компьютера, довольно комплексными. Они обеспечивают перевод адресов 6502 в адреса Z80, при необходимости — страничание памяти в случае ZX Spectrum 128 (например, мой эмулятор Apple I на ZX 48 эмулирует 16 КиБ RAM, тогда как на ZX 128 с помощью страничания — 32 КиБ RAM). И точно так же обеспечивают связь с периферией (чтение клавиатуры, обслуживание регистров разных чипов — графических, звуковых, ...). Поскольку у Apple I нет VideoRAM, а общение с дисплеем идёт через порт терминала, мой эмулятор не решал эмуляцию графического чипа и вычитку VideoRAM — только запись на терминал.
А теперь наступает само аппаратно независимое ядро; оно само использует только рутины LOADA и STOREA.
«Нелегальные» инструкции и NOP ничего не делают — даже задержки: я рассчитывал, что сама эмуляция будет настолько медленной, что ничего такого не понадобится.
Названия по большей части понятно указывают, какая инструкция обрабатывается в данной рутине. Вызовы рутин PARAM8 и PARAM16 вызывают чтение восьмибитного или 16-битного параметра инструкции.
Начнём с инструкций загрузки регистров.
=================
| 6502 CORE |
ilg noop ret
tax ld a,(rega) t_x ld (regx),a ld (data),a call negative jp zeroa
tay ld a,(rega) t_y ld (regy),a ld (data),a call negative jp zeroa
txa ld a,(regx) t_a ld (rega),a ld (data),a call negative jp zeroa
tya ld a,(regy) jp t_a
tsx ld a,(regs) jp t_x
txs ld a,(regx) ld (regs),a ret
ldak call param8 jp t_a
ldam call param16 call loada jp t_a
ldamx call param16 call addx16 call loada jp t_a ldamy call param16 call addy16 call loada jp t_a
ldaz call param8 ld l,a:ld h,0:call loada jp t_a
ldazx call param8 ld l,a:ld h,0 call addx8 call loada jp t_a
ldaix call param8 ld l,a:ld h,0 call addx8 call paramind call loada jp t_a
ldaiy call param8 ld l,a:ld h,0 call paramind call addy16 call loada jp t_a
ldxk call param8 jp t_x
ldxm call param16 call loada jp t_x
ldxmy call param16 call addy16 call loada jp t_x
ldxz call param8 ld l,a:ld h,0:call loada jp t_x
ldxzy call param8 ld l,a:ld h,0 call addy8 call loada jp t_x
ldyk call param8 jp t_y
ldym call param16 call loada jp t_y
ldymx call param16 call addx16 call loada jp t_y
ldyz call param8 ld l,a:ld h,0:call loada jp t_y
ldyzx call param8 ld l,a:ld h,0 call addx8 call loada jp t_y
stam call param16 ld a,(rega) call storea ret
stamx call param16 call addx16 ld a,(rega) call storea ret
stamy call param16 call addy16 ld a,(rega) call storea ret
staz call param8 ld l,a:ld h,0:ld a,(rega) call storea ret
stazx call param8 ld l,a:ld h,0 call addx8 ld a,(rega) call storea ret
staix call param8 ld l,a:ld h,0 call addx8 call paramind ld a,(rega) call storea ret
staiy call param8 ld l,a:ld h,0 call paramind call addy16 ld a,(rega) call storea ret
stxm call param16 ld a,(regx) call storea ret
stxz call param8 ld l,a:ld h,0:ld a,(regx) call storea ret
stxzy call param8 ld l,a:ld h,0 call addy8 ld a,(regx) call storea ret
stym call param16 ld a,(regy) call storea ret
styz call param8 ld l,a:ld h,0:ld a,(regy) call storea ret
styzx call param8 ld l,a:ld h,0 call addx8 ld a,(regy) call storea ret
pha ld a,(rega) ld hl,(regsp) ld (data),a call storea call pushni call negativea:jp zeroa
php ld a,(regp) ld hl,(regsp) call storea call pushni ret
pla call popni ld hl,(regsp) call loada ld (rega),a ld (data),a call negativea:jp zeroa
plp call popni ld hl,(regsp) call loada ld (regp),a ret
pushni ld a,(regs):dec a ld (regs),a:ret popni ld a,(regs):inc a ld (regs),a:ret
jmpk call param16 dec hl ld (regpc),hl ret
jmpm call param16 push hl call loada ld (adr),a pop hl inc hl call loada ld (adr+1),a ld hl,(adr) dec hl ld (regpc),hl ret
jsr call param16 ld a,(regpc+1) ld hl,(regsp) call storea call pushni ld a,(regpc) ld hl,(regsp) call storea call pushni ld hl,(adr) dec hl ld (regpc),hl ret
rts call popni ld hl,(regsp) call loada ld (regpc),a call popni ld hl,(regsp) call loada ld (regpc+1),a ret
brk call param ld a,(regpc+1) ld hl,(regsp) call storea call pushni ld a,(regpc) ld hl,(regsp) call storea call pushni call php ld hl,#fffe call loada ld (adr),a ld hl,#ffff call loada ld (adr+1),a ld hl,(adr) ld (regpc),hl call setb ret
rti call plp jp rts
beq call param8 ld (relparam),a call tstz ret z relcom ld a,(relparam) bit 7,a jr nz,relback relfwd ld hl,(regpc) ld e,a ld d,0 add hl,de ld (regpc),hl ret relback xor #ff ld hl,(regpc) ld e,a ld d,0 scf sbc hl,de ld (regpc),hl ret relparam nop
bne call param8 ld (relparam),a call tstz ret nz jp relcom
bmi call param8 ld (relparam),a call tstn ret z jp relcom
bpl call param8 ld (relparam),a call tstn ret nz jp relcom
bcs call param8 ld (relparam),a call tstc ret z jp relcom
bcc call param8 ld (relparam),a call tstc ret nz jp relcom
bvs call param8 ld (relparam),a call tstv ret z jp relcom
bvc call param8 ld (relparam),a call tstv ret nz jp relcom
adck call param8 adccom ld (data),a call tstd jp z,adcnd ld a,39:ld (adcdec),a ;DAA adcnd call tstc ld a,(data) ld b,a jr z,adcnocarry scf:jp adcc adcnocarry scf:ccf adcc ld a,(rega) adc a,b adcdec nop ld (rega),a push af call carry pop af call flow ld a,(rega):call negative ld a,(rega):call zero xor a:ld (adcdec),a:ret
adcm call param16 call loada jp adccom adcmx call param16 call addx16 call loada jp adccom adcmy call param16 call addy16 call loada jp adccom adcz call param8 ld l,a:ld h,0:call loada jp adccom adczx call param8 ld l,a:ld h,0 call addx8 call loada jp adccom adcix call param8 ld l,a:ld h,0 call addx8 call paramind call loada jp adccom adciy call param8 ld l,a:ld h,0 call paramind call addy16 call loada jp adccom
sbck call param8 sbccom ld (data),a call tstd jp z,sbcnd ld a,39:ld (sbcdec),a ;DAA sbcnd ld a,(data):ld b,a call tstc jr z,sbcnocarry scf:ccf:jp sbcc ;~CARRY sbcnocarry scf ;~CARRY sbcc ld a,(rega) sbc a,b sbcdec nop push af ld (rega),a ccf call carry pop af call flow ld a,(rega):call negative ld a,(rega):call zero xor a:ld (sbcdec),a:ret
sbcm call param16 call loada jp sbccom sbcmx call param16 call addx16 call loada jp sbccom sbcmy call param16 call addy16 call loada jp sbccom sbcz call param8 ld l,a:ld h,0:call loada jp sbccom sbczx call param8 ld l,a:ld h,0 call addx8 call loada jp sbccom sbcix call param8 ld l,a:ld h,0 call addx8 call paramind call loada jp sbccom sbciy call param8 ld l,a:ld h,0 call paramind call addy16 call loada jp sbccom
incz call param8 ld h,0:ld l,a incc ld (adr),hl call loada inc a ld (data),a ld hl,(adr) call storea call negativea jp zeroa inczx call param8 ld h,0:ld l,a call addx8 jp incc incm call param16 jp incc incmx call param16 call addx16 jp incc
inx ld a,(regx) inc a ld (regx),a ld (data),a call negative jp zeroa
iny ld a,(regy) inc a ld (regy),a ld (data),a call negative jp zeroa
decz call param8 ld h,0:ld l,a decc ld (adr),hl call loada dec a ld (data),a ld hl,(adr) call storea call negativea jp zeroa deczx call param8 ld h,0:ld l,a call addx8 jp decc decm call param16 jp decc decmx call param16 call addx16 jp decc
dex ld a,(regx) dec a ld (regx),a ld (data),a call negative jp zeroa
dey ld a,(regy) dec a ld (regy),a ld (data),a call negative jp zeroa
asla ld a,(rega) sla a ld (data),a call carry ld a,(data) ld (rega),a call negative jp zeroa
aslz call param8 ld h,0:ld l,a ld (adr),hl call loada sla a ld (data),a call carry ld a,(data) ld hl,(adr) call storea call negativea jp zeroa
aslzx call param8 ld h,0:ld l,a call addx8 ld (adr),hl call loada sla a ld (data),a call carry ld a,(data) ld hl,(adr) call storea call negativea jp zeroa
aslm call param16 ld (adr),hl call loada sla a ld (data),a call carry ld a,(data) ld hl,(adr) call storea call negativea jp zeroa
aslmx call param16 call addx16 ld (adr),hl call loada sla a ld (data),a call carry ld a,(data) ld hl,(adr) call storea call negativea jp zeroa
lsra ld a,(rega) srl a ld (data),a call carry ld a,(data) ld (rega),a call negative jp zeroa
lsrz call param8 ld h,0:ld l,a ld (adr),hl call loada srl a ld (data),a call carry ld a,(data) ld hl,(adr) call storea call negativea jp zeroa
lsrzx call param8 ld h,0:ld l,a call addx8 ld (adr),hl call loada srl a ld (data),a call carry ld a,(data) ld hl,(adr) call storea call negativea jp zeroa
lsrm call param16 ld (adr),hl call loada srl a ld (data),a call carry ld a,(data) ld hl,(adr) call storea call negativea jp zeroa
lsrmx call param16 call addx16 ld (adr),hl call loada srl a ld (data),a call carry ld a,(data) ld hl,(adr) call storea call negativea jp zeroa
andk call param8 andc ld b,a ld a,(rega) and b ld (rega),a ld (data),a call negative jp zeroa andz call param8 ld h,0:ld l,a call loada jp andc andzx call param8 ld h,0:ld l,a call addx8 call loada jp andc andm call param16 call loada jp andc andmx call param16 call addx16 call loada jp andc andmy call param16 call addy16 call loada jp andc andix call param8 ld h,0:ld l,a call addx8 call paramind call loada jp andc andiy call param8 ld h,0:ld l,a call paramind call addy16 call loada jp andc
orak call param8 orac ld b,a ld a,(rega) or b ld (rega),a ld (data),a call negative jp zeroa oraz call param8 ld h,0:ld l,a call loada jp orac orazx call param8 ld h,0:ld l,a call addx8 call loada jp orac oram call param16 call loada jp orac oramx call param16 call addx16 call loada jp orac oramy call param16 call addy16 call loada jp orac oraix call param8 ld h,0:ld l,a call addx8 call paramind call loada jp orac oraiy call param8 ld h,0:ld l,a call paramind call addy16 call loada jp orac
eork call param8 eorc ld b,a ld a,(rega) xor b ld (rega),a ld (data),a call negative jp zeroa eorz call param8 ld h,0:ld l,a call loada jp eorc eorzx call param8 ld h,0:ld l,a call addx8 call loada jp eorc eorm call param16 call loada jp eorc eormx call param16 call addx16 call loada jp eorc eormy call param16 call addy16 call loada jp eorc eorix call param8 ld h,0:ld l,a call addx8 call paramind call loada jp eorc eoriy call param8 ld h,0:ld l,a call paramind call addy16 call loada jp eorc
rola ld a,(rega) ld b,a call rolb ld (rega),a
rolb call tstc jr nz,rolacs scf ccf jp rolac rolacs scf rolac ld a,b rla ld b,a call carry ld a,b:ret
rolz call param8 ld h,0:ld l,a rolzc ld (adr),hl call loada ld b,a:call rolb ld hl,(adr) call storea ret
rolzx call param8 ld h,0:ld l,a call addx8 jp rolzc
rolm call param16 jp rolzc
rolmx call param16 call addx16 jp rolzc
rora ld a,(rega) ld b,a call rorb ld (rega),a
rorb call tstc jr nz,roracs scf ccf jp rorac roracs scf rorac ld a,b rra ld b,a call carry ld a,b:ret
rorz call param8 ld h,0:ld l,a rorzc ld (adr),hl call loada ld b,a:call rorb ld hl,(adr) call storea ret
rorzx call param8 ld h,0:ld l,a call addx8 jp rorzc
rorm call param16 jp rorzc
rormx call param16 call addx16 jp rorzc
clc jp resc sec jp setc cld jp resd sed jp setd cli jp resi sei jp seti clv jp resv
cmpk call param8 cmpc ld b,a ld a,(rega) cmpr sub b ld (data),a ccf call carry call negativea jp zeroa
cmpz call param8 ld h,0:ld l,a call loada jp cmpc
cmpzx call param8 ld h,0:ld l,a call addx8 call loada jp cmpc
cmpm call param16 call loada jp cmpc cmpmx call param16 call addx16 call loada jp cmpc cmpmy call param16 call addy16 call loada jp cmpc cmpix call param8 ld h,0:ld l,a call addx8 call paramind call loada jp cmpc cmpiy call param8 ld h,0:ld l,a call paramind call addy16 call loada jp cmpc
cpxk call param8 ld b,a ld a,(regx) jp cmpr cpxz call param8 ld h,0:ld l,a call loada ld b,a ld a,(regx) jp cmpr cpxm call param16 call loada ld b,a ld a,(regx) jp cmpr cpyk call param8 ld b,a ld a,(regy) jp cmpr cpyz call param8 ld h,0:ld l,a call loada ld b,a ld a,(regy) jp cmpr cpym call param16 call loada ld b,a ld a,(regy) jp cmpr
bitz call param8 ld h,0:ld l,a bitcomm call loada ld (data),a and %01000000 jr z,bitcorv call setv bitcov call negativea ld a,(rega) and (data) jp zero bitcorv call resv:jp bitcov
bitm call param16 jp bitcomm
===============================
| END OF CORE INSTRUCTION SET |
Следуют рутины для считывания параметров за инструкцией, рутины для обработки косвенных и индексных параметров — прибавление восьмибитного или 16-битного числа к эмулируемому регистру X или Y.
param ld hl,(regpc) inc hl ld (regpc),hl ret param8 call param call loada ret param16 call param call loada ld (adr),a call param call loada ld (adr+1),a ld hl,(adr) ret paramind push hl call loada ld (adr),a pop hl:inc hl call loada ld (adr+1),a ld hl,(adr) ret addx8 ld a,(regx) add a,l:ld l,a ret addx16 ld a,(regx) ld e,a:ld d,0 add hl,de:ret addy8 ld a,(regy) add a,l:ld l,a ret addy16 ld a,(regy) ld e,a:ld d,0 add hl,de:ret
Здесь затем пространство, где хранятся эмулируемые регистры. Восьмибитный стек REGS расширен до 16-битного регистра REGSP. Преднастроены регистр REGPC и флаги REGP на исходные значения, остальные регистры нулевые.
Потом следуют рутины для работы с флагами. ADDR и DATA — два временных хранилища 16-битного и 8-битного значения.
==================
| 6502 REGISTERS |
rega nop regx nop regy nop regp db %00100010 regsp regs nop db 1 regpc dw #ff00
negativea ld a,(data) negative and %10000000 jr z,resn jp setn
carry jr c,setc jp resc
flow jp po,resv jp setv
zeroa ld a,(data) zero or a jr z,setz jp resz
setc ld d,%1 jp setcom setz ld d,%10 jp setcom seti ld d,%100 jp setcom setd ld d,%1000 jp setcom setb ld d,%10000 jp setcom setv ld d,%1000000 jp setcom setn ld d,%10000000 setcom ld a,(regp) or d ld (regp),a ret resc ld d,%11111110 jp rescom resz ld d,%11111101 jp rescom resi ld d,%11111011 jp rescom resd ld d,%11110111 jp rescom resb ld d,%11101111 jp rescom resv ld d,%10111111 jp rescom resn ld d,%01111111 rescom ld a,(regp) and d ld (regp),a ret tstz ld d,%00000010 jp tstcom tstn ld d,%10000000 jp tstcom tstc ld d,%00000001 jp tstcom tstd ld d,%00001000 jp tstcom tstv ld d,%01000000 tstcom ld a,(regp) and d ret
adr nop:nop data nop
Следует таблица инструкций. Как единственная, она выровнена на 256-байтную «страницу» и содержит попросту только 16-битные адреса рутин выполнения инструкций, упорядоченных по возрастанию. Недокументированные инструкции не эмулируются, их код помечен ILG.
===================
| T A B L E S |
org $/256+1*256
table dw brk,oraix,ilg,ilg dw ilg,oraz,aslz,ilg dw php,orak,asla,ilg dw ilg,oram,aslm,ilg
dw bpl,oraiy,ilg,ilg dw ilg,orazx,aslzx,ilg dw clc,oramy,ilg,ilg dw ilg,oramx,aslmx,ilg
dw jsr,andix,ilg,ilg dw bitz,andz,rolz,ilg dw plp,andk,rola,ilg dw bitm,andm,rolm,ilg
dw bmi,andiy,ilg,ilg dw ilg,andzx,rolzx,ilg dw sec,andmy,ilg,ilg dw ilg,andmx,rolmx,ilg
dw rti,eorix,ilg,ilg dw ilg,eorz,lsrz,ilg dw pha,eork,lsra,ilg dw jmpk,eorm,lsrm,ilg
dw bvc,eoriy,ilg,ilg dw ilg,eorzx,lsrzx,ilg dw cli,eormy,ilg,ilg dw ilg,eormx,lsrmx,ilg
dw rts,adcix,ilg,ilg dw ilg,adcz,rorz,ilg dw pla,adck,rora,ilg dw jmpm,adcm,rorm,ilg
dw bvs,adciy,ilg,ilg dw ilg,adczx,rorzx,ilg dw sei,adcmy,ilg,ilg dw ilg,adcmx,rormx,ilg
dw ilg,staix,ilg,ilg dw styz,staz,stxz,ilg dw dey,ilg,txa,ilg dw stym,stam,stxm,ilg
dw bcc,staiy,ilg,ilg dw styzx,stazx,stxzy,ilg dw tya,stamy,txs,ilg dw ilg,stamx,ilg,ilg
dw ldyk,ldaix,ldxk,ilg dw ldyz,ldaz,ldxz,ilg dw tay,ldak,tax,ilg dw ldym,ldam,ldxm,ilg
dw bcs,ldaiy,ilg,ilg dw ldyzx,ldazx,ldxzy,ilg dw clv,ldamy,tsx,ilg dw ldymx,ldamx,ldxmy,ilg
dw cpyk,cmpix,ilg,ilg dw cpyz,cmpz,decz,ilg dw iny,cmpk,dex,ilg dw cpym,cmpm,decm,ilg
dw bne,cmpiy,ilg,ilg dw ilg,cmpzx,deczx,ilg dw cld,cmpmy,ilg,ilg dw ilg,cmpmx,decmx,ilg
dw cpxk,sbcix,ilg,ilg dw cpxz,sbcz,incz,ilg dw inx,sbck,noop,ilg dw cpxm,sbcm,incm,ilg
dw beq,sbciy,ilg,ilg dw ilg,sbczx,inczx,ilg dw sed,sbcmy,ilg,ilg dw ilg,sbcmx,incmx,ilg
Share your thoughts about the article