1.1.Listing Asemblera
Program asem;
Type
TLabTip = (lEqu, lprog, ldata, lextrn);
TDsize = (d8, d16, d32, d64, d80);
TLabela = Record
labime: string[40];
labtip: TLabTip;
labval: longint;
labdsize: TDsize;
End;
texists=(exmodrm,exsib,exdisp8, exdisp16, exdisp32, exreg, exkind, exsegment);
TOperand = Record
existv: Set Of texists;
datasizes: Set Of TDsize;
adrsizes: Set Of TDsize;
modrm: byte;
sib: byte;
disp8: byte;
disp16: word;
disp32: longint;
segnum: word;
reg: byte;
kind: integer;
End;
toptable = Record
instr: string[35];
gencod: string[20];
End;
Var
labele: Array[1..10000] Of TLabela;
optable: Array[1..2000] Of TOptable;
FPValue: Array[1..10] Of char;
brlabela, actseg: integer;
skok, dummyb: boolean;
maxopcode, prolaz, dummy: integer;
pozicija: Array[1..3] Of longint;
patstr: string;
ulaz, izlazlab, izlazpat: Text;
izlazcode, izlazdata, izlazstack: File Of byte;
Function trim(st: string): string;
Begin
While (st > '') and (st[1] = ' ') Do
st := copy(st, 2, length(st));
While (st > '') and (st[length(st)] = ' ') Do
st := copy(st, 1, length(st) - 1);
TRIM := ST;
End;
Function uppercase(st: string): string;
Var
i: integer;
Begin
For i := 1 To length(st) Do
If(st[i]>= 'a') and (st[i] <= 'z') Then
st[i] := chr(Ord(st[i]) - 32);
uppercase := st;
End;
Function IntToStr(n: longint; base: cardinal): string;
Var
st, c, pr: string;
ev: cardinal;
Begin
If (base = 10) and (n < 0) Then Begin
pr := '-';
n := -n;
End
Else
pr := '';
ev := n;
c := '0123456789ABCDEF';
If ev = 0 Then st := '0'
Else
st := '';
While ev > 0 Do Begin
st := c[(ev mod base) + 1] + st;
ev := ev div base;
End;
IntToStr := pr + st;
End;
Function inttohex(n, digits: longint): string;
Var
st: string;
negative: boolean;
i: integer;
Begin
If n < 0 Then Begin
n := -n;
n := n - 1;
negative := True;
End
Else
negative := False;
st := IntToStr(n, 16);
While length(st)<digits Do st:= '0' + st;
If negative Then
Begin
For i := 1 To length(st) Do Begin
Case st[i] Of
'0': st[i] := 'F';
'1': st[i] := 'E';
'2': st[i] := 'D';
'3': st[i] := 'C';
'4': st[i] := 'B';
'5': st[i] := 'A';
'6': st[i] := '9';
'7': st[i] := '8';
'8': st[i] := '7';
'9': st[i] := '6';
'A': st[i] := '5';
'B': st[i] := '4';
'C': st[i] := '3';
'D': st[i] := '2';
'E': st[i] := '1';
'F': st[i] := '0';
End;
End;
End;
inttohex := st;
End;
Function nadjilabelu(ime: string): integer;
Var
i: integer;
Begin
nadjilabelu := -1;
For i := 1 To brlabela Do
If ime = labele[i].labime Then Begin
nadjilabelu := i;
End
End;
Procedure upisilabelu(ime: string; adresa: integer;
lt: TLabtip; ds: TDSize);
Var
p: integer;
Begin
p := NadjiLabelu(ime);
If p = -1 Then
Begin
brlabela := brlabela + 1;
p := brlabela;
End;
With labele[p] Do Begin
labime := ime;
labtip := lt;
labval := adresa;
labdsize := ds;
End;
End;
Function EvaluirajBroj(br: string;
Var Greska: boolean): longint;
Var
i, p, c, baza, last, rez: longint;
z: char;
Begin
Greska := False;
rez := 0;
i := 1;
If br = '' Then Begin
EvaluirajBroj := 0;
greska := True;
exit;
End;
If not (br[1] in ['0'..'9', '-']) Then
greska := True;
If (br[1] = '-')and(length(br) > 1) Then
Begin
p := -1;
i := i + 1
End
Else
p := 1;
Case br[length(br)] Of
'o', 'O': baza := 8;
'b', 'B': baza := 2;
'h', 'H': baza := 16;
'0'..'9': baza := 10
Else Begin
baza := 0;
greska := True;
End;
End;
last := length(br);
If baza > 10 Then last := last - 1;
While i <= last Do Begin
z := br[i];
c := 16;
If (z >= '0') and (z <= '9') Then
c := Ord(z) - Ord('0');
If (z >= 'a') and (z <= 'f') Then
c := Ord(z) - Ord('a') + 10;
If (z >= 'A') and (z <= 'F') Then
c := Ord(z) - Ord('A') + 10;
If c >= baza Then greska := True;
rez := rez * baza + c;
i := i + 1;
End;
If greska Then rez := 0;
Evaluirajbroj := p * rez;
End;
Procedure UpisiIzlaz(outst: string);
Var
i: integer;
b: byte;
g: boolean;
Begin
For i:=0 To(length(outst)div2)-1 Do Begin
b := evaluirajbroj('0' + copy(outst,
i * 2 + 1, 2) + 'H', g);
If prolaz = 2 Then
Case actseg Of
1: Write(izlazcode, b);
2: Write(izlazdata, b);
3: Write(izlazstack, b);
End;
End;
End;
Function regcode(reg: string; Var kind: integer): integer;
Const
Registers: Array[0..8, 0..7] Of string =
(('AL','CL','DL','BL','AH','CH','DH','BH'),
('AX','CX','DX','BX','SP','BP','SI','DI'),
('EAX','ECX','EDX','EBX','ESP','EBP','ESI', 'EDI'),
('CR0','***','CR2','CR3','CR4','***','***', '***'),
('DR0','DR1','DR2','DR3','***','***','DR6', 'DR7'),
('TR0','TR1','TR2','TR3','TR4','TR5','TR6', 'TR7'),
('ES','CS','SS','DS','FS','GS',’***','***'),('ST0','ST1','ST2','ST3','ST4','ST5','ST6','ST7'),
('MMX0','MMX1','MMX2','MMX3','MMX4','MMX5',
'MMX6', 'MMX7'));
Var
i, j: integer;
Begin
reg := uppercase(reg);
If copy(reg, 1, 3) = 'ST(' Then
reg := 'ST' + copy(reg, 4, 1);
If copy(reg, 1, 4) = 'MMX(' Then
reg := 'MMX' + copy(reg, 4, 1);
For i := 0 To 8 Do
For j := 0 To 7 Do
If registers[i, j] = reg Then Begin
regcode := j;
kind := i;
exit;
End;
regcode := -1;
kind := -1;
End;
Procedure deplasmani(Var op: TOperand; broj: longint;
predzn: boolean);
Begin
op.existv := op.existv + [exdisp32];
op.disp32 := broj;
If (predzn and (op.disp32 < 32768) and (op.disp32>-32769))or(not (predzn) and (op.disp32<65536)and(op.disp32 >= 0)) Then
Begin
op.existv := op.existv + [exdisp16];
op.disp16 := op.disp32;
End;
If (predzn and (op.disp32 < 128) and (op.disp32>-129)) or(not (predzn) and (op.disp32 < 256) and (op.disp32 >= 0)) Then Begin
op.existv := op.existv + [exdisp8];
op.disp8 := op.disp32;
End;
End;
Procedure ResolveDisp(Var disp, unknown: string);
Var
kind: integer;
greska: boolean;
n: longint;
Begin
unknown := '';
If regcode(disp, kind)>-1 Then exit;
dummy := EvaluirajBroj(disp, greska);
If not (greska) Then exit;
n := nadjilabelu(disp);
If n>-1 Then Begin
patstr := disp;
disp := IntToStr(labele[n].labval, 10);
exit
End
Else Begin
unknown := '';
disp := '0';
End;
End;
Procedure zamijeni(Var x, y: string);
Var
z: string;
Begin
z := x; x := y; y := z;
End;
Function progutaj(st: string; Var puni: string): boolean;
Var
n: integer;
Begin
n := pos(st, uppercase(puni));
If n > 0 Then Begin
puni := trim(copy(puni,1,n-1)+copy(
puni, n + length(st), length(puni)));
progutaj := True;
End
Else
progutaj := False;
End;
FUNCTION parseOp(arg: string; Var op: TOperand;
b32: boolean): boolean;
Var
tip: integer;
n: longint;
Greska, ponovifazu: boolean;
A, B, C, D: string;
A1, B1, C1, D1, unknown, dsp: string;
kind, po: integer;
Procedure setmod(x: byte);
Begin
op.modrm := x;
op.existv := op.existv + [exmodrm];
End;
Procedure setsib(x: byte);
Begin
op.sib := x;
op.existv := op.existv + [exsib];
End;
Function Uzorak(pattern,st:string):boolean;
Var
m: string;
i: integer;
Begin
Uzorak := True;
If pattern = 'A' Then Begin
a := st;
exit
End;
For i := 1 To length(pattern) Do
Begin
If pattern[i]in['A','B','C','D'] Then
Begin
m:=copy(st,1,
pos(pattern[i+1],st)-1);
If m = '' Then
uzorak := False;
Case pattern[i] Of
'A': a := m;
'B': b := m;
'C': c := m;
'D': d := m;
End;
st := copy(st, pos(pattern[i + 1],
st), length(st));
End
Else
st := copy(st, pos(pattern[i], st)
+ 1, length(st));
End;
End;
Procedure Obrada1; { Slucaj A }
Begin
n := regcode(A, kind);
If n>-1 Then Begin
op.existv := op.existv + [exreg];
op.reg := n;
op.kind := kind;
If kind in[0,1,2]Then SetMod(3*64+n);
Case kind Of
0: op.datasizes := [d8];
1, 6: op.datasizes := [d16];
2, 3, 4, 5: op.datasizes := [d32];
7, 8: op.datasizes := [d64];
End;
End
Else Begin
If pos(':', A) = 0 Then Begin
n := EvaluirajBroj(A, greska);
Deplasmani(op, n, n < 0);
End
Else Begin
op.segnum:=EvaluirajBroj(copy(A,1,
pos(':', A) - 1), greska);
op.existv:=op.existv + [exSegment];
n:=EvaluirajBroj(copy(A,pos(':',A)+
1,length(A)), greska);
Deplasmani(op, n, n < 0);
End;
End;
End;
Procedure OBrada7; { Slucaj [A] }
Begin
n := regcode(A, kind);
If n>-1 Then Begin
Case kind Of
1: Begin
Case n Of
3: setmod(0 * 64 + 7); {BX }
6: setmod(0 * 64 + 4); {SI}
7: setmod(0 * 64 + 5); {DI}
5: Begin { BP}
tip := 8;B := '0';
ponovifazu := True;
End
Else
Greska := True;
End;
op.adrsizes := [d16];
End;
2: Begin
Case n Of
{EAX..EDI} 0..3,6,7:setmod(0*64+n);
4:Begin { ESP}
setmod(0 * 64 + 4); {SIB}
setsib(64 * 0 + 8 * 4 + 4);
End;
5: Begin { EBP}
tip := 8;
B := '0';
ponovifazu := True;
End
Else
Greska := True;
End;
op.adrsizes := [d32];
End
Else
Greska := True; {ni 16 ni 32bit}
End;
End
Else Begin
n := EvaluirajBroj(A, greska);
Deplasmani(op, n, False);
If b32 Then Begin
op.existv := [exdisp32];
setmod(0 * 64 + 5);
End
Else Begin
op.existv := [exdisp16];
setmod(0 * 64 + 6);
End
End
End;
Procedure OBrada8; { Slucaj [A+B]}
Var
n2, m: longint;
Begin
n := regcode(A, kind); {Samo registar}
If n = -1 Then Begin
Greska := True;
exit
End;
Case kind Of
1: Begin
op.adrsizes := [d16];
n2 := regcode(B, kind);
If n2>-1 Then Begin
If kind > 1 Then Greska := True
Else {[bx+si],[bx+di],[bp+si],[bp+di]}
If (n = 3) and (n2 = 6) Then
setmod(0 * 64 + 0)
Else If (n = 3) and (n2 = 7) Then
setmod(0 * 64 + 1)
Else If (n = 5) and (n2 = 6) Then
setmod(0 * 64 + 2)
Else If (n = 5) and (n2 = 7) Then
setmod(0 * 64 + 3)
Else
Greska := True;
End
Else Begin
m := 1;
n2 := EvaluirajBroj(B, greska);
Deplasmani(op, n2, True);
If exdisp8 in op.existv Then
Begin
m := 1;
op.existv := [exdisp8]
End
Else
If exdisp16 in op.existv Then
Begin
m := 2;
op.existv := [exdisp16]
End
Else
Greska := True;
Case n Of
3: setmod(m*64+7); {[bx+disp]}
5: setmod(m*64+6); {[bp+disp]}
6: setmod(m*64+4); {[si+disp]}
7: setmod(m*64+5); {[di+disp]}
Else
Greska := True;
End;
End;
End;
2: Begin
{ U 32 bita dopusteno samo REG+const. Za REG+REG koristi REG*1 + REG}
op.adrsizes := [d32];
n2 := regcode(B, kind);
If n2>-1 Then Begin
Greska := True;
exit
End;
n2 := EvaluirajBroj(B, greska);
Deplasmani(op, n2, True);
m := 1;
If exdisp8 in op.existv Then Begin
m := 1;
op.existv := [exdisp8]
End
Else If exdisp32 in op.existv Then
Begin
m := 2;
op.existv := [exdisp32]
End
Else
Greska := True;
If n > 4 Then setmod(m * 64 + n)
Else
Begin {ESP}
setmod(m * 64 + 4);
setsib(64 * 0 + 8 * 4 + 4);
End
End
Else
Greska := True; { Ni 16 ni 32}
End;
End;
Procedure OBrada9; { Slucaj [A*B]}
Var
sc: integer;
Begin
n := regcode(A, kind);
If (kind>2)or(n=1)or(n=4)or(n=-1) or
(length(b) > 1) or (not (b[1] in
['1','2','4', '8'])) Then Begin
Greska := True;
exit;
End;
op.adrsizes := [d32];
sc := pos(b[1], '1248') - 1;
setmod(0 * 64 + 4);
setsib(64*sc+8*n+5); { EBP specijalan}
End;
Procedure OBrada10; { Slucaj [A+B+C]}
Var
n2, n3, m: longint;
Begin
n := regcode(A, kind);
If(kind > 1) or not (n in [3, 5]) Then
Begin
Greska := True;
exit;
End;
n2 := regcode(B, kind);
If (kind>1) or not (n2 in [6, 7]) Then
Begin
Greska := True; exit;
End;
n3 := regcode(C, kind);
If (n3>-1) Then
Begin
Greska := True;
exit;
End;
n3 := EvaluirajBroj(C, greska);
op.adrsizes := [d16];
Deplasmani(op, n3, True);
m := 1;
If exdisp8 in op.existv Then
Begin
m := 1;
op.existv := [exdisp8]
End
Else If exdisp16 in op.existv Then
Begin
m := 2;
op.existv := [exdisp16]
End
Else
Greska := True;
If (n=3)and(n2=6)Then setmod(m*64+0)
Else If (n=3)and(n2=7) Then
setmod(m * 64 + 1)
Else If (n = 5) and (n2 = 6) Then
setmod(m * 64 + 2)
Else If (n = 5) and (n2 = 7) Then
setmod(m * 64 + 3)
Else
Greska := True;
End;
Procedure OBrada11; { Slucaj [A*B+C]}
Var
sc, n2, m: longint;
Begin
n := regcode(A, kind);
If (kind>2)or(n=1)or(n=4)or(n = -1) or
(length(b) > 1) or (not (b[1] in
['1', '2', '4', '8'])) Then Begin
Greska := True;
exit;
End;
sc := pos(b[1], '1248') - 1;
n2 := regcode(C, kind);
op.adrsizes := [d32];
m := 1;
If n2 = -1 Then Begin
n2 := EvaluirajBroj(C, greska);
Deplasmani(op, n2, True);
If exdisp8 in op.existv Then Begin
m := 1;
op.existv := [exdisp8]
End
Else If exdisp32 in op.existv Then
Begin
m := 2;
op.existv := [exdisp32]
End
Else
Greska := True;
setmod(m * 64 + 4);
setsib(64 * sc + 8 * n + 5);
End
Else Begin
If kind > 2 Then greska := True;
If n2 = 5 Then Begin
ponovifazu := True;
tip := 13;
D := '0';
exit
End;
setmod(0 * 64 + 4);
setsib(64 * sc + 8 * n + n2);
End;
End;
Procedure OBrada13; { Slucaj [A*B+C+D]}
Var
sc, n2, n3, m: longint;
Begin
n := regcode(A, kind);
If (n=-1)or(kind>2)or(n=1)or(n=4) or
(length(b) > 1) or (not (b[1] in
['1','2','4', '8'])) Then Begin
Greska := True;
exit;
End;
sc := pos(b[1], '1248') - 1;
n2 := regcode(C, kind);
op.adrsizes := [d32];
If (n2 = -1) or (kind > 2) Then Begin
Greska := True;
exit;
End;
n3 := regcode(D, kind);
If (n3>-1) Then Begin
Greska := True;
exit;
End;
n3 := EvaluirajBroj(D, greska);
Deplasmani(op, n3, True);
m := 1;
If exdisp8 in op.existv Then Begin
m := 1;
op.existv := [exdisp8]
End
Else If exdisp32 in op.existv Then
Begin
m := 2;
op.existv := [exdisp32]
End
Else
Greska := True;
setmod(m * 64 + 4);
setsib(64 * sc + 8 * n + n2);
End;
Begin {Parseop}
tip := -1;
Greska := False;
op.datasizes := [];
If progutaj('BYTE', arg) Then
op.datasizes := [d8]
Else If progutaj('DWORD', arg) Then
op.datasizes := [d32]
Else If progutaj('QWORD', arg) Then
op.datasizes := [d64]
Else If progutaj('TWORD', arg) Then
op.datasizes := [d80]
Else If progutaj('WORD', arg) Then
op.datasizes := [d16];
dummyb := progutaj('PTR', arg);
{ Prva faza: Obrada raznih slucajeva operanda}
arg := trim(arg);
If length(arg) >= 3 Then
If(arg[1]='''')and(arg[3]='''') Then
arg := IntToStr(Ord(arg[2]), 10);
If uzorak('[A*B+C+D]',arg)Then tip := 13
Else If uzorak('[A+B*C+D]',arg)Then tip:=14
Else If uzorak('[A+B+C*D]',arg)Then tip:=15
Else If uzorak('[A*B+C-D]',arg)Then tip:=16
Else If uzorak('[A+B*C-D]',arg)Then tip:=17
Else If uzorak('[A-B+C*D]',arg)Then tip:=18
Else If uzorak('[A*B-C+D]',arg)Then tip:=19
Else If uzorak('[A*B+C]',arg)Then tip:=11
Else If uzorak('[A+B+C]',arg)Then tip:=10
Else If uzorak('[A*B-C]',arg)Then tip:=20
Else If uzorak('[A+B-C]',arg)Then tip:=21
Else If uzorak('[A-B+C]',arg)Then tip:=22
Else If uzorak('[A+B*C]',arg)Then tip:=12
Else If uzorak('[A*B]',arg)Then tip:=9
Else If uzorak('[A+B]',arg)Then tip:=8
Else If uzorak('[A-B]',arg)Then tip:=23
Else If uzorak('A[B*C+D]',arg)Then tip:=5
Else If uzorak('A[B*C-D]',arg) Then tip:=24
Else If uzorak('A[B+C*D]',arg) Then tip:=6
Else If uzorak('A[B*C]',arg) Then tip:=4
Else If uzorak('A[B+C]',arg) Then tip:=3
Else If uzorak('A[B-C]',arg) Then tip:=25
Else If uzorak('A[B]',arg) Then tip:=2
Else If uzorak('[A]',arg) Then tip:=7
Else If uzorak('A',arg) Then tip:=1;
If tip = -1 Then greska := True;
If not (greska) Then Begin
{ Druga faza:Smanjivanje broja slucaja}
Case tip Of
16: Begin
D := '-' + D; tip := 13
End;
17: Begin
D := '-' + D; tip := 14
End;
18: Begin
B := '-' + B; tip := 15
End;
19: Begin
C := '-' + C; tip := 13
End;
20: Begin
C := '-' + C; tip := 11
End;
21:
Begin
C := '-' + C;
tip := 10
End;
22: Begin
B := '-' + B; tip := 10
End;
23: Begin
B := '-' + B; tip := 8
End;
24: Begin
D := '-' + D; tip := 5
End;
25: Begin
C := '-' + C; tip := 3
End;
End;
A1 := A; B1 := B; C1 := C; D1 := D;
Case tip Of
2: tip := 8;
3: tip := 10;
4: Begin
a := b1; b := c1;
c := a1; tip := 11;
End;
5: Begin
d := a1; c := d1; b := c1;
a := b1; tip := 13;
End;
6: Begin
d := a1; c := b1;
a := c1; b := d1; tip := 13;
End;
12: Begin
c := a1; a := b1;
b := c1; tip := 11;
End;
14: Begin
a := b1; b := c1;
c := a1; d := d1; tip := 13;
End;
15: Begin
a := c1; b := d1;
c := a1; d := b1; tip := 13;
End;
End;
{ Treca faza, deplasman na kraj}
Case tip Of
8: Begin
If regcode(A, kind) = -1 Then
zamijeni(A, B);
If regcode(B, kind) in [3, 5] Then
If kind = 1 {16 bit} Then
zamijeni(A, B);
End;
10: Begin
If regcode(A, kind) = -1 Then
zamijeni(A, C);
If regcode(B, kind) = -1 Then
zamijeni(B, C);
If regcode(B, kind) in [3, 5] Then
If kind = 1 {16 bit} Then
zamijeni(A, B);
End;
9, 11: Begin
If regcode(A, kind) = -1 Then
zamijeni(A, B);
End;
13: Begin
If regcode(A, kind) = -1 Then
zamijeni(A, B);
If regcode(C, kind) = -1 Then
zamijeni(C, D);
End;
End;
{ Cetvrta faza, proracun deplasmana, slucaj A moze postati [A] ako je rijec o labeli, slucaj [A+B] moze postati [A] ako ni jedan nije registar }
If tip = 8 Then Begin
If (RegCode(A, kind) = -1) and
(RegCode(B,kind)=-1) Then Begin
If (A[1] in ['0'..'9']) and not
(B[1] in ['0'..'9']) Then Begin
patstr := B;
End
Else Begin
dsp := A + '+' + B;
ResolveDisp(A, unknown);
ResolveDisp(B, unknown);
patstr := dsp;
A := IntToStr(EvaluirajBroj(A,
greska) +
EvaluirajBroj(B, greska), 10);
End;
B := '';
tip := 7;
End;
End;
If tip = 1 Then Begin
If not (progutaj('OFFSET', A)) Then
If RegCode(A,kind)=-1 Then Begin
dummy := EvaluirajBroj(A,greska);
If Greska Then Begin {Trazi labl}
po := nadjilabelu(A);
If(po=-1)and(skok = False) Then
tip := 7 { Pretpostavka}
Else
If labele[po].labtip=ldata Then
Begin
tip := 7;
op.datasizes:=
[labele[po].labdsize];
End;
End
End
End;
unknown := '';
Case tip Of
1: If pos(':', A) = 0 Then
ResolveDisp(A, unknown);
7: ResolveDisp(A, unknown);
8: ResolveDisp(B, unknown);
10, 11: ResolveDisp(C, unknown);
13: ResolveDisp(D, unknown);
End;
greska := False;
{ Peta faza kalkulacija mod/rm, SIB i deplasmana }
op.existv := [];
op.adrsizes := [];
repeat
ponovifazu := False;
Case tip Of
1: Obrada1;
7: Obrada7;
8: Obrada8;
9: Obrada9;
10: Obrada10;
11: Obrada11;
13: Obrada13;
End;
UNTIL not (ponovifazu);
End;
If greska Then parseop := False
Else
parseop := True;
End;
Procedure ReadOpcodeTable;
Var
i, j: integer;
f: Text;
st: string;
t: toptable;
Begin
maxopcode := 0;
Assign(f, 'opcod.txt');
reset(f);
While not EOF(f) Do
Begin
readln(f, st);
maxopcode := maxopcode + 1;
optable[maxopcode].instr :=
trim(copy(st, 1, 20));
optable[maxopcode].gencod := copy(st,
21, 20);
End;
For i := 1 To maxopcode - 1 Do
For j := i + 1 To maxopcode Do
If optable[i].instr >
optable[j].instr Then Begin
t := optable[i];
optable[i] := optable[j];
optable[j] := t;
End;
End;
Function Binsearch(instr: string): integer;
Var
high, j, low: integer;
Begin
low := 0;
high := maxopcode;
While high - low > 1 Do Begin
j := (high + low) div 2;
If instr<=optable[j].instr Then high:=j
Else
low := j
End;
If optable[high].instr=instr Then
Binsearch:=high
Else
Binsearch := -1;
End;
{*******************}
Function GenerateHexInstruction(inst: string;
b32: boolean): string;
Label
postoji;
Var
labela, opcode, arg1, arg2, arg3, comb1,
comb2,comb3, cf: string;
op1, op2, op3: TOperand;
p, i, j, k, n: integer;
b1, greska, no67: boolean;
g1, outstr, st, modif: string;
modski, registarski: integer;
Procedure izdvoji(Var x:string;sep:char);
Begin
If st = '' Then Begin
x := '';
exit
End;
p := pos(sep, st);
If p > 0 Then Begin
x := trim(copy(st, 1, p - 1));
st:=trim(copy(st,p+1,length(st)-p));
End
Else Begin
If sep = ':' Then x := ''
Else Begin
x := trim(st);
st := '';
End
End
End;
Procedure ClearOp(Var op: TOperand);
Begin
With op Do
Begin
existv := [];
datasizes := [];
adrsizes := [];
modrm := 0;
sib := 0;
disp8 := 0;
disp16 := 0;
disp32 := 0;
segnum := 0;
reg := 0;
kind := 0;
End;
End;
Function MakeOps(arg: string; VAR op:
TOperand; Var rez: string): boolean;
Begin
If not(parseop(arg,op,b32))Then Begin
Makeops := False;
exit;
End;
If length(arg) <= 4 Then
rez := copy(arg + ' ', 1, 4)
Else
rez := '';
If exsegment in op.existv Then Begin
If exdisp16 in op.existv Then
rez:= rez + 's:16';
If(exdisp32 in op.existv)and b32 Then
rez := rez + 's:32';
End
Else If exreg in op.existv Then Begin
Case op.kind Of
0: rez := rez + 'reg8rgm8';
1: rez := rez + 'rg16rm16';
2: rez := rez + 'rg32rm32';
3: rez := rez + 'creg';
4: rez := rez + 'dreg';
5: rez := rez + 'treg';
6: rez := rez + 'segr';
7: rez := rez + 'fpur';
8: rez := rez + 'mmxr';
End;
End
Else
Begin { Memorija ili neposredno}
If exmodrm in op.existv Then Begin
rez := rez + 'memg';
If op.datasizes = [] Then
rez := rez + 'mem8mm16mm32mm64mm80rgm8rm16rm32rm64'
Else Begin
If d8 in op.datasizes Then
rez := rez + 'mem8rgm8';
If d16 in op.datasizes Then
rez := rez + 'mm16rm16';
If d32 in op.datasizes Then
rez := rez + 'mm32rm32';
If d64 in op.datasizes Then
rez := rez + 'mm64rm64';
If d80 in op.datasizes Then
rez := rez + 'mm80rm80';
End;
If b32 and (op.modrm = 5) Then
rez := rez + 'ab32';
If not(b32) and (op.modrm = 6) Then
rez := rez + 'ab16abs8';
End
Else
Begin
rez := rez + 'immg';
If exdisp8 in op.existv Then
rez := rez + 'ime8';
If exdisp16 in op.existv Then
rez := rez + 'im16';
If exdisp32 in op.existv Then
rez := rez + 'im32';
End
End;
MakeOps := True;
End;
Function endian16(a: string): string;
Begin
endian16:=copy(a,3,2)+ copy(a, 1, 2);
End;
Function endian32(a: string): string;
Begin
endian32:=copy(a,7,2)+ copy(a, 5, 2) +
copy(a, 3, 2) + copy(a, 1, 2);
End;
Function end1632(a:string;n:TDsize):
string;
Begin
Case n Of
d16: end1632 := Endian16(a);
d32: end1632 := Endian32(a);
Else
end1632 := a;
End;
End;
Procedure writemodrm(slobodni: integer);
Var
op: toperand;
mrm: byte;
Begin
If modski = 1 Then op := op1
Else If modski = 2 Then op := op2
Else
greska := True;
If slobodni = 8 Then
Begin
If registarski = 1 Then
slobodni := op1.reg
Else If registarski = 2 Then
slobodni := op2.reg
Else
greska := True;
End;
mrm:=(op.modrm)and($C7)or(slobodni*8);
outstr := outstr + inttohex(mrm, 2);
If patstr>''Then patstr:=patstr+' ' +
IntToStr(pozicija[actseg]
+length(outstr) div 2,10) + ' A';
If exSIb in op.existv Then
outstr:=outstr + inttohex(op.sib, 2);
If exdisp8 in op.existv Then
outstr:=outstr+inttohex(op.disp8, 2)
Else If exdisp16 in op.existv Then
outstr := outstr +
endian16(inttohex(op.disp16, 4))
Else If exdisp32 in op.existv Then
outstr := outstr +
endian32(inttohex(op.disp32, 8));
End;
Procedure writedisp(ex: texists);
Var
op: TOperand;
Begin
If (arg1>'')and(ex in op1.existv) Then
op := op1
Else If(arg2>'')and(ex in op2.existv) Then op := op2
Else If(arg3>'')and(ex in op3.existv) Then op := op3
Else
greska := True;
If patstr > '' Then Begin
patstr := patstr + ' ' +
IntToStr(pozicija[actseg] +
length(outstr) div 2, 10) + ' D';
op.disp32 := 0; {za coff}
End;
If ex = exdisp8 Then
outstr:=outstr+
(inttohex(op.disp8,2));
If ex = exdisp16 Then
outstr := outstr + endian16(inttohex
(op.disp16, 4));
If ex = exdisp32 Then
outstr := outstr + endian32(inttohex(
op.disp32, 8));
End;
Procedure writeseg;
Begin
outstr := outstr + endian16(inttohex(
op1.segnum, 4));
End;
Procedure writerel(offs:longint;
ex: texists);
Var
op: TOperand;
Function test(a,min,max:integer):
integer;
Begin
If (a < min) or (a > max) Then
greska := True;
test := a;
End;
Begin
If (arg1 > '') Then op := op1
Else If (arg2 > '') Then op := op2
Else If (arg3 > '') Then op := op3
Else
greska := True;
If ((op.disp32 = 0) and (prolaz = 1))
or (op.disp32 = -1) Then
op.disp32 := offs;
If patstr>'' Then
patstr := patstr + ' ' +
IntToStr(pozicija[actseg] +
length(outstr) div 2, 10) + ' R';
If ex = exdisp8 Then
outstr := outstr +
{malo drugacije jer je rijec o razlici}
(inttohex(test(op.disp32 - offs,
- 128, 127), 2));
If ex = exdisp16 Then
outstr := outstr +
endian16(inttohex(test(op.disp32 -
offs, - 32768, 32767), 4));
If ex = exdisp32 Then
outstr := outstr +
endian32(inttohex(op.disp32-offs,8));
End;
Function dod(n: integer): integer;
Begin
dod := (length(outstr) div 2) + n;
End;
Procedure prefix(pr, cod: string);
Begin
If progutaj(pr,st)Then
outstr := outstr + cod;
End;
Procedure modifikator(pr: string);
Begin
If progutaj(pr,st)Then modif:='_' + pr;
End;
Function ispseudo(x: string): boolean;
Begin
x := copy(x, 1, 3);
If (x='DB ')or(x='DW ')or(x = 'DD ')Or
(x='DQ ')or(x='DT ') Then Begin
ispseudo := True
End
Else
ispseudo := False;
End;
Function posnostr(bb: char; s1: string): integer;
Var
odsijeci, ustringu: boolean;
i: integer;
Begin
i := 1;
odsijeci := False;
ustringu := False;
While not (odsijeci) Do Begin
If i>length(s1) Then odsijeci := True
Else Begin
If s1[i] = chr(39) Then
ustringu := not (ustringu);
If not(ustringu)and(s1[i]=bb) Then
odsijeci := True
Else
i := i + 1;
End;
End;
If i <= length(s1) Then posnostr := i
Else
posnostr := 0;
End;
Procedure StrToFloat2(tekstime: string; ValueType: char);
Label
WriteNum, GetExponent, DivExp;
Const
CWNear: word = $133F;
DCon10: integer = 10;
Var
Temp: integer;
CtrlWord: word;
Brojac,DecCifara, Exponent, i: integer;
Negative, ExpNegative: boolean;
Begin
Brojac := 1;
If length(tekstime) = 0 Then exit;
While tekstime[Brojac] = ' ' Do Begin
Brojac := Brojac + 1;
If brojac>length(tekstime) Then exit;
End;
ExpNegative := False;
Negative := False;
DecCifara := 0;
If tekstime[Brojac] = '+' Then
Brojac := Brojac + 1
Else If tekstime[Brojac]='-'Then Begin