1
0
mirror of https://github.com/pfusik/xasm.git synced 2024-06-01 01:41:29 +00:00
xasm/xasm.asm
2013-01-07 12:07:27 +01:00

2404 lines
36 KiB
NASM

; X-Assembler
IDEAL
P386
MODEL TINY
CODESEG
compak = 6*1024
l_icl = 1024
l_org = 4096
l_lab = 50000
STRUC com
cod db ?
nam db ?,?,?
vec dw ?
ENDS
STRUC icl
prev dw ?
handle dw ?
line dd ?
nam db ?
ENDS
STRUC lab
val dw ?
flags db ?
b_sign = 7
m_sign = 80h
m_lnus = 40h
m_ukp1 = 20h
len db ?
nam db ?
ENDS
STRUC movt
cod db ?
vec dw ?
ENDS
;[flags]
m_pass = 1
m_eofl = 2
m_skip = 4
m_norg = 8
m_rorg = 10h
m_rqff = 20h
b_hdr = 6
m_hdr = 40h
;[swits]
m_swc = 1
m_swi = 2
m_swl = 4
m_swo = 8
m_sws = 10h
m_swt = 20h
;[flist]
m_lstc = 1
m_lsti = 2
m_lstl = 4
m_lsto = 8
m_lsts = m_lsto+m_lstl+m_lsti
nhand = -1 ;null handle
eol equ 13,10
eot equ 13,10,'$'
MACRO lda _rg ;shorter than 'mov (e)ax, _rg'
_rge SUBSTR <_rg>, 1, 1
IFIDNI _rge, <e>
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, <e>
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 bp, offset _errtx
ENDIF
IF _func and 0ff00h
mov ax, _func
ELSE
mov ah, _func
ENDIF
call 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 jpass1 _dest
test [flags], m_pass
jz _dest
ENDM
MACRO jpass2 _dest
test [flags], m_pass
jnz _dest
ENDM
MACRO cmd _oper
_tp SUBSTR <_oper>, 4, 2
_tp CATSTR <0>, &_tp, <h>
db _tp
IRP _ct,<3,2,1>
_tp SUBSTR <_oper>, _ct, 1
% db '&_tp'
ENDM
_tp SUBSTR <_oper>, 6
dw _tp
ENDM
MACRO opr _oper
_tp SUBSTR <_oper>, 1, 1
db _tp
_tp SUBSTR <_oper>, 2
_tp CATSTR <v_>, _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(?)
objnam db 128 dup(?)
lstnam db 128 dup(?)
tabnam db 128 dup(?)
t_icl db l_icl dup(?)
t_org db l_org dup(?)
ENDM
;*****************************
zero db 100h dup(?)
start:
IFDEF compak
undata
db compak+start-$ dup(?)
ENDIF
print hello
mov di, 81h
movzx cx, [di-1]
jcxz usg
mov al, ' '
repe scasb
je usg
dec di
inc cx
mov si, di
mov al, '?'
repne scasb
jne begin
usg: print usgtxt
dos 4c02h
begin: lodsb
cmp al, '/'
je usg
mov di, offset (icl t_icl).nam+1
lea dx, [di-1]
xor ah, ah
mov [tabnam], ah
dinam equ di-t_icl-offset (icl).nam
mnam1: dec di
mov [objnam+dinam], ax
mov [lstnam+dinam], ax
stosw
lodsb
cmp al, ' '
je mnam2
cmp al, '/'
je mnam2
cmp al, 0dh
jne mnam1
mnam2: dec si
call adasx
mov [fslen], di
chex1: dec di
cmp [byte di], '.'
jne chex1
mov [byte objnam+dinam], '.'
mov [dword objnam+dinam+1], 'XBO'
mov [byte lstnam+dinam], '.'
mov [dword lstnam+dinam+1], 'TSL'
gsw1: lodsb
cmp al, ' '
je gsw1
cmp al, 0dh
je gswx
cmp al, '/'
jne usg
lodsb
and al,0dfh
mov di, offset swilet
mov cx, 6
repne scasb
jne usg
bts [word swits], cx
jc usg
mov di, offset lstnam
mov ecx, 'TSL'
cmp al, 'L'
je gsw2
mov di, offset tabnam
mov ecx, 'BAL'
cmp al, 'T'
je gsw2
cmp al, 'O'
jne gsw1
cmp [byte si], ':'
jne usg
mov di, offset objnam
mov ecx, 'XBO'
gsw2: cmp [byte si], ':'
jne gsw1
inc si
mov dx, di
gsw3: lodsb
stosb
cmp al, ' '
je gsw4
cmp al, '/'
je gsw4
cmp al, 0dh
jne gsw3
gsw4: mov [byte di-1], 0
lda ecx
call adext
dec si
jmp gsw1
gswx: mov al, [swits]
not al
and al, m_lstl+m_lstc
or al, m_lsto
mov [flist], al
npass: mov [orgvec], offset t_org-2
mov di, [fslen]
opfile: call fopen
main: test [flags], m_eofl
jnz filend
mov bx, [iclen]
mov bx, [(icl bx).prev]
inc [(icl bx).line]
inc [lines]
mov di, offset line
test [swits], m_swi
jz gline1
and [flist], not m_lsti
cmp bx, offset t_icl
jbe gline1
or [flist], m_lsti
gline1: cmp di, offset line+256
jnb linlon
mov cx, 1
mov dx, di
call fread
mov ax, 0a0dh
jz eof
dec di
scasw
jne gline1
jmp syntax
eof: or [flags], m_eofl
stosw
syntax: call lsplen
mov si, offset line
mov al, [si]
cmp al, 0dh
je lsteol
cmp al, '*'
je lstrem
cmp al, ';'
je lstrem
cmp al, '|'
je lstrem
test [flags], m_skip
jz nskip
skip1: call get
cmp al, ' '
je skip2
cmp al, 9
jne skip1
skip2: call space1
lodsd
and eax, 0dfdfdfh
cmp eax, 'DNE'
je filend
push offset lstrem
cmp eax, 'TFI'
je skift
cmp eax, 'SLE'
je skels
cmp eax, 'FIE'
jne skret
call p_eif
dec [sift]
jns skret
and [flags], not m_skip
inc [sift] ;0
skret: ret
skift: call shlelf
inc [sift]
ret
skels: call btself
cmp [sift], 0
jnz skret
jmp fliski
lsteol: call chklst
jnz main
mov di, offset lstspa
call lspeol
call putlnm
jmp main
lstrem: call chklst
jnz main
mov di, offset lstspa+1
call putlsp
jmp main
nskip: mov [labvec], 0
cmp al, ' '
je s_cmd
cmp al, 9
je s_cmd
jpass2 deflp2
call flabel
jnc ltwice
mov di, [laben]
mov [labvec], di
mov ax, [origin]
stosw
mov al, m_lnus
mov ah, dl
stosw
mov cx, dx
sub cl, 4
lda si
mov si, offset tlabel
rep movsb
sta si
mov [laben], di
cmp di, offset t_lab+l_lab-4
jb s_cmd
error e_tlab
ltwice: error e_twice
deflp2: call rlabel
mov ax, [pslab]
mov [labvec], ax
add [pslab], dx
s_cmd: lodsb
cmp al, ' '
je s_cmd
cmp al, 9
je s_cmd
cmp al, 0dh
jne s_cmd1
cmp [byte high labvec], 0
je lsteol
jmp uneol
s_cmd1: dec si
mov di, offset lstorg
test [flags], m_norg
jnz nlorg
mov ax, [origin]
call phword
mov al, ' '
stosb
nlorg: mov [lstidx], di
lodsw
and ax, 0dfdfh
xchg al, ah
shl eax, 16
mov ah, 0dfh
and ah, [si]
test [flags], m_norg
jz lbnox
cmp [byte high labvec], 0
je lbnox
cmp eax, 'EQU' shl 8
jne noorg
lbnox: inc si
mov di, offset comtab
mov bx, 64*size com
sfcmd1: mov al, [(com di+bx).cod]
cmp eax, [dword (com di+bx).cod]
jb sfcmd3
jne sfcmd2
mov [cod], al
call [(com di+bx).vec]
call linend
jmp main
sfcmd2: add di, bx
cmp di, offset comend
jb sfcmd3
sub di, bx
sfcmd3: shr bx, 1
cmp bl, 3
ja sfcmd1
mov bl, 0
je sfcmd1
error e_inst
skend: call chklst
jnz filend
mov di, offset lstspa+1
call putlsp
filend: and [flags], not m_eofl
call fclose
cmp bx, offset t_icl
ja main
jpass2 fin
cmp [elflag], 1
jne miseif
or [flags], m_pass+m_norg+m_rorg+m_rqff+m_hdr
and [flist], not m_lsto
jmp npass
fin: mov bx, [ohand]
mov bp, offset e_wrobj
call hclose
test [swits], m_swt
jz nlata
cmp [laben], offset t_lab
jbe nlata
cmp [byte tabnam], 0
jnz oplata
cmp [lhand], nhand
jne latt1
call opnlst
jmp latt2
latt1: call plseol
jmp latt2
oplata: call lclose
mov dx, offset tabnam
call opntab
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
mov ax, [(lab si).val]
test [(lab si).flags], m_sign
jz lata4
mov [byte di-1], '-'
neg ax
lata4: call phword
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 lspeol
call putlst
cmp si, [laben]
jb lata1
nlata: call lclose
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
linlon: push offset e_long
jmp erron
miseif: push offset e_meif
jmp erron
; ERROR
errln: call ppline
erron: call prname
print errtxt
pop si
call prline
dos 4c02h
; WARNING
warln: call ppline
waron: call prname
print wartxt
pop ax
pop si
push ax
mov [byte exitcod], 1
jmp prline
prname: mov bx, [iclen]
cmp bx, offset t_icl
jna prnamx
mov di, [(icl bx).prev]
push di
lea dx, [(icl di).nam]
mov [byte bx-1], '$'
print
mov dl, ' '
dos 2
mov dl, '('
dos 2
pop bx
mov eax, [(icl bx).line]
call pridec
mov dl, ')'
dos 2
mov dl, ' '
dos 2
prnamx: ret
ppline: mov si, offset line
prline: mov dl, [si]
dos 2
inc si
cmp [byte si-1], 0ah
jne prline
ret
; I/O
xdisk: push bp
dos
jc erron
pop bp
ret
icler: push offset e_icl
jmp erron
lclose: mov bx, [lhand]
mov bp, offset e_wrlst
mov [lhand], nhand
hclose: cmp bx, nhand
je cloret
file 3eh
cloret: ret
fopen: cmp di, offset t_icl+l_icl-2
jnb icler
mov bx, [iclen]
mov [(icl bx).line], 0
lea dx, [(icl bx).nam]
mov [(icl di).prev], bx
mov [iclen], di
file 3d00h, e_open
mov bx, [iclen]
mov bx, [(icl bx).prev]
mov [(icl bx).handle], ax
ret
fread: mov ah, 3fh
fread1: mov bx, [iclen]
mov bx, [(icl bx).prev]
mov bx, [(icl bx).handle]
mov bp, offset e_read
call xdisk
test ax, ax
ret
fclose: mov ah, 3eh
call fread1
mov bx, [iclen]
cmp bx, [srcen]
jne fclos1
mov [srcen], 0
fclos1: mov bx, [(icl bx).prev]
mov [iclen], bx
ret
putwor: push ax
call putbyt
pop ax
mov al, ah
putbyt: jpass1 putx
mov [obyte], al
cmp [ohand], nhand
jne putb1
mov dx, offset objnam
xor cx, cx
file 3ch, e_crobj
mov [ohand], ax
print objtxt
putb1: mov bx, [ohand]
mov dx, offset obyte
mov cx, 1
file 40h, e_wrobj
inc [bytes]
putx: ret
orgwor: push ax
call phword
pop ax
jmp putwor
chorg: test [flags], m_norg
jz putx
noorg: error e_norg
tmorgs: error e_orgs
savwor: push ax
call savbyt
pop ax
mov al, ah
savbyt: mov [sbyte], al
call chorg
test [flags], m_hdr
jz savb1
mov ax, [origin]
test [flags], m_rorg
jnz borg1
cmp ax, [curorg]
je borg3
borg1: add [orgvec], 2
jpass1 borg2
mov di, offset lstorg
test [flags], m_rqff
jz noff
mov ax, 0ffffh
call orgwor
mov ax, ' >'
stosw
mov ax, [origin]
noff: call orgwor
mov al, '-'
stosb
mov bx, [orgvec]
mov ax, [bx]
call orgwor
mov ax, ' >'
stosw
mov [lstidx], di
mov ax, [origin]
borg2: and [flags], not (m_rorg+m_rqff)
borg3: jpass2 borg4
mov di, [orgvec]
stosw
borg4: inc ax
mov [curorg], ax
savb1: inc [origin]
test [flist], m_lsts
jnz lsbpop
mov di, [lstidx]
cmp di, offset line-3
jae lstxtr
mov al, [sbyte]
call phbyte
mov al, ' '
lstpls: stosb
mov [lstidx], di
lsbpop: mov al, [sbyte]
jmp putbyt
lstxtr: ja lsbpop
mov al, '+'
jmp lstpls
chklst: mov al, m_lsts
test [flags], m_skip
jz chkls1
mov al, m_lsts+m_lstc
chkls1: test al, [flist]
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
linen1: test [flist], m_lsts
jnz linret
mov di, [lstidx]
putlsp: call putspa
; Listuje linie z numerem
putlnm: mov di, offset lstspa
mov bx, [iclen]
mov bx, [(icl bx).prev]
mov eax, [(icl bx).line]
call numdec
lstlsp: dec di
mov [byte di], ' '
cmp di, offset lstnum
ja lstlsp
mov bx, [iclen]
cmp bx, [srcen]
je nlsrc
mov [srcen], bx
cmp [lhand], nhand
jne lsrc1
call opnlst
lsrc1: mov dx, offset srctxt
mov cx, offset srctxl
call putlad
mov bx, [iclen]
mov cx, bx
mov bx, [(icl bx).prev]
lea dx, [(icl bx).nam]
stc
sbb cx, dx
call putlad
call plseol
nlsrc:
test [swits], m_sws
jnz putlst
mov si, offset lstnum
mov di, si
spata1: xor dl, dl
spata2: lodsb
stosb
cmp al, 0ah
je spatax
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
spatax: call lsplen
; Zapis linii lstnum o dlug. linlen
putlst: mov dx, offset lstnum
mov cx, [linlen]
putlad: mov bx, [lhand]
file 40h, e_wrlst
linret: ret
opnlst: mov dx, offset lstnam
opntab: xor cx, cx
file 3ch, e_crlst
mov [lhand], ax
print lsttxt
mov dx, offset hello
mov cx, hellen
jmp putlad
plseol: mov dx, offset eoltxt
mov cx, 2
jmp putlad
lspeol: mov ax, 0a0dh
stosw
lsplen: lea ax, [di+zero-lstnum]
mov [linlen], ax
ret
adasx: mov eax, 'XSA'
; Dodaje rozszerzenie nazwy, gdy go nie ma
; we: dx,di-poczatek,koniec nazwy; eax-rozsz.
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
; Zapisuje dziesietnie EAX; di-koniec liczby
numdec: mov ebx, 10
numde1: cdq
div ebx
add dl, '0'
dec di
mov [di], dl
test eax, eax
jnz numde1
ret
; Wyswietla dziesietnie EAX
pridec: mov di, offset dectxt+10
call numdec
mov dx, di
print
ret
; Zapisuje hex AX od [DI]
phword: push ax
mov al, ah
call phbyte
pop ax
phbyte: push ax
shr al, 4
call phdig
pop ax
and al, 0fh
phdig: cmp al, 10
sbb al, 69h
das
stosb
ret
; Pobiera znak (eol=error)
get: lodsb
cmp al, 0dh
je uneol
ret
uneol: error e_uneol
ilchar: error e_char
; Omija 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
; Zapisuje spacje od di do line
putspa: mov cx, offset line
sub cx, di
mov al, ' '
rep stosb
mov [lstspa], ' '
ret
; Czyta nazwe pliku
rfname: call spaces
mov di, offset (icl).nam
add di, [iclen]
; Czyta lancuch i zapisuje 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
; Przepisuje etykiete do tlabel (wyj: dx-dl.etykiety+4)
rlabel: mov di, offset tlabel
mov [byte di], 0
rlab1: lodsb
cmp al, '0'
jb rlabx
cmp al, '9'
jbe rlab2
cmp al, 'A'
jb rlabx
cmp al, 'Z'
jbe rlab2
cmp al, '_'
je rlab2
cmp al, 'a'
jb rlabx
cmp al, 'z'
ja rlabx
add al, 'A'-'a'
rlab2: stosb
cmp di, offset tlabel+252
jb rlab1
jmp linlon
rlabx: cmp [byte tlabel], 'A'
jb ilchar
lea dx, [di+zero-tlabel+lab.nam]
dec si
ret
; Czyta etykiete i szuka w t_lab
; wyj: dx-dlugosc etykiety+4
; C=0: znaleziona, bx=adres wpisu
; C=1: nie ma jej
flabel: call rlabel
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
lea bx, [si+tlabel-offset (lab).nam]
sub bx, di ;c=0
flabx: pop si
ret
wropar: error e_wpar
spaval: call spaces
; Czyta wyrazenie i zwraca jego wartosc w [val]
; (C=1 wartosc nieokreslona w pass 1)
getval: xor bx, bx
mov [ukp1], bh
push bx
v_lop:
v_par1: inc bh
call get
cmp al, '['
je v_par1
cmp al, '('
je wropar
cmp al, '-'
je valuem
dec si
mov al, '+'
valuem: mov bl, al
xor eax, eax
call get
cmp al, '*'
je valorg
cmp al, "'"
je valchr
cmp al, '"'
je valchr
cmp al, '^'
je valreg
mov bp, -1
xor edx, edx
mov ecx, 16
cmp al, '$'
je rdnum3
mov cl, 2
cmp al, '%'
je rdnum3
mov cl, 10
cmp al, '0'
jb ilchar
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 ebp, al
lda edx
mul ecx
add eax, ebp
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: jpass1 vlchuk
and [(lab bx).flags], not m_lnus
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: bt [word (lab bx).flags], b_sign
sbb eax, eax
mov ax, [(lab bx).val]
pop bx
jmp value1
valorg: call chorg
mov ax, [origin]
jmp value1
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
cmp al, '4'
ja ilchar
sub al, '0'
jb ilchar
add al, 0d0h
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
jne value1
sub ax, 0f0h
valre2: jmp value1
value0: dec si
test bp, bp
js ilchar
lda edx
value1: cmp bl, '-'
jne value2
neg eax
value2: 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
mov cx, noper1
repne scasb
je foper1
test bh, bh
jnz mbrack
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: lea ax, [di+operpa]
add di, di
add di, ax
mov bl, [di]
mov bp, [di+1]
pop eax
v_com: pop cx
cmp cx, bx
jb v_xcm
pop ecx
xchg eax, ecx
pop dx
push offset v_com
push dx
ret
v_xcm: cmp bl, 1
jbe v_xit
push cx bp eax bx
jmp v_lop
v_xit: mov [dword val], eax
cmp [ukp1], 1
cmc
jc v_ret
wrange: cmp eax, 10000h
cmc
jnb v_ret
cmp eax, -0ffffh
jb orange
ret
brange: cmp eax, 100h
jb v_ret
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
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
sta edx
v_ret: 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
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
je v_one
v_zer: xor eax, eax
ret
v_one: stc
sbb eax, eax
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
; Pobiera operand rozkazu i rozpoznaje 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 getad1
dec si
lodsw
and al, 0dfh
mov dl, 2
cmp ax, ':A'
je getad1
inc dx
cmp ax, ':Z'
je getad1
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
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
getaim: 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
getaid: lodsb
cmp al, ','
je getaix
cmp al, ')'
jne mparen
lodsw
mov dx, 709h
cmp ax, '0,'
je getadx
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, 6
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, 6
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
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, 0c0h
je ilamod
cmp al, 0e0h
je ilamod
putsfx: call putcmd
mov al, [amod+1]
mov bx, offset sfxtab
xlat
test al, al
jnz savbyt
putret: ret
p_inw: call getadr
cmp al, 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
je cod8
mov al, 4
jmp putcod
p_bra: call getadr
jpass1 bra1
mov ax, [val]
sub ax, [origin]
add ax, 7eh
test ah, ah
jnz toofar
add al, 80h
mov [byte val], al
mov al, [cod]
bra1: call savbyt
mov al, [byte val]
jmp savbyt
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 getadr
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
mov ax, [val]
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
mov di, offset op1
call stop
push [word ukp1]
call getadr
pop [word ukp1]
mov [tempsi], si
mov di, offset op2
call stop
movzx bx, [cod]
add bx, offset movtab
ldop1: mov si, offset 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).cod]
mov [cod], al
push bx
call [(movt bx).vec]
pop bx
ret
mcall2: mov al, [(movt bx+3).cod]
mov [cod], al
push bx
call [(movt bx+3).vec]
pop bx
ret
p_mvs: call getops
call mcall1
mov si, offset 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
mov [byte high val], 0
mov [word val+2], 0
p_mw1: call mcall1
mov si, offset 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: movzx eax, [byte high val]
cmp [ukp1], ah ;0
jnz p_mwh
cmp al, [byte val]
je p_mw3
p_mwh: mov [dword val], eax
p_mw2: call mcall1
p_mw3: mov si, offset op2
call ldop
inc [val]
jmp p_mvx
p_opt: call spaces
xor cx, cx
opt1: lodsw
and al, 0dfh
cmp al, 'L'
je optlst
cmp al, 'H'
je opthdr
jcxz opter
dec si
dec si
ret
opter: error e_opt
optlst: inc cx
cmp ah, '+'
je optl1
cmp ah, '-'
jne opter
or [flist], m_lsto
jmp opt1
optl1: jpass1 opt1
and [flist], not m_lsto
jmp opt1
opthdr: inc cx
cmp ah, '+'
je opth1
cmp ah, '-'
jne opter
and [flags], not (m_hdr+m_rqff)
jmp opt1
opth1: bts [word flags], b_hdr
jc opt1
or [flags], m_rorg
jmp opt1
p_ert: call spaval
jpass1 equret
test eax, eax
jz equret
error e_user
p_equ: mov di, [labvec]
test di, di
jz nolabl
mov [(lab di).val], 0
and [(lab di).flags], not m_sign
call spaval
mov di, [labvec]
jnc equ1
or [(lab di).flags], m_ukp1
equ1: mov [(lab di).val], ax
test eax, eax
jns equ2
or [(lab di).flags], m_sign
equ2: test [flist], m_lsts
jnz equret
sta dx
mov di, offset lstorg
mov ax, ' ='
test eax, eax
jns equ3
mov ah, '-'
neg dx
equ3: stosw
lda dx
call phword
mov [lstidx], di
equret: ret
nolabl: error e_label
chkhon: test [flags], m_hdr
jnz equret
error e_hoff
p_org: call spaces
and [flags], not m_norg
lodsw
and al, 0dfh
cmp ax, ':F'
je orgff
cmp ax, ':A'
je orgaf
dec si
dec si
jmp orget
orgff: or [flags], m_rqff
orgaf: or [flags], m_rorg
call chkhon
orget: call getuns
jc unknow
mov [origin], ax
ret
p_rui: call chkhon
mov ah, 2
mov [origin], ax
call spauns
jmp savwor
valuco: call getval
jc unknow
call get
cmp al, ','
jne badsin
mov ax, [val]
ret
badsin: error e_sin
p_dta: call spaces
dta1: call get
and al, 0dfh
mov [cod], al
cmp al, 'A'
je dtan1
cmp al, 'B'
je dtan1
cmp al, 'L'
je dtan1
cmp al, 'H'
je dtan1
cmp al, 'C'
je dtat1
cmp al, 'D'
je dtat1
cmp al, 'R'
je dtar1
jmp ilchar
dtan1: lodsb
cmp al, '('
jne mparen
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 badsin
call valuco
test eax, eax
js badsin
mov [sinmin], ax
call getuns
jc unknow
cmp ax, [sinmin]
jb badsin
mov [sinmax], ax
lodsb
cmp al, ')'
jne mparen
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
lodsb
cmp al, ','
je dtan2
cmp al, ')'
je dtanxt
mparen: 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
ret
dtar1: lodsb
cmp al, '('
jne mparen
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
jmp ilchar
dreal2: mov bh, 1
test al, al
jz dreal1
dec cx
dreal3: inc cx
call putdig
call getdig
jnc dreal3
cmp al, '.'
je drealp
and al, 0dfh
cmp al, 'E'
jne drealf
dreale: call getsgn
call getdig
jc ilchar
mov ah, al
call getdig
jnc dreal4
shr ax, 8
dreal4: aad
add di, di
jnc drealn
neg ax
drealn: add cx, ax
jmp drealf
dreal5: test edx, edx
jnz dreal9
test bl, bl
jnz dreal9
dec cx
dreal9: call putdig
drealp: call getdig
jnc dreal5
and al, 0dfh
cmp al, 'E'
je dreale
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
dreals: rol edx, 16
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
cmp al, ')'
jne mparen
jmp dtanxt
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, '+'
clc
je sgnret
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 fread1
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
shlelf: shl [elflag], 1
jnc cndret
error e_tmift
btself: bts [elflag], 0
jnc cndret
error e_eifex
p_ift: call spaval
jc unknow
call shlelf
test eax, eax
jz fliski
cndret: ret
p_els: cmp [elflag], 1
je misift
call btself
fliski: xor [flags], m_skip
ret
p_eif: shr [elflag], 1
jnz cndret
misift: error e_mift
; 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- 6-,0) 7-),0
sfxtab db 0,0,0e8h,0cah,0c8h,088h,0,0
movtab movt <0a0h,p_ac1>,<080h,p_ac1>
movt <0a2h,p_ld1>,<086h,p_st1>
movt <0a0h,p_ld1>,<084h,p_st1>
comtab: cmd ADC60p_acc
cmd ADD18p_ads
cmd AND20p_acc
cmd ASL00p_srt
cmd BCC90p_bra
cmd BCSb0p_bra
cmd BEQf0p_bra
cmd BIT2cp_bit
cmd BMI30p_bra
cmd BNEd0p_bra
cmd BPL10p_bra
cmd BRK00p_imp
cmd BVC50p_bra
cmd BVS70p_bra
cmd CLC18p_imp
cmd CLDd8p_imp
cmd CLI58p_imp
cmd CLVb8p_imp
cmd CMPc0p_acc
cmd CPXe0p_cpi
cmd CPYc0p_cpi
cmd DECc0p_srt
cmd DEXcap_imp
cmd DEY88p_imp
cmd DTA00p_dta
cmd EIF00p_eif
cmd ELS00p_els
cmd END00p_end
cmd EOR40p_acc
cmd EQU00p_equ
cmd ERT00p_ert
cmd ICL00p_icl
cmd IFT00p_ift
cmd INCe0p_srt
cmd INIe2p_rui
cmd INS00p_ins
cmd INW00p_inw
cmd INXe8p_imp
cmd INYc8p_imp
cmd JCCb0p_juc
cmd JCS90p_juc
cmd JEQd0p_juc
cmd JMI10p_juc
cmd JMP4cp_jmp
cmd JNEf0p_juc
cmd JPL30p_juc
cmd JSR20p_jsr
cmd JVC70p_juc
cmd JVS50p_juc
cmd LDAa0p_acc
cmd LDXa2p_ldi
cmd LDYa0p_ldi
cmd LSR40p_srt
cmd MVA00p_mvs
cmd MVX06p_mvs
cmd MVY0cp_mvs
cmd MWA00p_mws
cmd MWX06p_mws
cmd MWY0cp_mws
cmd NOPeap_imp
cmd OPT00p_opt
cmd ORA00p_acc
cmd ORG00p_org
cmd PHA48p_imp
cmd PHP08p_imp
cmd PLA68p_imp
cmd PLP28p_imp
cmd ROL20p_srt
cmd ROR60p_srt
cmd RTI40p_imp
cmd RTS60p_imp
cmd RUNe0p_rui
cmd SBCe0p_acc
cmd SEC38p_imp
cmd SEDf8p_imp
cmd SEI78p_imp
cmd STA80p_acc
cmd STX86p_sti
cmd STY84p_sti
cmd SUB38p_ads
cmd TAXaap_imp
cmd TAYa8p_imp
cmd TSXbap_imp
cmd TXA8ap_imp
cmd TXS9ap_imp
cmd TYA98p_imp
comend:
operpa: opr 1ret
opr 5add
opr 5sub
opr 6mul
opr 6div
opr 6mod
opr 6and
opr 5or
opr 5xor
opr 4equ
opr 4les
opr 4grt
opr 6sal
opr 6sar
opr 4leq
opr 4geq
opr 4neq
opr 4neq
opr 3anl
opr 2orl
opert2 db '<<>><=>=<>!=&&||'
noper2 = ($-opert2)/2
opert1 db '+-*/%&|^=<>'
noper1 = $-opert1
swilet db 'TSOLIC'
hello db 'X-Assembler 2.0 by Fox/Taquart',eot
hellen = $-hello-1
usgtxt db "Syntax: XASM source [options]",eol
db "/c List false conditionals",eol
db "/i Don't list included source",eol
db "/l[:fname] Generate listing",eol
db "/o:fname Write object as 'fname'",eol
db "/s Don't convert spaces to tabs in listing",eol
db "/t[:fname] List label table",eot
objtxt db 'Writing object...',eot
lsttxt db 'Writing listing...'
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 object',eot
dectxt db 10 dup(' '),'$'
wartxt db 'WARNING: $'
w_bugjp db 'Buggy indirect jump',eol
w_bras db 'Branch would be sufficient',eol
errtxt db 'ERROR: $'
e_open db 'Can''t open file',eol
e_read db 'Disk read error',eol
e_crobj db 'Can''t write object',eol
e_wrobj db 'Error writing object',eol
e_crlst db 'Can''t write listing',eol
e_wrlst db 'Error writing listing',eol
e_icl db 'Too many files nested',eol
e_long db 'Line too long',eol
e_uneol db 'Unexpected eol',eol
e_char db 'Illegal character',eol
e_twice db 'Label declared twice',eol
e_inst db 'Illegal instruction',eol
e_nbig db 'Number too big',eol
e_xtra db 'Extra characters on line',eol
e_label db 'Label name required',eol
e_str db 'String error',eol
e_orgs db 'Too many ORGs',eol
e_paren db 'Need parenthesis',eol
e_tlab db 'Too many labels',eol
e_amod db 'Illegal addressing mode',eol
e_bra db 'Branch out of range by $'
brout db ' bytes',eol
e_sin db 'Bad or missing sinus parameter',eol
e_spac db 'Space expected',eol
e_opt db 'Invalid options',eol
e_over db 'Arithmetic overflow',eol
e_div0 db 'Divide by zero',eol
e_range db 'Value out of range',eol
e_uknow db 'Label not defined before',eol
e_undec db 'Undeclared label',eol
e_fref db 'Illegal forward reference',eol
e_wpar db 'Use square brackets instead',eol
e_brack db 'Not matching brackets',eol
e_user db 'User error',eol
e_tmift db 'Too many IFTs nested',eol
e_eifex db 'EIF expected',eol
e_mift db 'Missing IFT',eol
e_meif db 'Missing EIF',eol
e_norg db 'No ORG specified',eol
e_fshor db 'File is too short',eol
e_hoff db 'Illegal when headers off',eol
exitcod dw 4c00h
ohand dw nhand
lhand dw nhand
flags db m_norg+m_rorg+m_rqff+m_hdr
swits db 0
sift db 0
lines dd 0
bytes dd 0
srcen dw 0
iclen dw t_icl
laben dw t_lab
pslab dw t_lab
elflag dd 1
sinmin dw 1
sinmax dw 0
sinadd dd ?
sinamp dd ?
sinsiz dw ?
val dw ?,?
amod db ?,?
ukp1 db ?,?
flist db ?
obyte db ?
sbyte db ?
cod db ?
origin dw ?
curorg dw ?
orgvec dw ?
fslen dw ?
labvec dw ?
linlen dw ?
lstidx dw ?
tempsi dw ?
op1 dd ?
dw ?
op2 dd ?
dw ?
insofs dd ?
inslen dw ?
IFNDEF compak
undata
ENDIF
t_lab db l_lab dup(?)
ENDS
END start