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