; xasm 2.6.1 ; by Piotr Fusik ; - No more "Arithmetic overflow" and "Division by zero" errors when correctly using forward-referenced labels ; (bug found by Marcin Lewandowski) ; - The following now assembles: ; ift 0 ; foo equ 1 ; ift foo ; eif ; eif ; (bug found by Adrian Matoga) ; - Issue errors for non-existing INC @ and DEC @ ; - Negative numbers fixed in the listing EXE = 1 ; EXE vs COM, not sure if COM still works COMPAK = 0 ; 1d00h, only if COM SET_WIN_TITLE = 0 ; modify title of the console window (lame!) LABELS_32 = 1 ; 32-bit labels FOUR_ZEROS_TO_SPACES = 1 ; make hex representation more readable - 4 digits for 16-bit values POOR_MAN_MAKE = 0 ; check modification times of the main source file and the object file and skip assembly if unnecessary CONVERT_TO_TABS = 0 ; compress listing with tabs (disable with /s) LONG_FILE_NAMES = 1 ; use Win32 long filenames interface if available RELOC_ORG = 1 ; support org r: FUNCTIONS = 0 ; support functions in expressions IDEAL P386 IF EXE MODEL SMALL ELSE MODEL TINY ENDIF CODESEG l_icl = 1024 l_org = 4096 l_def = 1024 IF EXE l_lab = 53000 ELSE l_lab = 48000 ENDIF STRUC com c_code db ? c_flag db ? c_name db ?,?,? c_vec dw ? ENDS STRUC icl prev dw ? handle dw ? line dd ? flags db ? m_eofl = 1 nam db ? ENDS STRUC lab IF LABELS_32 l_val dd ? ELSE l_val dw ? b_sign = 7 m_sign = 80h ENDIF flags db ? m_lnus = 40h m_ukp1 = 20h len db ? nam db ? ENDS STRUC movt m_lcod db ? m_lvec dw ? m_scod db ? m_svec dw ? m_inc db ? m_dec db ? ENDS ;[flags] m_pass = 1 m_norg = 2 m_rorg = 4 m_rqff = 8 b_hdr = 4 m_hdr = 10h m_pair = 20h m_repa = 40h b_skit = 7 m_skit = 80h b_enve = 8 m_enve = 100h m_wobj = 200h m_times = 400h m_first = 800h m_5200 = 1000h m_repl = 2000h b_ski2 = 14 m_ski2 = 4000h b_def = 15 m_def = 8000h ;[swits] m_swc = 1 m_swd = 2 m_swe = 4 m_swi = 8 m_swl = 10h IF POOR_MAN_MAKE b_swn = 5 m_swn = 20h m_swo = 40h ELSE m_swo = 20h ENDIF m_swp = 2*m_swo m_swq = 2*m_swp IF CONVERT_TO_TABS m_sws = 2*m_swq m_swt = 2*m_sws ELSE m_swt = 2*m_swq ENDIF m_swu = 2*m_swt ;[flist] m_lsti = 8 m_lstl = 10h m_lsto = 20h m_lsts = m_lsto+m_lstl+m_lsti ; [fillfl] m_fillen = 1 ; fill enabled m_fillpo = 2 ; fill possible b_fillrq = 2 ; fill requested m_fillrq = 4 nhand = -1 ;null handle STDERR = 2 cr equ 13 eol equ 13,10 eot equ 13,10,'$' MACRO lda _rg ;shorter than 'mov (e)ax, _rg' _rge SUBSTR <_rg>, 1, 1 IFIDNI _rge, xchg eax, _rg ELSE xchg ax, _rg ENDIF ENDM MACRO sta _rg ;shorter than 'mov _rg, (e)ax' _rge SUBSTR <_rg>, 1, 1 IFIDNI _rge, xchg _rg, eax ELSE xchg _rg, ax ENDIF ENDM MACRO dos _func IFNB <_func> IF _func and 0ff00h mov ax, _func ELSE mov ah, _func ENDIF ENDIF int 21h ENDM MACRO file _func, _errtx IFNB <_errtx> mov [errmsg], offset _errtx ENDIF IF _func and 0ff00h mov ax, _func ELSE mov ah, _func ENDIF call xdisk ENDM MACRO jfile _func, _errtx IFNB <_errtx> mov [errmsg], offset _errtx ENDIF IF _func and 0ff00h mov ax, _func ELSE mov ah, _func ENDIF jmp xdisk ENDM MACRO print _text IFNB <_text> mov dx, offset _text ENDIF dos 9 ENDM MACRO error _err push offset _err jmp errln ENDM MACRO testfl _mask ; testflag is tasm's optimized version of test testflag [flags], _mask ENDM MACRO resfl _mask ; maskflag is tasm's optimized version of and maskflag [flags], not (_mask) ENDM MACRO setfl _mask ; setflag is tasm's optimized version of or setflag [flags], _mask ENDM MACRO testsw _mask testflag [swits], _mask ENDM MACRO setsw _mask setflag [swits], _mask ENDM MACRO jpass1 _dest testflag [flags], m_pass jz _dest ENDM MACRO jpass2 _dest testflag [flags], m_pass jnz _dest ENDM MACRO jopcod _dest cmp bp, offset var jne _dest ENDM MACRO jnopcod _dest cmp bp, offset var je _dest ENDM MACRO cmd _oper _tp SUBSTR <_oper>, 4, 4 _tp CATSTR <0>, &_tp, dw _tp IRP _ct,<3,2,1> _tp SUBSTR <_oper>, _ct, 1 % db '&_tp' ENDM _tp SUBSTR <_oper>, 8 dw _tp ENDM MACRO opr _oper _tp SUBSTR <_oper>, 1, 1 db _tp _tp SUBSTR <_oper>, 2 _tp CATSTR , _tp dw _tp ENDM MACRO undata db 6 dup(?) lstnum db 5 dup(?) lstspa db ? lstorg db 26 dup(?) line db 258 dup(?) tlabel db 256 dup(?) obuf db 128 dup(?) obufen = $ objnam db 128 dup(?) lstnam db 128 dup(?) tabnam db 128 dup(?) t_icl db l_icl dup(?) t_org db l_org dup(?) t_def db l_def dup(?) ENDM ;***************************** IF EXE ELSE db 100h dup(?) ENDIF start: IF COMPAK undata db COMPAK+start-$ dup(?) ENDIF IF EXE mov dx, @data mov es, dx mov ss, dx mov sp, offset staken mov di, offset tlabel mov ax, [16h] stosw mov si, 81h movzx cx, [byte si-1] inc cx rep movsb mov ds, dx ENDIF IF SET_WIN_TITLE mov di, offset hello mov ax, 168eh xor dx, dx int 2fh mov [titfin], 0dh ENDIF ; print hello IF EXE mov si, offset tlabel+3 ELSE mov si, 82h ENDIF mov [objnam], 0 mov [lstnam], 0 mov [tabnam], 0 mov [(icl t_icl).nam], 0 ; pusta nazwa zrodla ; parsuj argumenty parg0: dec si parg1: lodsb cmp al, ' ' je parg1 cmp al, 9 je parg1 cmp al, 0dh je pargx cmp al, '/' je popt1 mov di, offset (icl t_icl).nam cmp [byte di], 0 jnz usg ; juz byla nazwa zrodla mov dx, di dec si call clfname call adasx mov [fslen], di jmp parg0 usg: print hello ; usage - instrukcja dos 4c03h popt1: lodsb and al, 0dfh ; mala litera -> duza mov di, offset swilet mov cx, NUM_SWITCHES repne scasb jne usg ; nie ma takiego switcha bts [swits], cx ; sprawdz bit i ustaw jnc popt2 cmp al, 'D' ; tylko /d dozwolone kilka razy jne usg popt2: mov di, offset lstnam cmp al, 'L' je popt4 mov di, offset tabnam cmp al, 'T' je popt4 mov di, offset objnam cmp al, 'O' je popt3 cmp al, 'D' jne parg1 mov di, [defen] popt3: cmp [byte si], ':' ; /O i /D wymagaja ':' jne usg popt4: mov ah, al lodsb cmp al, ':' jne parg0 call clfname ; pobierz nazwe cmp ah, 'D' jne parg0 ; mov [byte di], 0 lea cx, [di-3] sub cx, [defen] jbe usg xchg di, [defen] inc di mov al, '=' repne scasb jne usg jmp parg0 pargx: cmp [(icl t_icl).nam], 0 ; czy jest nazwa? je usg testsw m_swq jnz nohelo mov [usgtxt], '$' print hello nohelo: mov di, offset lstnam mov eax, 'TSL' call defnam mov di, offset objnam mov eax, 'XBO' call defnam mov al, [byte swits] and al, m_lstl xor al, m_lstl+m_lsto mov [flist], al testsw m_swe jz noswe IF EXE mov ax, [word tlabel] jmp prpsp1 ENDIF prpsp: mov ax, [16h] prpsp1: mov ds, ax cmp ax, [16h] jne prpsp mov ax, [2ch] test ax, ax jz enver dec ax IF EXE mov [ss:envseg], ax ELSE mov [cs:envseg], ax ENDIF mov ds, ax mov es, ax mov si, 10h mov di, si xor al, al renv1: cmp al, [si] jz renvx cmp [word si], 'RE' jne renv2 cmp [byte si+2], 'R' jne renv2 cmp [byte si+7], '=' jne renv2 cmp [dword si+3], 'ELIF' je renv3 cmp [dword si+3], 'ENIL' je renv3 renv2: movsb cmp al, [si-1] jnz renv2 jmp renv1 renv3: lodsb test al, al jnz renv3 jmp renv1 enver: IF EXE push ss ELSE push cs ENDIF pop ds call prenvt dos 4c02h renvx: IF EXE push ss ELSE push cs ENDIF pop ds mov [envofs], di stosb push ds pop es noswe: IF POOR_MAN_MAKE btr [swits], b_swn jnc noswn mov dx, offset objnam ; sprawdz czas modyfikacji object'a dos 3d00h jc noswn ; pewnie nie istnieje sta bx ; handle -> bx dos 5700h mov [word objmod], cx ; zapisz czas mov [word high objmod], dx ; zapisz date dos 3eh setsw m_swn ; sprawdzimy czas modyfikacji source'a noswn: ENDIF mov bp, offset var npass: mov [orgvec], offset t_org-2 mov [defvec], offset t_def mov [fillfl], 0 mov di, [fslen] opfile: call fopen IF POOR_MAN_MAKE btr [swits], b_swn jnc main sta bx dos 5700h ; sprawdz czas modyfikacji push dx push cx pop eax cmp eax, [objmod] ja main mov si, offset oldtxt call prline dos 4c00h ENDIF main: mov di, offset line mov si, [defvec] cmp si, [defen] jae nodef mdef1: movsb cmp [byte si], '=' jne mdef1 inc si mov eax, 'uqe ' stosd stosb mdef2: movsb cmp [byte si], 0 jne mdef2 inc si mov [defvec], si setfl m_def inc [(icl t_icl).line] jmp syntax nodef: btr [flags], b_def jnc ndef1 mov [(icl t_icl).line], 0 mov [srcen], 0 ndef1: mov bx, [iclen] mov bx, [(icl bx).prev] test [(icl bx).flags], m_eofl jnz filend ; czy byl juz koniec pliku ? ; ... nie - omin ewentualny LF call fread1 jz filend mov bx, [iclen] mov bx, [(icl bx).prev] inc [(icl bx).line] ; zwieksz nr linii w pliku inc [lines] ; ilosc wszystkich linii testsw m_swi jz gline1 ; czy /I and [flist], not m_lsti ; ... tak cmp bx, offset t_icl jbe gline1 ; czy includowany plik ? or [flist], m_lsti ; ... tak, nie listuj gline1: mov al, [di] cmp al, 0dh ; pc cr jne gline2 call fread1 jz eof cmp [byte di], 0ah je syntax push offset e_nomac jmp erron gline2: cmp al, 0ah ; unix lf je syntax cmp al, 9bh ; atari eol je syntax inc di cmp di, offset line+256 jnb linlon call fread1 jnz gline1 ; eof eof: mov bx, [iclen] ; koniec pliku or [(icl bx).flags], m_eofl syntax: mov [byte di], 0dh mov [eolpos], di mov [lstidx], offset lstorg mov [labvec], 0 mov si, offset line ; asembluj linie call rlabel jb nolabl cmp [skflag], 0 jnz labelx jpass2 deflp2 ; jest etykieta call flab0 ; definicja etykiety w pass 1 jnc ltwice mov di, [laben] mov [labvec], di IF LABELS_32 movzx eax, [origin] stosd ELSE mov ax, [origin] stosw ; domyslnie equ * ENDIF mov al, m_lnus mov ah, dl stosw mov cx, dx sub cl, offset (lab).nam lda si mov si, offset tlabel rep movsb ; przepisz nazwe sta si mov [laben], di cmp di, offset t_lab+l_lab+offset (lab)-offset (lab).nam jb labelx error e_tlab ltwice: error e_twice deflp2: mov bx, [pslab] ; definicja etykiety w pass 2 mov [labvec], bx add [pslab], dx ; oznacz jako minieta test [(lab bx).flags], m_lnus jz labelx testsw m_swu jz labelx push si push offset w_ulab call warln pop si labelx: cmp [byte si], 0dh je lstrem call spaces nolabl: lodsb cmp al, ' ' je nolabl cmp al, 9 je nolabl cmp al, '*' je lstrem cmp al, ';' je lstrem cmp al, '|' je lstrem cmp al, 0dh je lstrem cmp al, ':' jne s_one cmp [skflag], 0 jnz lstcnd call getuns jc unknow sta cx jcxz lstre1 call spaces xor eax, eax jmp s_cmd skip1: lodsd ; sprawdz komende dec si and eax, 0dfdfdfh mov di, offset cndtxt mov cx, 5 repne scasd jne lstcnd call [word di-4+cndvec-cndtxt] lstrem: cmp [skflag], 0 jz lstre1 lstcnd: testsw m_swc jz main lstre1: cmp [byte high labvec], 0 jz lstre2 call chorg call phorg lstre2: call lstlin jmp main s_one: dec si mov cx, 1 mov eax, -1 s_cmd: cmp [skflag], 0 jnz skip1 mov [times], cx mov [loopctr], eax resfl m_times setfl m_first cmp cx, 1 je jone setfl m_times jone: testfl m_norg jnz nlorg call phorg nlorg: mov [cmdvec], si rdcmd1: resfl m_pair rdcmd2: mov [scdvec], 0 rdcmd3: lodsw ; wez trzy litery and ax, 0dfdfh xchg al, ah shl eax, 16 mov ah, 0dfh and ah, [si] jopcod lbnox ; jezeli nie cytujemy ... mov [obufpt], offset obuf ; (oprozniamy bufor wyjsciowy) testfl m_norg jz lbnox ; ... i nie bylo ORG ... cmp [byte high labvec], 0 je lbnox ; ... a jest etykieta ... cmp eax, 'EQU' shl 8 call nenorg ; ... to dozwolony jest tylko EQU lbnox: inc si cmp [byte si], ':' ; czy para instrukcji? jne nopair jopcod ntopco inc si mov [scdvec], si call get ; w kolejnych trzech literach nie moze byc EOLa call get call get setfl m_pair nopair: mov di, offset comtab ; przeszukiwanie polowkowe mov bx, 64*size com sfcmd1: mov al, [(com di+bx).c_code] mov [cod], al mov al, [(com di+bx).c_flag] cmp eax, [dword (com di+bx).c_flag] jb sfcmd2 je fncmd add di, bx cmp di, offset comend jb sfcmd2 sub di, bx sfcmd2: shr bx, 1 cmp bl, 3 ja sfcmd1 mov bl, 0 je sfcmd1 error e_inst ntrep: error e_crep ntopco: error e_opcod ntpair: error e_pair ntrepa: error e_repa fncmd: test al, 80h jz ckcmd1 jopcod ntopco ; nie ma opcoda ckcmd1: test al, 40h jz ckcmd2 testfl m_times ; nie mozna powtarzac ... jnz ntrep testfl m_pair ; ... ani parowac jnz ntpair ckcmd2: test al, 20h ; dyrektywa? jz ckcmd3 test al, 10h ; nie mozna generowac skoku przez dyrektywe jz rncmd3 ; (dyrektywa neutralna) resfl m_repa ; skok zabroniony testfl m_skit jz rncmd3 eskit: error e_skit ckcmd3: jopcod ckcmd4 btr [flags], b_skit jnc ckcmd4 setfl m_ski2 inc [curorg] inc [obufpt] mov cx, m_pair+m_times mov dx, offset w_skif call skirew ckcmd4: test al, 08h jz ckcmd5 testfl m_repa ; pseudo instrukcja powtarzania jz ntrepa mov cx, m_repl mov dx, offset w_repl call skirew jmp rncmd2 ckcmd5: setfl m_repa test al, 04h mov ax, [origin] mov [reporg], ax jz rncmd2 resfl m_ski2 setfl m_skit ; pseudo instrukcja omijania mov [obuf], 2 mov al, [(com di+bx).c_code] call savbyt ; robimy miejsce na argument skoku IF RELOC_ORG call incorg ELSE inc [origin] ENDIF jmp encmd2 rncmd2: resfl m_repl testfl m_pair+m_times jz rncmd3 setfl m_repl ; ustaw repl, jesli koniec linii z para lub licznikiem rncmd3: mov al, [cod] call [(com di+bx).c_vec] ; wywolaj procedure btr [flags], b_ski2 jnc encmd2 mov ax, [origin] sub ax, [reporg] add ax, 80h call calcbr mov [obuf], al encmd2: call oflush resfl m_first mov cx, [scdvec] jcxz encmd3 mov si, cx jmp rdcmd2 encmd3: call linend inc [loopctr] dec [times] jz main mov si, [cmdvec] jmp rdcmd1 skirew: jpass1 skiret testfl cx jz skiret testfl m_first jz skiret pusha push dx call warln popa skiret: ret ; ERROR errln: call ppline erron: call prname mov dx, offset errtxt mov cx, errtxl call prerr pop si call msgenv dos 4c02h ; WARNING warln: call ppline call prname mov dx, offset wartxt mov cx, wartxl call prerr pop ax pop si push ax mov [byte exitcod], 1 msgenv: call prline btr [flags], b_enve jnc skiret prenvt: mov si, offset envtxt jmp prline gname: mov di, [(icl bx).prev] mov dx, offset clitxt mov cx, clitxl testfl m_def jnz gnamex lea cx, [bx-1] lea dx, [(icl di).nam] sub cx, dx gnamex: ret prname: mov bx, [iclen] cmp bx, offset t_icl jna skiret call gname push di mov [envnam], dx sub bx, dx mov [envlen], bx call prerr mov al, ' ' call putchar mov al, '(' call putchar pop bx mov eax, [(icl bx).line] call numdet mov dx, di mov [envnum], di mov cx, offset dectxt+10 sub cx, di call prerr mov al, ')' call putchar mov al, ' ' call putchar testsw m_swe jz skiret les di, [dword envofs] mov ax, [es:3] shl ax, 4 sub ax, di sub ax, offset dectxt+10+19-1 sub ax, [envlen] add ax, [envnum] mov [envlen], ax js senve mov eax, 'FRRE' stosd mov eax, '=ELI' stosd mov si, [envnam] senv1: movsb cmp [byte si], 0 ;'$' jne senv1 xor al, al stosb mov eax, 'LRRE' stosd mov eax, '=ENI' stosd mov si, [envnum] senv2: movsb cmp [byte si], '$' jne senv2 xor ax, ax stosw push ds pop es ret senve: setfl m_enve ret ppline: mov si, offset line prline: mov dx, si xor cx, cx prli1: inc si inc cx cmp [byte si-1], 0dh jne prli1 mov bx, STDERR dos 40h mov al, 0ah putchar: mov [chbuf], al mov dx, offset chbuf mov cx, 1 prerr: mov bx, STDERR dos 40h ret miseif: push offset e_meif jmp erron skiten: push offset e_skit jmp erron ; End of file pofend: pop ax filend: call fclose cmp bx, offset t_icl ja main jpass2 fin cmp [elflag], 1 jne miseif testfl m_skit jnz skiten setfl m_pass+m_norg+m_rorg+m_rqff+m_hdr+m_wobj and [flist], not m_lsto jmp npass fin: mov bx, [ohand] mov [errmsg], offset e_wrobj call hclose testsw m_swt jz nlata ; czy /T ? cmp [laben], offset t_lab ; ... tak jbe nlata ; czy tablica pusta ? cmp [byte tabnam], 0 ; ... nie jnz oplata ; czy dana nazwa ? cmp [lhand], nhand ; ... nie jne latt1 ; czy otwarty listing ? call opnlst ; ... nie - otworz jmp latt2 latt1: call plseol jmp latt2 oplata: call lclose ; zamknij listing IF LONG_FILE_NAMES mov si, offset tabnam ELSE mov dx, offset tabnam ENDIF call opntab ; otworz tablica latt2: mov dx, offset tabtxt mov cx, tabtxl call putlad mov si, offset t_lab lata1: mov di, offset lstnum mov eax, ' ' test [(lab si).flags], m_lnus jz lata2 mov al, 'n' lata2: test [(lab si).flags], m_ukp1 jz lata3 mov ah, '2' lata3: stosd IF LABELS_32 mov eax, [(lab si).l_val] test eax, eax jns lata4 mov [byte di-1], '-' neg eax lata4: call phdword ELSE mov ax, [(lab si).l_val] test [(lab si).flags], m_sign jz lata4 mov [byte di-1], '-' neg ax lata4: call phword ENDIF mov al, ' ' stosb mov cx, (offset (lab)-offset (lab).nam) and 0ffh add cl, [(lab si).len] add si, offset (lab).nam rep movsb call putlst cmp si, [laben] jb lata1 nlata: call lclose testsw m_swq jnz zrbyt mov eax, [lines] shr eax, 1 call pridec print lintxt mov eax, [bytes] test eax, eax jz zrbyt call pridec print byttxt zrbyt: mov ax, [exitcod] ; dos ;!!! ; I/O xdisk: dos jnc cloret xderror: push [errmsg] jmp erron icler: push offset e_icl jmp erron lclose: mov bx, nhand ; mov bx, [lhand] xchg bx, [lhand] ; mov [lhand], nhand mov [errmsg], offset e_wrlst hclose: cmp bx, nhand je cloret jfile 3eh IF LONG_FILE_NAMES lfnopen: mov ax, 716ch lfndos: mov [errmsg], cx xor cx, cx dos jnc lfnok add ah, -71h jnc xderror mov dx, si lfnok: ret lfncreat: mov bx, 2001h mov dx, 12h call lfnopen jnc lfnok jfile 3c00h ENDIF fopen: cmp di, offset t_icl+l_icl-2 jnb icler push si testsw m_swp jz fopen1 mov si, offset (icl).nam add si, [iclen] mov di, offset tlabel IF LONG_FILE_NAMES mov cx, offset e_open mov ax, 7160h call lfndos jnc pathok file 60h pathok: ELSE file 60h, e_open ENDIF mov si, offset tlabel mov di, offset (icl).nam add di, [iclen] fomna: lodsb stosb test al, al jnz fomna fopen1: mov bx, [iclen] mov [(icl bx).line], 0 mov [(icl bx).flags], 0 IF LONG_FILE_NAMES lea si, [(icl bx).nam] mov [(icl di).prev], bx mov [iclen], di mov bx, 2000h mov dx, 1 mov cx, offset e_open call lfnopen jnc openok file 3d00h openok: ELSE lea dx, [(icl bx).nam] mov [(icl di).prev], bx mov [iclen], di file 3d00h, e_open ENDIF pop si mov bx, [iclen] mov bx, [(icl bx).prev] mov [(icl bx).handle], ax cloret: ret fread1: mov dx, di mov cx, 1 fread: mov ah, 3fh fsrce: mov bx, [iclen] mov bx, [(icl bx).prev] mov bx, [(icl bx).handle] mov [errmsg], offset e_read call xdisk test ax, ax ret fclose: mov ah, 3eh call fsrce mov bx, [iclen] cmp bx, [srcen] jne fclos1 mov [srcen], 0 fclos1: mov bx, [(icl bx).prev] mov [iclen], bx ret putwor: mov cx, 2 ; zapisz slowo do pliku mov dx, offset oword mov [oword], ax putblk: jpass1 putx ; zapisz blok cmp [ohand], nhand jne putb1 ; otwarty object ? IF LONG_FILE_NAMES push cx dx si mov si, offset objnam ; ... nie - otworz mov cx, offset e_crobj call lfncreat ELSE mov dx, offset objnam ; ... nie - otworz xor cx, cx file 3ch, e_crobj ENDIF mov [ohand], ax testsw m_swq jnz noobjt print objtxt noobjt: IF LONG_FILE_NAMES pop si dx cx ELSE pop dx cx ENDIF putb1: mov bx, [ohand] file 40h, e_wrobj movzx ecx, cx add [bytes], ecx putx: ret orgwor: push ax call phword pop ax jmp putwor chorg: testfl m_norg nenorg: jz putx error e_norg tmorgs: error e_orgs filer: error e_fill ;;internal: error e_fatal incorg: inc [origin] IF RELOC_ORG inc [ldorg] ENDIF ret savwor: push ax call savbyt pop ax mov al, ah savbyt: jopcod xopco testfl m_wobj jz incorg btr [fillfl], b_fillrq jnc nofill push ax resfl m_rorg+m_rqff IF RELOC_ORG mov ax, [ldorg] ELSE mov ax, [origin] ENDIF sub ax, [curorg] jz fillfi jb filer fillop: push ax mov dx, offset fillbyt mov cx, 1 call putblk pop ax dec ax jnz fillop IF RELOC_ORG mov ax, [ldorg] ELSE mov ax, [origin] ENDIF mov [curorg], ax fillfi: pop ax nofill: mov di, [obufpt] stosb mov [obufpt], di IF RELOC_ORG mov ax, [ldorg] ELSE mov ax, [origin] ENDIF testfl m_hdr jz borg4 call chorg testfl m_rorg jnz borg1 cmp ax, [curorg] je borg3 borg1: add [orgvec], 2 cmp [orgvec], offset t_org+l_org jae tmorgs jpass1 borg2 mov di, offset lstorg testfl m_rqff jz noff mov ax, 0ffffh call orgwor mov ax, ' >' stosw IF RELOC_ORG mov ax, [ldorg] ELSE mov ax, [origin] ENDIF noff: call orgwor mov al, '-' stosb mov bx, [orgvec] mov ax, [bx] call orgwor mov ax, ' >' stosw IF RELOC_ORG mov ax, [ldorg] ELSE mov ax, [origin] ENDIF mov [lstidx], di borg2: resfl m_rorg+m_rqff borg3: jpass2 borg4 mov di, [orgvec] stosw borg4: inc ax mov [curorg], ax setflag [fillfl], m_fillpo IF RELOC_ORG call incorg ELSE inc [origin] ENDIF ;; cmp ax, [origin] ;; je internal cmp [obufpt], offset obufen jb oflur testfl m_skit jnz eskit oflush: mov dx, offset obuf mov cx, [obufpt] sub cx, dx jz oflur mov [obufpt], dx call putblk test [flist], m_lsts jnz oflur mov bx, offset obuf mov di, [lstidx] olst1: cmp di, offset line-3 jae lstxtr mov al, [bx] inc bx call phbyte mov al, ' ' stosb loop olst1 olstx: mov [lstidx], di oflur: ret lstxtr: cmp di, offset line-1 jae olstx mov ax, ' +' stosw mov [lstidx], di linret: ret ; Stwierdza blad, jesli nie spacja, tab lub eol linend: lodsb cmp al, 0dh je linen1 cmp al, ' ' je linen1 cmp al, 9 je linen1 error e_xtra ; Listuje linie po ostatnim przebiegu linen1: cmp [times], 1 jne linret ; Listuje linie lstlin: test [flist], m_lsts jnz linret mov di, offset lstspa mov bx, [iclen] mov bx, [(icl bx).prev] mov eax, [(icl bx).line] call numdec mov al, ' ' lstl1: dec di mov [di], al cmp di, offset lstnum ja lstl1 mov di, [lstidx] mov cx, offset line sub cx, di rep stosb mov [lstspa], al mov bx, [iclen] cmp bx, [srcen] je nlsrc ; czy zmienil sie asemblowany plik ? mov [srcen], bx ; ... tak cmp [lhand], nhand jne lsrc1 ; otwarty listing ? call opnlst ; ... nie - otworz lsrc1: mov dx, offset srctxt mov cx, offset srctxl call putlad ; komunikat o nowym source'u mov bx, [iclen] call gname call putlad ; nazwa call plseol nlsrc: mov di, [eolpos] IF CONVERT_TO_TABS testsw m_sws jnz ctrail ; jezeli nie ma /S ... mov si, offset lstnum mov di, si ; ... zamien spacje na taby spata1: xor dl, dl spata2: lodsb cmp al, 0dh je ctrail stosb cmp al, 9 je spata1 dec dx cmp al, ' ' jne spata2 and dx, 7 jz spata2 mov cx, dx mov bx, si spata3: cmp al, [bx] jne spata2 inc bx loop spata3 mov [byte di-1], 9 mov si, bx jmp spata1 strail: dec di ctrail: cmp [byte di-1], ' ' je strail cmp [byte di-1], 9 je strail ENDIF putlst: mov ax, 0a0dh stosw mov dx, offset lstnum mov cx, di sub cx, dx putlad: mov bx, [lhand] jfile 40h, e_wrlst opnlst: IF LONG_FILE_NAMES mov si, offset lstnam ELSE mov dx, offset lstnam ENDIF opntab: IF LONG_FILE_NAMES mov cx, offset e_crlst call lfncreat ELSE xor cx, cx file 3ch, e_crlst ENDIF mov [lhand], ax testsw m_swq jnz nolstt print lsttxt nolstt: mov dx, offset hello mov cx, hellen jmp putlad plseol: mov dx, offset eoltxt mov cx, 2 jmp putlad adasx: mov eax, 'XSA' ; Dodaj rozszerzenie nazwy, gdy go nie ma ; we: dx,di-poczatek,koniec nazwy; eax-rozszerzenie adext: mov bx, di adex1: dec bx cmp [byte bx], '\' je adex2 cmp [byte bx], '.' je adexr cmp bx, dx ja adex1 adex2: mov [byte di-1], '.' stosd adexr: ret ; Zapisz dziesietnie eax; di-koniec liczby numdet: mov di, offset dectxt+10 numdec: mov ebx, 10 numde1: cdq div ebx add dl, '0' dec di mov [di], dl test eax, eax jnz numde1 ret ; Wyswietl dziesietnie eax pridec: call numdet mov dx, di ; mov [envnum], di print ret ; Zapisz hex origin phorg: mov di, offset lstorg mov ax, [origin] call phword ; listuj * hex mov al, ' ' stosb mov [lstidx], di ret IF LABELS_32 phdword: IF FOUR_ZEROS_TO_SPACES rol eax, 16 test ax, ax jnz phdword0 mov ax, ' ' stosw stosw jmp phdword1 phdword0: ENDIF call phword phdword1: rol eax, 16 ENDIF ; Zapisz hex ax od [di] phword: push ax mov al, ah call phbyte pop ax phbyte: aam 10h cmp al, 10 sbb al, 69h das xchg al, ah cmp al, 10 sbb al, 69h das stosw ret ; Pobierz nazwe pliku z linii polecen (si) i zapisz do di clfname: lodsb cmp al, '"' je clfqt clf1: stosb lodsb cmp al, ' ' je clfx cmp al, 9 je clfx ; cmp al, '/' ; je clfx cmp al, 0dh jne clf1 clfx: xor al, al stosb ret clf2: stosb clfqt: lodsb cmp al, 0dh je clfx cmp al, '"' jne clf2 inc si jmp clfx ; wpisz domyslna nazwe dla obx lub lst defnam: cmp [byte di], 0 jnz defnr mov si, [fslen] defn1: dec si cmp [byte si], '.' jne defn1 lea cx, [si+1] mov si, offset (icl t_icl).nam sub cx, si rep movsb stosd defnr: ret ; Pobierz znak (eol=error) get: lodsb cmp al, 0dh je uneol ret uneol: error e_uneol ; Omin spacje i tabulatory spaces: call get cmp al, ' ' je space1 cmp al, 9 je space1 error e_spac space1: call get cmp al, ' ' je space1 cmp al, 9 je space1 dec si rstret: ret ; Pobierz nazwe pliku rfname: call spaces mov di, offset (icl).nam add di, [iclen] ; Pobierz lancuch do [di] rstr: call get cmp al, "'" je rstr0 cmp al, '"' jne strer rstr0: mov dx, di mov ah, al rstr1: call get stosb cmp al, ah jne rstr1 lodsb cmp al, ah je rstr1 dec si mov [byte di-1], 0 lea cx, [di-1] sub cx, dx jnz rstret strer: error e_str ; Przepisz etykiete do tlabel (wyj: dx-dl.etykiety+offset(lab).nam) rlabel: mov di, offset tlabel mov [byte di], 0 rlab1: lodsb cmp al, '0' jb rlabx cmp al, '9' jbe rlab2 cmp al, '_' je rlab2 and al, 0dfh cmp al, 'A' jb rlabx cmp al, 'Z' ja rlabx rlab2: stosb cmp di, offset tlabel+256+offset (lab)-offset (lab).nam jb rlab1 linlon: push offset e_long jmp erron rlabx: lea dx, [(lab di).nam] sub dx, offset tlabel dec si cmp [byte tlabel], 'A' ret ; Czytaj etykiete i szukaj w t_lab ; wyj: dx-dlugosc etykiety+offset(lab).nam ; C=0: znaleziona, bx=adres wpisu ; C=1: nie ma jej flabel: call rlabel jb ilchar flab0: push si xor cx, cx mov si, offset t_lab mov ax, [laben] dec ax flab1: add si, cx cmp ax, si jb flabx mov cl, [(lab si).len] cmp cl, dl jne flab1 add si, offset (lab).nam sub cl, offset (lab).nam mov di, offset tlabel repe cmpsb jne flab1 mov bx, offset tlabel - offset (lab).nam add bx, si sub bx, di ; c=0 flabx: pop si ret wropar: error e_wpar ; Czytaj wyrazenie i zwroc jego wartosc w [val] ; (C=1 wartosc nieokreslona w pass 1) IF LABELS_32 get32: ELSE spaval: call spaces getval: ENDIF xor bx, bx mov [ukp1], bh push bx v_lop: v_par1: inc bh v_par0: call get cmp al, '[' je v_par1 mov di, offset opert0 mov cx, noper0 repne scasb jne v_n1a sub di, offset opert0-noper1-noper2 call goprpa dec bh push di bx inc bh jmp v_par0 v_n1a: cmp al, '(' je wropar IF FUNCTIONS mov eax, [si-1] mov di, offset funtxt mov cx, nfun repne scasd jne notfun sub di, offset funtxt shr di, 1 call [funvec+di] jmp value1 notfun: ENDIF movzx eax, al cmp al, '*' je valorg cmp al, '#' je valctr cmp al, "'" je valchr cmp al, '"' je valchr cmp al, '^' je valreg cmp al, '{' je valquo mov di, -1 cdq ; xor edx, edx mov ecx, 16 cmp al, '$' je rdnum3 mov cl, 2 cmp al, '%' je rdnum3 mov cl, 10 cmp al, '9' ja vlabel rdnum1: cmp al, '9' jbe rdnum2 and al, 0dfh cmp al, 'A' jb value0 add al, '0'+10-'A' rdnum2: sub al, '0' cmp al, cl jnb value0 movzx edi, al lda edx mul ecx add eax, edi js toobig adc edx, edx jnz toobig sta edx rdnum3: lodsb jmp rdnum1 vlabel: push bx dec si call flabel jnc vlabfn jpass1 vlukp1 error e_undec vlabfn: and [(lab bx).flags], not m_lnus jpass1 vlchuk cmp bx, [pslab] jb vlchuk test [(lab bx).flags], m_ukp1 jz vlukp1 error e_fref vlchuk: test [(lab bx).flags], m_ukp1 jz vlabkn vlukp1: mov [ukp1], 0ffh vlabkn: IF LABELS_32 mov eax, [(lab bx).l_val] ELSE bt [word (lab bx).flags], b_sign sbb eax, eax mov ax, [(lab bx).l_val] ENDIF pop bx jmp value1 valorg: call chorg mov ax, [origin] jmp value1 valctr: mov eax, [loopctr] test eax, eax jns value1 error e_ctr valchr: mov dl, al call get cmp al, dl jne valch1 lodsb cmp al, dl jne strer valch1: cmp dl, [si] jne strer inc si cmp [byte si], '*' jne value1 inc si xor al, 80h jmp value1 valreg: call get sub al, '0' cmp al, 4 ja ilchar add al, 0d0h testfl m_5200 jz no5200 cmp al, 0d3h je nopia cmp al, 0d2h jne no5200 mov al, 0e8h no5200: mov ah, al call get cmp al, '9' jbe valre1 and al, 0dfh cmp al, 'A' jb ilchar add al, '0'+10-'A' valre1: sub al, '0' cmp al, 0fh ja ilchar cmp ah, 0d1h ja value1 jne valre2 sub ax, 0f0h valre2: testfl m_5200 jz value1 mov ah, 0c0h jmp value1 nopia: error e_5200 valquo: jopcod rcopco push bx mov [opcosp], sp mov bp, offset var2 jmp rdcmd3 xopco: mov sp, [opcosp] mov bp, offset var mov ah, al call get cmp al, '}' jne msopco movzx eax, ah pop bx jmp value1 rcopco: error e_ropco msopco: error e_mopco value0: dec si test di, di js ilchar lda edx value1: push eax v_par2: dec bh js mbrack lodsb cmp al, ']' je v_par2 mov ah, [si] mov di, offset opert2 mov cx, noper2 repne scasw je foper2 ; operator 2-znakowy mov cx, noper1 repne scasb je foper1 ; operator 1-znakowy test bh, bh ; koniec wyrazenia jnz mbrack ; musza byc zamkniete nawiasy dec si mov di, offset opert1 foper1: sub di, offset opert1 jmp goper foper2: inc si sub di, offset opert2 shr di, 1 add di, noper1 goper: call goprpa pop eax v_com: pop cx cmp cx, bx jb v_xcm pop dx cmp dx, offset v_1arg jae v_r1a sta ecx pop eax v_r1a: jpass2 v_run cmp [ukp1], 1 jnb v_com v_run: push offset v_com push dx ret v_xcm: cmp bl, 1 jbe v_xit push cx eax di bx jmp v_lop v_xit: mov [dword val], eax cmp [ukp1], 1 cmc IF LABELS_32 ret spaval: call spaces getval: call get32 ENDIF jc unsret wrange: cmp eax, 10000h cmc jnb unsret cmp eax, -0ffffh jb orange ret brange: cmp eax, 100h jb unsret cmp eax, -0ffh jb orange ret spauns: call spaces getuns: call getval pushf jnc getun1 jpass1 getun2 getun1: test eax, eax js orange getun2: popf unsret: ret getpos: call getval jc unknow test eax, eax jg unsret orange: error e_range mbrack: error e_brack toobig: error e_nbig ; Procedury operatorow nie moga zmieniac bx ani di v_sub: neg ecx ; - v_add: add eax, ecx ; + jno v_ret oflow: error e_over div0: error e_div0 v_mul: mov edx, ecx ; * xor ecx, eax imul edx test ecx, ecx js v_mu1 test edx, edx jnz oflow test eax, eax js oflow ret v_mu1: inc edx jnz oflow test eax, eax jns oflow ret v_div: jecxz div0 ; / cdq idiv ecx ret v_mod: jecxz div0 ; % cdq idiv ecx lda edx ret v_sln: neg ecx v_sal: test ecx, ecx ; << js v_srn jz v_ret cmp ecx, 20h jb v_sl1 test eax, eax jnz oflow ret v_sl1: add eax, eax jo oflow loop v_sl1 p_skp: v_ret: ret v_srn: neg ecx v_sar: test ecx, ecx ; >> js v_sln cmp ecx, 20h jb v_sr1 mov cl, 1fh v_sr1: sar eax, cl ret v_and: and eax, ecx ; & ret v_or: or eax, ecx ; | ret v_xor: xor eax, ecx ; ^ ret v_equ: cmp eax, ecx ; = v_eq1: je v_one v_zer: xor eax, eax ret v_one: mov eax, 1 ret v_neq: cmp eax, ecx ; <> != jne v_one jmp v_zer v_les: cmp eax, ecx ; < jl v_one jmp v_zer v_grt: cmp eax, ecx ; > jg v_one jmp v_zer v_leq: cmp eax, ecx ; <= jle v_one jmp v_zer v_geq: cmp eax, ecx ; >= jge v_one jmp v_zer v_anl: jecxz v_zer ; && test eax, eax jz v_ret jmp v_one v_orl: or eax, ecx ; || jz v_ret jmp v_one ; Operatory 1-argumentowe v_1arg: v_neg: neg eax v_plu: ret v_low: movzx eax, al ret v_hig: movzx eax, ah ret v_nol: test eax, eax jmp v_eq1 v_not: not eax ret IF FUNCTIONS ; funkcje f_abs: call value test eax, eax js v_neg ret f_ang: f_hyp: f_ret: ret f_max: call valuco push eax call valuco pop ecx cmp eax, ecx jge f_ret ; jle? f_ecx: lda ecx ret f_min: call valuco push eax call valuco pop ecx cmp eax, ecx jge f_ecx ; jle? ret f_sqr: ; TODO ret ENDIF goprpa: lea ax, [di+operpa] add di, di add di, ax mov bl, [di] mov di, [di+1] ret onemod: jnopcod getadr cmp [byte si], '}' jne getadr jmp xopco getaim: jnopcod getai0 cmp [byte si], '}' je getai2 getai0: cmp al, '<' pushf call getval popf jb getai2 je getai1 mov al, ah getai1: movzx eax, al mov [dword val], eax getai2: mov dx, 1 jmp getadx ; Pobierz operand rozkazu i rozpoznaj tryb adresowania getadr: call spaces lodsb xor dx, dx cmp al, '@' je getadx cmp al, '#' je getaim cmp al, '<' je getaim cmp al, '>' je getaim mov dl, 8 cmp al, '(' je getao1 dec si lodsw and al, 0dfh mov dl, 2 cmp ax, ':A' je getao2 inc dx cmp ax, ':Z' je getao2 dec si dec si xor dx, dx getad1: push dx call getuns sbb al, al jnz getad2 mov al, [byte high val] getad2: pop dx getad9: cmp dl, 8 jae getaid cmp dl, 2 jae getad3 cmp al, 1 adc dl, 2 getad3: lodsw and ah, 0dfh mov bl, 2 cmp ax, 'X,' je getabi mov bl, 4 cmp ax, 'Y,' je getabi dec si dec si jmp getadx getabi: add dl, bl getaxt: lodsb cmp al, '+' je getabx inc bx cmp al, '-' je getabx dec si jmp getadx getabx: mov dh, bl getadx: lda dx mov [word amod], ax ret getao1: jnopcod getad1 cmp [byte si], ')' je getaid getao2: jnopcod getad1 cmp [byte si], ',' je getad9 cmp [byte si], '}' je getad9 jmp getad1 getaid: lodsb cmp al, ',' je getaix call chkpar lodsw mov dx, 1009h mov bl, 14h cmp ax, '0,' je getaxt xor dh, dh mov bl, 4 and ah, 0dfh cmp ax, 'Y,' je getaxt inc dx dec si dec si jmp getadx getaix: lodsw mov dh, 8 cmp ax, ')0' je getadx xor dh, dh and al, 0dfh cmp ax, ')X' je getadx jmp ilchar p_imp = savbyt p_ads: call getadr mov al, [cod] call savbyt mov al, 60h cmp [cod], 18h je p_as1 mov al, 0e0h p_as1: mov [cod], al jmp p_ac1 p_acc: call getadr p_ac1: mov ax, [word amod] cmp al, 7 jne acc1 dec [amod] acc1: cmp ah, 8 jb acc3 mov ax, 0a2h je acc2 mov al, 0a0h acc2: call savwor acc3: mov al, [amod] mov bx, offset acctab xlat test al, al jz ilamod or al, [cod] cmp al, 89h ; sta # jne putsfx ilamod: error e_amod p_srt: call getadr cmp al, 6 jnb ilamod cmp al, 1 je ilamod mov bx, offset srttab xlat or al, [cod] cmp al, 0cah je ilamod cmp al, 0eah je ilamod putsfx: call putcmd mov al, [amod+1] and al, 7 mov bx, offset sfxtab xlat test al, al jnz savbyt putret: ret p_inw: call getadr cmp ax, 6 jnb ilamod sub al, 2 jb ilamod mov bx, offset inwtab xlat push ax call putcmd inc [val] mov ax, 03d0h test [amod], 1 jz p_iw1 dec ah p_iw1: call savwor pop ax jmp putsfx p_ldi: call getadr p_ld1: mov al, [amod] cmp al, 1 jb ilamod cmp al, 4 jb ldi1 and al, 0feh xor al, [cod] cmp al, 0a4h jne ilamod mov al, [amod] ldi1: mov bx, offset lditab xlat putcod: or al, [cod] jmp putsfx putcmd: call savbyt mov al, [amod] mov bx, offset lentab xlat cmp al, 2 jb putret mov eax, [dword val] jne savwor jpass1 putcm1 call brange putcm1: jmp savbyt p_sti: call getadr p_st1: mov al, [amod] cmp al, 2 jb ilamod je cod8 cmp al, 3 je cod0 and al, 0feh xor al, [cod] cmp al, 80h jne ilamod or [amod], 1 mov al, 10h jmp putcod cod8: mov al, 8 jmp putcod cod0: xor al, al jmp putcod p_cpi: call getadr cmp al, 1 jb ilamod cmp al, 4 jnb ilamod cmp al, 2 jb cod0 mov al, 0ch je putcod mov al, 4 jmp putcod p_rep: mov ax, [origin] xchg ax, [reporg] jmp bra0 p_bra: call onemod and al, 0feh cmp al, 2 jne ilamod mov ax, [val] bra0: jpass1 bra1 call chorg sub ax, [origin] add ax, 7eh call calcbr mov [byte val], al bra1: mov al, [cod] call savbyt mov al, [byte val] jmp savbyt calcbr: test ah, ah jnz toofar add al, 80h ret toofar: cmp ax, 8080h jae toofa1 sub ax, 0ffh neg ax toofa1: neg ax mov di, offset brout call phword error e_bra p_jsr: call onemod mov al, 20h jmp p_abs p_bit: call getadr cmp al, 2 mov al, 2ch je putcmd cmp [amod], 3 jne ilamod mov al, 24h jmp putcmd p_juc: call getadr mov al, [cod] mov ah, 3 call savwor jmp p_jp1 p_jmp: call getadr p_jp1: cmp [amod], 10 je chkbug jpass1 p_jpu cmp [cod], 4ch je p_jpu testfl m_norg ; nieznany * (przy OPT H-) jnz p_jpu mov ax, [val] ; moze branch wystarczy? sub ax, [origin] add ax, 80h test ah, ah jnz p_jpu push si push offset w_bras call warln pop si p_jpu: mov al, 4ch p_abs: and [amod], 0feh cmp [amod], 2 je p_jpp jmp ilamod chkbug: jpass1 p_jid cmp [byte val], 0ffh jne p_jid push si push offset w_bugjp call warln pop si p_jid: mov al, 6ch p_jpp: jmp putcmd getops: call getadr lea di, [op1] call stop push [word ukp1] call getadr pop [word ukp1] mov [tempsi], si lea di, [op2] call stop movzx bx, [cod] add bx, offset movtab ldop1: lea si, [op1] ldop: lodsd mov [dword val], eax lodsw mov [word amod], ax ret stop: mov eax, [dword val] stosd mov ax, [word amod] stosw ret mcall1: mov al, [(movt bx).m_lcod] mov [cod], al push bx call [(movt bx).m_lvec] pop bx ret mcall2: mov al, [(movt bx).m_scod] mov [cod], al push bx call [(movt bx).m_svec] pop bx ret p_mvs: call getops call mcall1 lea si, [op2] call ldop p_mvx: call mcall2 mov si, [tempsi] ret p_mws: call getops mov ax, [word amod] cmp ax, 8 jae ilamod cmp al, 1 jne p_mw1 and [dword val], 0ffh p_mw1: call mcall1 lea si, [op2] call ldop cmp [word amod], 8 jae ilamod call mcall2 call ldop1 cmp [amod], 1 je p_mwi inc [val] jmp p_mw2 p_mwi: cmp [ukp1], 0 jnz p_mwh mov dx, [val] cmp dl, dh je p_mw3 dec dh mov al, [(movt bx).m_inc] cmp dl, dh je p_mw4 add dh, 2 cmp dl, dh jne p_mwh mov al, [(movt bx).m_dec] p_mw4: test al, al jz p_mwh call savbyt jmp p_mw3 p_mwh: sar [dword val], 8 p_mw2: call mcall1 p_mw3: lea si, [op2] call ldop inc [val] jmp p_mvx p_opt: call spaces xor dx, dx jmp opt0 opt1: shr cx, 1 bts dx, cx jc opter call [word di-2+optvec-opttxt] opt0: lodsw and al, 0dfh mov cx, 10 mov di, offset opttxt repne scasw je opt1 test dx, dx jz opter dec si dec si ret opter: error e_opt optf0: ; maskflag [fillfl], not (m_fillen+m_fillrq) maskflag [fillfl], not m_fillen ret optf1: setflag [fillfl], m_fillen ret optg0: resfl m_5200 ret optg1: setfl m_5200 ret opth0: resfl m_hdr+m_rqff ret opth1: bts [flags], b_hdr jc optr setfl m_rorg ret optl0: or [flist], m_lsto ret optl1: jpass1 optr and [flist], not m_lsto optr: ret opto0: resfl m_wobj ret opto1: setfl m_wobj ret p_ert: call spaval jpass1 equret test eax, eax jz equret error e_user p_equ: mov di, [labvec] test di, di jz nolabd mov [(lab di).l_val], 0 IF LABELS_32 call spaces call get32 ELSE and [(lab di).flags], not m_sign call spaval ENDIF mov di, [labvec] jnc equ1 or [(lab di).flags], m_ukp1 equ1: IF LABELS_32 mov [(lab di).l_val], eax ELSE mov [(lab di).l_val], ax test eax, eax jns equ2 or [(lab di).flags], m_sign equ2: ENDIF test [flist], m_lsts jnz equret sta dx mov di, offset lstorg mov ax, ' =' test eax, eax jns equ3 mov ah, '-' neg dx IF LABELS_32 xor eax, 0ffff0000h ENDIF equ3: stosw lda dx IF LABELS_32 call phdword ELSE call phword ENDIF mov [lstidx], di equret: ret nolabd: error e_label chkhon: testfl m_hdr jnz equret error e_hoff p_org: call spaces lodsw and al, 0dfh IF RELOC_ORG cmp ax, ':R' jne norgr call chorg call getuns jc unknow jmp setori norgr: ENDIF cmp ax, ':F' je orgff cmp ax, ':A' je orgaf dec si dec si jmp orget orgff: setfl m_rqff orgaf: setfl m_rorg call chkhon orget: call getuns jc unknow testflag [fillfl], m_fillpo jz nforg setflag [fillfl], m_fillrq testflag [fillfl], m_fillen jnz setorg nforg: maskflag [fillfl], not m_fillrq setorg: resfl m_norg IF RELOC_ORG mov [ldorg], ax setori: ENDIF mov [origin], ax ret p_rui: call chkhon mov ah, 2 call nforg call spauns call savwor maskflag [fillfl], not m_fillpo ret valuco: call getval jc unknow call get cmp al, ',' jne badfun mov ax, [val] ret badfun: error e_func dtan0: cmp al, 'A' je dtan1 cmp al, 'B' je dtan1 cmp al, 'L' je dtan1 cmp al, 'H' je dtan1 cmp al, 'R' jne dtab1 jmp dtar1 dtat0: cmp al, 'C' je dtat1j cmp al, 'D' jne dtab1 dtat1j: dec si mov [cod], al jmp dtat1 p_dta: call spaces dta1: lodsw and al, 0dfh cmp ah, '(' je dtan0 cmp ah, "'" je dtat0 cmp ah, '"' je dtat0 dtab1: dec si dec si mov al, ' ' dtan1: mov [cod], al dtan2: lodsd and eax, 0ffdfdfdfh cmp eax, '(NIS' jne dtansi call valuco mov [sinadd], eax call valuco mov [sinamp], eax call getpos mov [sinsiz], ax mov [sinmin], 0 dec ax mov [sinmax], ax call get cmp al, ')' je presin cmp al, ',' jne badfun call valuco test eax, eax js badfun mov [sinmin], ax call getuns jc unknow cmp ax, [sinmin] jb badfun mov [sinmax], ax lodsb call chkpar presin: finit fldpi fld st faddp st(1), st fidiv [sinsiz] gensin: fild [sinmin] fmul st, st(1) fsin fimul [sinamp] fiadd [sinadd] fistp [dword val] inc [sinmin] mov eax, [dword val] call wrange jmp dtasto dtansi: sub si, 4 call getval dtasto: mov al, [cod] cmp al, 'A' je dtana jpass1 dtans cmp al, 'L' je dtanl cmp al, 'H' je dtanh mov eax, [dword val] call brange jmp dtans dtana: mov ax, [val] call savwor jmp dtanx dtanl: mov al, [byte low val] jmp dtans dtanh: mov al, [byte high val] dtans: call savbyt dtanx: mov ax, [sinmin] cmp ax, [sinmax] jbe gensin cmp [cod], ' ' je dtanxt lodsb cmp al, ',' je dtan2 dtanp: push offset dtanxt chkpar: cmp al, ')' je paret error e_paren unknow: error e_uknow dtat1: mov di, offset tlabel call rstr lodsb mov ah, 80h cmp al, '*' je dtat2 dec si xor ah, ah dtat2: push si mov si, dx dtatm: lodsb xor al, ah cmp [cod], 'D' jne ascinx mov dl, 60h and dl, al jz ascin1 cmp dl, 60h je ascinx sub al, 60h ascin1: add al, 40h ascinx: push ax cx call savbyt pop cx ax loop dtatm pop si dtanxt: lodsb cmp al, ',' je dta1 dec si paret: ret ; Zapisz liczbe rzeczywista dtar1: dtar2: xor bx, bx xor edx, edx xor cx, cx call getsgn dreal1: call getdig jnc dreal2 cmp al, '.' je drealp test bh, bh jnz drealz ilchar: error e_char dreal2: mov bh, 1 test al, al jz dreal1 dec cx dreal3: inc cx call putdig call getdig jnc dreal3 cmp al, '.' je drealp jmp dreale dreal5: test edx, edx jnz dreal9 test bl, bl jnz dreal9 dec cx dreal9: call putdig drealp: call getdig jnc dreal5 dreale: and al, 0dfh cmp al, 'E' jne drealf call getsgn call getdig jc ilchar mov ah, al call getdig jnc dreal4 shr ax, 8 dec si dreal4: inc si aad add di, di jnc drealn neg ax drealn: add cx, ax drealf: test edx, edx jnz drealx test bl, bl jnz drealx drealz: xor ax, ax xor edx, edx jmp dreals drealx: add cx, 80h cmp cx, 20h js drealz cmp cx, 0e2h jnb toobig add di, di rcr cl, 1 mov al, 10h jc dreal7 cmp bl, al mov al, 1 jb dreal7 shrd edx, ebx, 4 shr bl, 4 jmp dreal8 dreal6: shld ebx, edx, 4 shl edx, 4 dreal7: cmp bl, al jb dreal6 dreal8: lda cx mov ah, bl rol edx, 16 dreals: push edx call savwor pop ax xchg ah, al call savwor pop ax xchg ah, al call savwor dec si lodsb cmp al, ',' je dtar2 jmp dtanp putdig: cmp bl, 10h jnb rlret shld ebx, edx, 4 shl edx, 4 add dl, al ret getsgn: call get cmp al, '-' stc je sgnret cmp al, '+' je sgnret ; C=0 dec si sgnret: rcr di, 1 rlret: ret getdig: call get cmp al, '0' jb rlret cmp al, '9'+1 cmc jb rlret sub al, '0' ret p_icl: call rfname pop ax push di call linend mov dx, offset (icl).nam add dx, [iclen] pop di call adasx jmp opfile p_ins: call rfname xor eax, eax mov [insofs], eax mov [inslen], ax lodsb cmp al, ',' jne p_ii2 push di call getval jc unknow mov [insofs], eax lodsb cmp al, ',' jne p_ii1 call getpos mov [inslen], ax inc si p_ii1: pop di p_ii2: dec si push si call fopen mov dx, [word insofs] mov cx, [word high insofs] mov ax, 4200h jcxz p_ip1 mov al, 2 p_ip1: call fsrce p_in1: mov cx, [inslen] jcxz p_in2 test ch, ch jz p_in3 p_in2: mov cx, 256 p_in3: mov dx, offset tlabel call fread jz p_inx cwde mov bx, [iclen] mov bx, [(icl bx).prev] add [(icl bx).line], eax mov si, offset tlabel push ax sta cx p_inp: lodsb push cx call savbyt pop cx loop p_inp pop ax cmp [inslen], 0 jz p_in1 sub [inslen], ax jnz p_in1 p_inx: call fclose pop si cmp [inslen], 0 jz rlret error e_fshor p_end: pop ax call linend jmp filend p_ift: shl [elflag], 1 jc etmift shl [cmflag], 1 shl [skflag], 1 ift1: cmp [skflag], 0 jnz cndret call spaval jc unknow test eax, eax jnz ift2 ift0: setflag [skflag], 1 ret p_els: bts [elflag], 0 jc cnderr ift2: bts [cmflag], 0 jc ift0 maskflag [skflag], not 1 cndret: ret p_eli: maskflag [skflag], not 1 testflag [elflag], 1 jz ift1 cnderr: cmp [elflag], 1 je emift error e_eifex p_eif: shr [skflag], 1 shr [cmflag], 1 shr [elflag], 1 jnz cndret emift: error e_mift etmift: error e_tmift IF EXE ENDS DATASEG ; ORG 0 ENDIF ; addressing modes: ; 0-@ 1-# 2-A 3-Z 4-A,X 5-Z,X 6-A,Y 7-Z,Y 8-(Z,X) 9-(Z),Y 10-(A) lentab db 1,2,3,2,3,2,3,2,2,2,3 acctab db 0,9,0dh,5,1dh,15h,19h,19h,1,11h,0 srttab db 0ah,0,0eh,6,1eh,16h lditab db 0,0,0ch,4,1ch,14h,1ch,14h inwtab db 0eeh,0e6h,0feh,0f6h ; pseudo-adr modes: 2-X+ 3-X- 4-Y+ 5-Y- ; +8-,0) +16-),0 sfxtab db 0,0,0e8h,0cah,0c8h,088h movtab movt <0a0h,p_ac1,080h,p_ac1,0,0> movt <0a2h,p_ld1,086h,p_st1,0e8h,0cah> movt <0a0h,p_ld1,084h,p_st1,0c8h,088h> comtab = $ cmd ADC0060p_acc cmd ADD8018p_ads cmd AND0020p_acc cmd ASL0000p_srt cmd BCC0090p_bra cmd BCS00b0p_bra cmd BEQ00f0p_bra cmd BIT002cp_bit cmd BMI0030p_bra cmd BNE00d0p_bra cmd BPL0010p_bra cmd BRK0000p_imp cmd BVC0050p_bra cmd BVS0070p_bra cmd CLC0018p_imp cmd CLD00d8p_imp cmd CLI0058p_imp cmd CLV00b8p_imp cmd CMP00c0p_acc cmd CPX00e0p_cpi cmd CPY00c0p_cpi cmd DEC00c0p_srt cmd DEX00cap_imp cmd DEY0088p_imp cmd DTA8000p_dta cmd EIFe000p_eif cmd ELIe000p_eli cmd ELSe000p_els cmd ENDe000p_end cmd EOR0040p_acc cmd EQUe000p_equ cmd ERTe000p_ert cmd ICLe000p_icl cmd IFTe000p_ift cmd INC00e0p_srt cmd INIf0e2p_rui cmd INSf000p_ins cmd INW8000p_inw cmd INX00e8p_imp cmd INY00c8p_imp cmd JCC80b0p_juc cmd JCS8090p_juc cmd JEQ80d0p_juc cmd JMI8010p_juc cmd JMP004cp_jmp cmd JNE80f0p_juc cmd JPL8030p_juc cmd JSR0020p_jsr cmd JVC8070p_juc cmd JVS8050p_juc cmd LDA00a0p_acc cmd LDX00a2p_ldi cmd LDY00a0p_ldi cmd LSR0040p_srt cmd MVA8000p_mvs cmd MVX8008p_mvs cmd MVY8010p_mvs cmd MWA8000p_mws cmd MWX8008p_mws cmd MWY8010p_mws cmd NOP00eap_imp cmd OPTe000p_opt cmd ORA0000p_acc cmd ORGf000p_org cmd PHA0048p_imp cmd PHP0008p_imp cmd PLA0068p_imp cmd PLP0028p_imp cmd RCC8890p_rep cmd RCS88b0p_rep cmd REQ88f0p_rep cmd RMI8830p_rep cmd RNE88d0p_rep cmd ROL0020p_srt cmd ROR0060p_srt cmd RPL8810p_rep cmd RTI0040p_imp cmd RTS0060p_imp cmd RUNf0e0p_rui cmd RVC8850p_rep cmd RVS8870p_rep cmd SBC00e0p_acc cmd SCC8490p_skp cmd SCS84b0p_skp cmd SEC0038p_imp cmd SED00f8p_imp cmd SEI0078p_imp cmd SEQ84f0p_skp cmd SMI8430p_skp cmd SNE84d0p_skp cmd SPL8410p_skp cmd STA0080p_acc cmd STX0086p_sti cmd STY0084p_sti cmd SUB8038p_ads cmd SVC8450p_skp cmd SVS8470p_skp cmd TAX00aap_imp cmd TAY00a8p_imp cmd TSX00bap_imp cmd TXA008ap_imp cmd TXS009ap_imp cmd TYA0098p_imp comend = $ operpa = $ opr 1ret opr 6add opr 6sub opr 7mul opr 7div opr 7mod opr 7and opr 6or opr 6xor opr 5equ opr 5les opr 5grt opr 7sal opr 7sar opr 5leq opr 5geq opr 5neq opr 5neq opr 5equ opr 3anl opr 2orl opr 8plu opr 8neg opr 8low opr 8hig opr 4nol opr 8not opert2 db '<<>><=>=<>!===&&||' noper2 = ($-opert2)/2 opert1 db '+-*/%&|^=<>' noper1 = $-opert1 opert0 db '+-<>!~' noper0 = $-opert0 IF FUNCTIONS funtxt db 'ABS(ANG(HYP(MAX(MIN(SQR(' nfun = ($-funtxt)/4 funvec dw f_abs,f_ang,f_hyp,f_max,f_min,f_sqr ENDIF opttxt db 'F-F+G-G+H-H+L-L+O-O+' optvec dw optf0,optf1,optg0,optg1,opth0,opth1,optl0,optl1,opto0,opto1 cndtxt dd 'DNE','TFI','ILE','SLE','FIE' cndvec dw pofend,0,p_ift,0,p_eli,0,p_els,0,p_eif swilet db 'UT' IF CONVERT_TO_TABS db 'S' ENDIF db 'QPO' IF POOR_MAN_MAKE db 'N' ENDIF db 'LIEDC' NUM_SWITCHES = $-swilet hello db 'xasm 2.6.1' IF SET_WIN_TITLE titfin db 0,10 ELSE db eol ENDIF hellen = $-hello usgtxt db "Syntax: XASM source [options]",eol db "/c Include false conditionals in listing",eol db "/d:label=value Define a label",eol db "/e Set environment variables ERRFILE and ERRLINE",eol db "/i Don't list included files",eol db "/l[:filename] Generate listing",eol IF POOR_MAN_MAKE db "/n Assemble only if source file is newer than object file",eol ENDIF db "/o:filename Set object file name",eol db "/p Print fully qualified file names in listing and error messages",eol db "/q Suppress info messages",eol IF CONVERT_TO_TABS db "/s Don't convert spaces to tabs in listing",eol ENDIF db "/t[:filename] List label table",eol db "/u Warn of unused labels",eot IF POOR_MAN_MAKE oldtxt db 'Source file is older than object file - not assembling',cr ENDIF envtxt db 'Can''t modify environment',cr objtxt db 'Writing object file...',eot lsttxt db 'Writing listing file...' eoltxt db eot srctxt db 'Source: ' srctxl = $-srctxt tabtxt db 'Label table:',eol tabtxl = $-tabtxt lintxt db ' lines of source assembled',eot byttxt db ' bytes written to the object file',eot dectxt db 10 dup(' '),'$' wartxt db 'WARNING: ' wartxl = $-wartxt w_bugjp db 'Buggy indirect jump',eol w_bras db 'Plain branch instruction would be sufficient',eol w_ulab db 'Unused label',eol w_skif db 'Skipping only the first instruction',eol w_repl db 'Repeating only the last instruction',eol errtxt db 'ERROR: ' errtxl = $-errtxt e_open db 'Can''t open file',cr e_read db 'File read error',cr e_crobj db 'Can''t write to the object file',cr e_wrobj db 'Error writing to the object file',cr e_crlst db 'Can''t write to the listing file',cr e_wrlst db 'Error writing to the listing file',cr e_icl db 'Too many files nested',cr e_long db 'Line too long',cr e_uneol db 'Unexpected end of line',cr e_char db 'Illegal character',cr e_twice db 'Label declared twice',cr e_inst db 'Illegal instruction',cr e_nbig db 'Number too big',cr e_xtra db 'Extra characters on line',cr e_label db 'Label name required',cr e_str db 'String error',cr e_orgs db 'Too many ORGs',cr e_paren db 'Need parenthesis',cr e_tlab db 'Too many labels',cr e_amod db 'Illegal addressing mode',cr e_bra db 'Branch out of range by $' brout db ' bytes',cr e_func db 'Bad or missing function parameter',cr e_spac db 'Space expected',cr e_opt db 'Invalid option',cr e_over db 'Arithmetic overflow',cr e_div0 db 'Divide by zero',cr e_range db 'Value out of range',cr e_uknow db 'Label not defined before',cr e_undec db 'Undeclared label',cr e_fref db 'Illegal forward reference',cr e_wpar db 'Use square brackets instead',cr e_brack db 'Unmatched bracket',cr e_user db 'User error',cr e_tmift db 'Too many IFTs nested',cr e_eifex db 'EIF expected',cr e_mift db 'Missing IFT',cr e_meif db 'Missing EIF',cr e_norg db 'No ORG specified',cr e_fshor db 'File is too short',cr e_hoff db 'Illegal when Atari file headers disabled',cr e_crep db 'Can''t repeat this directive',cr e_opcod db 'Can''t get opcode of this',cr e_ropco db 'Nested opcodes not supported',cr e_mopco db 'Missing ''}''',cr e_pair db 'Can''t pair this directive',cr e_skit db 'Can''t skip over this',cr e_repa db 'No instruction to repeat',cr e_5200 db 'There''s no PIA chip in Atari 5200',cr e_fill db 'Can''t fill from higher to lower memory location',cr e_nomac db 'Sorry, Mac EOLs are no longer supported',cr e_ctr db '''#'' is allowed only in repeated lines',cr ;;e_fatal db 'Internal error. Please report to fox@scene.pl',cr clitxt db 'command line' clitxl = $-clitxt fillbyt db 0ffh exitcod dw 4c00h ohand dw nhand lhand dw nhand flags dw m_norg+m_rorg+m_rqff+m_hdr+m_wobj swits dw 0 lines dd 0 bytes dd 0 srcen dw 0 iclen dw t_icl defen dw t_def laben dw t_lab pslab dw t_lab elflag dd 1 cmflag dd 0 skflag dd 0 loopctr dd -1 sinmin dw 1 sinmax dw 0 sinadd dd ? sinamp dd ? sinsiz dw ? fillfl dw ? flist db ? fslen dw ? times dw ? cmdvec dw ? scdvec dw ? opcosp dw ? insofs dd ? inslen dw ? IF RELOC_ORG ldorg dw ? ENDIF origin dw ? curorg dw ? orgvec dw ? defvec dw ? reporg dw ? eolpos dw ? lstidx dw ? labvec dw ? obufpt dw ? oword dw ? IF POOR_MAN_MAKE objmod dd ? ENDIF op1 dd ? dw ? op2 dd ? dw ? tempsi dw ? errmsg dw ? envofs dw ? envseg dw ? envnam dw ? envnum dw ? envlen dw ? chbuf db ? var = $ MACRO bb _name _name&o = $-var _name equ byte bp+_name&o db ? ENDM MACRO bw _name _name&o = $-var _name equ word bp+_name&o dw ? ENDM bw val dw ? bb amod db ? bb ukp1 db ? bb cod var2 db ($-var) dup(?) IF COMPAK ELSE undata ENDIF t_lab db l_lab dup(?) IF EXE stak db 400h dup(?) staken = $ ENDS STACK 100h ENDIF ENDS END start