diff --git a/Compiler.exe b/Compiler.exe
index 1586837..393ad75 100644
Binary files a/Compiler.exe and b/Compiler.exe differ
diff --git a/compiler b/compiler
index 8808960..fc19927 100755
Binary files a/compiler and b/compiler differ
diff --git a/lib/KOSDRV/API.ob07 b/lib/KOSDRV/API.ob07
new file mode 100644
index 0000000..36606e9
--- /dev/null
+++ b/lib/KOSDRV/API.ob07
@@ -0,0 +1,123 @@
+(*
+ BSD 2-Clause License
+
+ Copyright (c) 2018-2022, Anton Krotov
+ All rights reserved.
+*)
+
+MODULE API;
+
+IMPORT SYSTEM;
+
+CONST
+ eol* = 0DX + 0AX;
+ BIT_DEPTH* = 32;
+
+VAR
+ action*, cmdline*, org*: INTEGER;
+
+
+PROCEDURE [stdcall-] sysfunc3* (arg1, arg2, arg3: INTEGER): INTEGER;
+BEGIN
+ SYSTEM.CODE(
+ 053H, (* push ebx *)
+ 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *)
+ 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *)
+ 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *)
+ 0CDH, 040H, (* int 64 *)
+ 05BH, (* pop ebx *)
+ 0C9H, (* leave *)
+ 0C2H, 00CH, 000H (* ret 12 *)
+ )
+ RETURN 0
+END sysfunc3;
+
+
+PROCEDURE OutChar* (c: CHAR);
+BEGIN
+ sysfunc3(63, 1, ORD(c))
+END OutChar;
+
+
+PROCEDURE OutLn*;
+BEGIN
+ OutChar(0DX);
+ OutChar(0AX)
+END OutLn;
+
+
+PROCEDURE OutStr (pchar: INTEGER);
+VAR
+ c: CHAR;
+BEGIN
+ IF pchar # 0 THEN
+ REPEAT
+ SYSTEM.GET(pchar, c);
+ IF c # 0X THEN
+ OutChar(c)
+ END;
+ INC(pchar)
+ UNTIL c = 0X
+ END
+END OutStr;
+
+
+PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER);
+BEGIN
+ IF lpCaption # 0 THEN
+ OutLn;
+ OutStr(lpCaption);
+ OutChar(":");
+ OutLn
+ END;
+ OutStr(lpText);
+ IF lpCaption # 0 THEN
+ OutLn
+ END
+END DebugMsg;
+
+
+PROCEDURE _NEW* (size: INTEGER): INTEGER;
+ RETURN sysfunc3(68, 12, size)
+END _NEW;
+
+
+PROCEDURE _DISPOSE* (ptr: INTEGER): INTEGER;
+BEGIN
+ sysfunc3(68, 13, ptr)
+ RETURN 0
+END _DISPOSE;
+
+
+PROCEDURE init* (reserved, _org: INTEGER);
+BEGIN
+ org := _org - 4096;
+ sysfunc3(68, 11, 0)
+END init;
+
+
+PROCEDURE exit* (code: INTEGER);
+BEGIN
+ sysfunc3(-1, 0, 0)
+END exit;
+
+
+PROCEDURE exit_thread* (code: INTEGER);
+BEGIN
+ sysfunc3(-1, 0, 0)
+END exit_thread;
+
+
+PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER;
+BEGIN
+ action := hinstDLL;
+ cmdline := fdwReason
+ RETURN hinstDLL
+END dllentry;
+
+
+PROCEDURE sofinit*;
+END sofinit;
+
+
+END API.
\ No newline at end of file
diff --git a/lib/KOSDRV/Debug.ob07 b/lib/KOSDRV/Debug.ob07
new file mode 100644
index 0000000..658fe39
--- /dev/null
+++ b/lib/KOSDRV/Debug.ob07
@@ -0,0 +1,292 @@
+(*
+ Copyright 2016, 2018, 2022, 2023 Anton Krotov
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*)
+
+MODULE Debug;
+
+IMPORT API, sys := SYSTEM;
+
+CONST
+
+ d = 1.0 - 5.0E-12;
+
+VAR
+
+ Realp: PROCEDURE (x: REAL; width: INTEGER);
+
+PROCEDURE Char*(c: CHAR);
+VAR res: INTEGER;
+BEGIN
+ res := API.sysfunc3(63, 1, ORD(c))
+END Char;
+
+PROCEDURE String*(s: ARRAY OF CHAR);
+VAR n, i: INTEGER;
+BEGIN
+ n := LENGTH(s);
+ FOR i := 0 TO n - 1 DO
+ Char(s[i])
+ END
+END String;
+
+PROCEDURE WriteInt(x, n: INTEGER);
+VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN;
+BEGIN
+ i := 0;
+ IF n < 1 THEN
+ n := 1
+ END;
+ IF x < 0 THEN
+ x := -x;
+ DEC(n);
+ neg := TRUE
+ END;
+ REPEAT
+ a[i] := CHR(x MOD 10 + ORD("0"));
+ x := x DIV 10;
+ INC(i)
+ UNTIL x = 0;
+ WHILE n > i DO
+ Char(" ");
+ DEC(n)
+ END;
+ IF neg THEN
+ Char("-")
+ END;
+ REPEAT
+ DEC(i);
+ Char(a[i])
+ UNTIL i = 0
+END WriteInt;
+
+PROCEDURE IsNan(AValue: REAL): BOOLEAN;
+VAR h, l: SET;
+BEGIN
+ sys.GET(sys.ADR(AValue), l);
+ sys.GET(sys.ADR(AValue) + 4, h)
+ RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {}))
+END IsNan;
+
+PROCEDURE IsInf(x: REAL): BOOLEAN;
+ RETURN ABS(x) = sys.INF()
+END IsInf;
+
+PROCEDURE Int*(x, width: INTEGER);
+VAR i: INTEGER;
+BEGIN
+ IF x # 80000000H THEN
+ WriteInt(x, width)
+ ELSE
+ FOR i := 12 TO width DO
+ Char(20X)
+ END;
+ String("-2147483648")
+ END
+END Int;
+
+PROCEDURE OutInf(x: REAL; width: INTEGER);
+VAR s: ARRAY 5 OF CHAR; i: INTEGER;
+BEGIN
+ IF IsNan(x) THEN
+ s := "Nan";
+ INC(width)
+ ELSIF IsInf(x) & (x > 0.0) THEN
+ s := "+Inf"
+ ELSIF IsInf(x) & (x < 0.0) THEN
+ s := "-Inf"
+ END;
+ FOR i := 1 TO width - 4 DO
+ Char(" ")
+ END;
+ String(s)
+END OutInf;
+
+PROCEDURE Ln*;
+BEGIN
+ Char(0DX);
+ Char(0AX)
+END Ln;
+
+PROCEDURE _FixReal(x: REAL; width, p: INTEGER);
+VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN;
+BEGIN
+ IF IsNan(x) OR IsInf(x) THEN
+ OutInf(x, width)
+ ELSIF p < 0 THEN
+ Realp(x, width)
+ ELSE
+ len := 0;
+ minus := FALSE;
+ IF x < 0.0 THEN
+ minus := TRUE;
+ INC(len);
+ x := ABS(x)
+ END;
+ e := 0;
+ WHILE x >= 10.0 DO
+ x := x / 10.0;
+ INC(e)
+ END;
+ IF e >= 0 THEN
+ len := len + e + p + 1;
+ IF x > 9.0 + d THEN
+ INC(len)
+ END;
+ IF p > 0 THEN
+ INC(len)
+ END
+ ELSE
+ len := len + p + 2
+ END;
+ FOR i := 1 TO width - len DO
+ Char(" ")
+ END;
+ IF minus THEN
+ Char("-")
+ END;
+ y := x;
+ WHILE (y < 1.0) & (y # 0.0) DO
+ y := y * 10.0;
+ DEC(e)
+ END;
+ IF e < 0 THEN
+ IF x - FLT(FLOOR(x)) > d THEN
+ Char("1");
+ x := 0.0
+ ELSE
+ Char("0");
+ x := x * 10.0
+ END
+ ELSE
+ WHILE e >= 0 DO
+ IF x - FLT(FLOOR(x)) > d THEN
+ IF x > 9.0 THEN
+ String("10")
+ ELSE
+ Char(CHR(FLOOR(x) + ORD("0") + 1))
+ END;
+ x := 0.0
+ ELSE
+ Char(CHR(FLOOR(x) + ORD("0")));
+ x := (x - FLT(FLOOR(x))) * 10.0
+ END;
+ DEC(e)
+ END
+ END;
+ IF p > 0 THEN
+ Char(".")
+ END;
+ WHILE p > 0 DO
+ IF x - FLT(FLOOR(x)) > d THEN
+ Char(CHR(FLOOR(x) + ORD("0") + 1));
+ x := 0.0
+ ELSE
+ Char(CHR(FLOOR(x) + ORD("0")));
+ x := (x - FLT(FLOOR(x))) * 10.0
+ END;
+ DEC(p)
+ END
+ END
+END _FixReal;
+
+PROCEDURE Real*(x: REAL; width: INTEGER);
+VAR e, n, i: INTEGER; minus: BOOLEAN;
+BEGIN
+ IF IsNan(x) OR IsInf(x) THEN
+ OutInf(x, width)
+ ELSE
+ e := 0;
+ n := 0;
+ IF width > 23 THEN
+ n := width - 23;
+ width := 23
+ ELSIF width < 9 THEN
+ width := 9
+ END;
+ width := width - 5;
+ IF x < 0.0 THEN
+ x := -x;
+ minus := TRUE
+ ELSE
+ minus := FALSE
+ END;
+ WHILE x >= 10.0 DO
+ x := x / 10.0;
+ INC(e)
+ END;
+ WHILE (x < 1.0) & (x # 0.0) DO
+ x := x * 10.0;
+ DEC(e)
+ END;
+ IF x > 9.0 + d THEN
+ x := 1.0;
+ INC(e)
+ END;
+ FOR i := 1 TO n DO
+ Char(" ")
+ END;
+ IF minus THEN
+ x := -x
+ END;
+ Realp := Real;
+ _FixReal(x, width, width - 3);
+ Char("E");
+ IF e >= 0 THEN
+ Char("+")
+ ELSE
+ Char("-");
+ e := ABS(e)
+ END;
+ IF e < 100 THEN
+ Char("0")
+ END;
+ IF e < 10 THEN
+ Char("0")
+ END;
+ Int(e, 0)
+ END
+END Real;
+
+PROCEDURE FixReal*(x: REAL; width, p: INTEGER);
+BEGIN
+ Realp := Real;
+ _FixReal(x, width, p)
+END FixReal;
+
+PROCEDURE Open*;
+TYPE
+
+ info_struct = RECORD
+ subfunc: INTEGER;
+ flags: INTEGER;
+ param: INTEGER;
+ rsrvd1: INTEGER;
+ rsrvd2: INTEGER;
+ fname: ARRAY 1024 OF CHAR
+ END;
+
+VAR info: info_struct; res: INTEGER;
+BEGIN
+ info.subfunc := 7;
+ info.flags := 0;
+ info.param := sys.SADR(" ");
+ info.rsrvd1 := 0;
+ info.rsrvd2 := 0;
+ info.fname := "/sys/develop/board";
+ res := API.sysfunc3(70, sys.ADR(info), 0)
+END Open;
+
+END Debug.
\ No newline at end of file
diff --git a/lib/KOSDRV/RTL.ob07 b/lib/KOSDRV/RTL.ob07
new file mode 100644
index 0000000..22e0c63
--- /dev/null
+++ b/lib/KOSDRV/RTL.ob07
@@ -0,0 +1,548 @@
+(*
+ BSD 2-Clause License
+
+ Copyright (c) 2018-2021, 2023, Anton Krotov
+ All rights reserved.
+*)
+
+MODULE RTL;
+
+IMPORT SYSTEM, API;
+
+
+CONST
+
+ minint = ROR(1, 1);
+
+ WORD = API.BIT_DEPTH DIV 8;
+
+
+VAR
+
+ name, types, tcount: INTEGER;
+
+
+PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER);
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *)
+ 085H, 0C0H, (* test eax, eax *)
+ 07EH, 019H, (* jle L *)
+ 0FCH, (* cld *)
+ 057H, (* push edi *)
+ 056H, (* push esi *)
+ 08BH, 075H, 010H, (* mov esi, dword [ebp + 16] *)
+ 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *)
+ 089H, 0C1H, (* mov ecx, eax *)
+ 0C1H, 0E9H, 002H, (* shr ecx, 2 *)
+ 0F3H, 0A5H, (* rep movsd *)
+ 089H, 0C1H, (* mov ecx, eax *)
+ 083H, 0E1H, 003H, (* and ecx, 3 *)
+ 0F3H, 0A4H, (* rep movsb *)
+ 05EH, (* pop esi *)
+ 05FH (* pop edi *)
+ (* L: *)
+ )
+END _move;
+
+
+PROCEDURE [stdcall] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN;
+VAR
+ res: BOOLEAN;
+
+BEGIN
+ IF len_src > len_dst THEN
+ res := FALSE
+ ELSE
+ _move(len_src * base_size, dst, src);
+ res := TRUE
+ END
+
+ RETURN res
+END _arrcpy;
+
+
+PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER);
+BEGIN
+ _move(MIN(len_dst, len_src) * chr_size, dst, src)
+END _strcpy;
+
+
+PROCEDURE [stdcall] _rot* (Len, Ptr: INTEGER);
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- Len *)
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- Ptr *)
+ 049H, (* dec ecx *)
+ 053H, (* push ebx *)
+ 08BH, 018H, (* mov ebx, dword [eax] *)
+ (* L: *)
+ 08BH, 050H, 004H, (* mov edx, dword [eax + 4] *)
+ 089H, 010H, (* mov dword [eax], edx *)
+ 083H, 0C0H, 004H, (* add eax, 4 *)
+ 049H, (* dec ecx *)
+ 075H, 0F5H, (* jnz L *)
+ 089H, 018H, (* mov dword [eax], ebx *)
+ 05BH, (* pop ebx *)
+ 05DH, (* pop ebp *)
+ 0C2H, 008H, 000H (* ret 8 *)
+ )
+END _rot;
+
+
+PROCEDURE [stdcall] _set* (b, a: INTEGER); (* {a..b} -> eax *)
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- b *)
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- a *)
+ 039H, 0C8H, (* cmp eax, ecx *)
+ 07FH, 033H, (* jg L1 *)
+ 083H, 0F8H, 01FH, (* cmp eax, 31 *)
+ 07FH, 02EH, (* jg L1 *)
+ 085H, 0C9H, (* test ecx, ecx *)
+ 07CH, 02AH, (* jl L1 *)
+ 083H, 0F9H, 01FH, (* cmp ecx, 31 *)
+ 07EH, 005H, (* jle L3 *)
+ 0B9H, 01FH, 000H, 000H, 000H, (* mov ecx, 31 *)
+ (* L3: *)
+ 085H, 0C0H, (* test eax, eax *)
+ 07DH, 002H, (* jge L2 *)
+ 031H, 0C0H, (* xor eax, eax *)
+ (* L2: *)
+ 089H, 0CAH, (* mov edx, ecx *)
+ 029H, 0C2H, (* sub edx, eax *)
+ 0B8H, 000H, 000H, 000H, 080H, (* mov eax, 0x80000000 *)
+ 087H, 0CAH, (* xchg edx, ecx *)
+ 0D3H, 0F8H, (* sar eax, cl *)
+ 087H, 0CAH, (* xchg edx, ecx *)
+ 083H, 0E9H, 01FH, (* sub ecx, 31 *)
+ 0F7H, 0D9H, (* neg ecx *)
+ 0D3H, 0E8H, (* shr eax, cl *)
+ 05DH, (* pop ebp *)
+ 0C2H, 008H, 000H, (* ret 8 *)
+ (* L1: *)
+ 031H, 0C0H, (* xor eax, eax *)
+ 05DH, (* pop ebp *)
+ 0C2H, 008H, 000H (* ret 8 *)
+ )
+END _set;
+
+
+PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *)
+BEGIN
+ SYSTEM.CODE(
+ 031H, 0C0H, (* xor eax, eax *)
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *)
+ 083H, 0F9H, 01FH, (* cmp ecx, 31 *)
+ 077H, 003H, (* ja L *)
+ 00FH, 0ABH, 0C8H (* bts eax, ecx *)
+ (* L: *)
+ )
+END _set1;
+
+
+PROCEDURE [stdcall] _divmod* (y, x: INTEGER); (* (x div y) -> eax; (x mod y) -> edx *)
+BEGIN
+ SYSTEM.CODE(
+ 053H, (* push ebx *)
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- x *)
+ 031H, 0D2H, (* xor edx, edx *)
+ 085H, 0C0H, (* test eax, eax *)
+ 074H, 018H, (* je L2 *)
+ 07FH, 002H, (* jg L1 *)
+ 0F7H, 0D2H, (* not edx *)
+ (* L1: *)
+ 089H, 0C3H, (* mov ebx, eax *)
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- y *)
+ 0F7H, 0F9H, (* idiv ecx *)
+ 085H, 0D2H, (* test edx, edx *)
+ 074H, 009H, (* je L2 *)
+ 031H, 0CBH, (* xor ebx, ecx *)
+ 085H, 0DBH, (* test ebx, ebx *)
+ 07DH, 003H, (* jge L2 *)
+ 048H, (* dec eax *)
+ 001H, 0CAH, (* add edx, ecx *)
+ (* L2: *)
+ 05BH (* pop ebx *)
+ )
+END _divmod;
+
+
+PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER);
+BEGIN
+ ptr := API._NEW(size);
+ IF ptr # 0 THEN
+ SYSTEM.PUT(ptr, t);
+ INC(ptr, WORD)
+ END
+END _new;
+
+
+PROCEDURE [stdcall] _dispose* (VAR ptr: INTEGER);
+BEGIN
+ IF ptr # 0 THEN
+ ptr := API._DISPOSE(ptr - WORD)
+ END
+END _dispose;
+
+
+PROCEDURE [stdcall] _length* (len, str: INTEGER);
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *)
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *)
+ 048H, (* dec eax *)
+ (* L1: *)
+ 040H, (* inc eax *)
+ 080H, 038H, 000H, (* cmp byte [eax], 0 *)
+ 074H, 003H, (* jz L2 *)
+ 0E2H, 0F8H, (* loop L1 *)
+ 040H, (* inc eax *)
+ (* L2: *)
+ 02BH, 045H, 00CH (* sub eax, dword [ebp + 0Ch] *)
+ )
+END _length;
+
+
+PROCEDURE [stdcall] _lengthw* (len, str: INTEGER);
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *)
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *)
+ 048H, (* dec eax *)
+ 048H, (* dec eax *)
+ (* L1: *)
+ 040H, (* inc eax *)
+ 040H, (* inc eax *)
+ 066H, 083H, 038H, 000H, (* cmp word [eax], 0 *)
+ 074H, 004H, (* jz L2 *)
+ 0E2H, 0F6H, (* loop L1 *)
+ 040H, (* inc eax *)
+ 040H, (* inc eax *)
+ (* L2: *)
+ 02BH, 045H, 00CH, (* sub eax, dword [ebp + 0Ch] *)
+ 0D1H, 0E8H (* shr eax, 1 *)
+ )
+END _lengthw;
+
+
+PROCEDURE [stdcall] strncmp (a, b, n: INTEGER): INTEGER;
+BEGIN
+ SYSTEM.CODE(
+ 056H, (* push esi *)
+ 057H, (* push edi *)
+ 053H, (* push ebx *)
+ 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *)
+ 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *)
+ 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *)
+ 031H, 0C9H, (* xor ecx, ecx *)
+ 031H, 0D2H, (* xor edx, edx *)
+ 0B8H,
+ 000H, 000H, 000H, 080H, (* mov eax, minint *)
+ (* L1: *)
+ 085H, 0DBH, (* test ebx, ebx *)
+ 07EH, 017H, (* jle L3 *)
+ 08AH, 00EH, (* mov cl, byte[esi] *)
+ 08AH, 017H, (* mov dl, byte[edi] *)
+ 046H, (* inc esi *)
+ 047H, (* inc edi *)
+ 04BH, (* dec ebx *)
+ 039H, 0D1H, (* cmp ecx, edx *)
+ 074H, 006H, (* je L2 *)
+ 089H, 0C8H, (* mov eax, ecx *)
+ 029H, 0D0H, (* sub eax, edx *)
+ 0EBH, 006H, (* jmp L3 *)
+ (* L2: *)
+ 085H, 0C9H, (* test ecx, ecx *)
+ 075H, 0E7H, (* jne L1 *)
+ 031H, 0C0H, (* xor eax, eax *)
+ (* L3: *)
+ 05BH, (* pop ebx *)
+ 05FH, (* pop edi *)
+ 05EH, (* pop esi *)
+ 05DH, (* pop ebp *)
+ 0C2H, 00CH, 000H (* ret 12 *)
+ )
+ RETURN 0
+END strncmp;
+
+
+PROCEDURE [stdcall] strncmpw (a, b, n: INTEGER): INTEGER;
+BEGIN
+ SYSTEM.CODE(
+ 056H, (* push esi *)
+ 057H, (* push edi *)
+ 053H, (* push ebx *)
+ 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *)
+ 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *)
+ 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *)
+ 031H, 0C9H, (* xor ecx, ecx *)
+ 031H, 0D2H, (* xor edx, edx *)
+ 0B8H,
+ 000H, 000H, 000H, 080H, (* mov eax, minint *)
+ (* L1: *)
+ 085H, 0DBH, (* test ebx, ebx *)
+ 07EH, 01BH, (* jle L3 *)
+ 066H, 08BH, 00EH, (* mov cx, word[esi] *)
+ 066H, 08BH, 017H, (* mov dx, word[edi] *)
+ 046H, (* inc esi *)
+ 046H, (* inc esi *)
+ 047H, (* inc edi *)
+ 047H, (* inc edi *)
+ 04BH, (* dec ebx *)
+ 039H, 0D1H, (* cmp ecx, edx *)
+ 074H, 006H, (* je L2 *)
+ 089H, 0C8H, (* mov eax, ecx *)
+ 029H, 0D0H, (* sub eax, edx *)
+ 0EBH, 006H, (* jmp L3 *)
+ (* L2: *)
+ 085H, 0C9H, (* test ecx, ecx *)
+ 075H, 0E3H, (* jne L1 *)
+ 031H, 0C0H, (* xor eax, eax *)
+ (* L3: *)
+ 05BH, (* pop ebx *)
+ 05FH, (* pop edi *)
+ 05EH, (* pop esi *)
+ 05DH, (* pop ebp *)
+ 0C2H, 00CH, 000H (* ret 12 *)
+ )
+ RETURN 0
+END strncmpw;
+
+
+PROCEDURE [stdcall] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN;
+VAR
+ res: INTEGER;
+ bRes: BOOLEAN;
+ c: CHAR;
+
+BEGIN
+ res := strncmp(str1, str2, MIN(len1, len2));
+ IF res = minint THEN
+ IF len1 > len2 THEN
+ SYSTEM.GET(str1 + len2, c);
+ res := ORD(c)
+ ELSIF len1 < len2 THEN
+ SYSTEM.GET(str2 + len1, c);
+ res := -ORD(c)
+ ELSE
+ res := 0
+ END
+ END;
+
+ CASE op OF
+ |0: bRes := res = 0
+ |1: bRes := res # 0
+ |2: bRes := res < 0
+ |3: bRes := res <= 0
+ |4: bRes := res > 0
+ |5: bRes := res >= 0
+ END
+
+ RETURN bRes
+END _strcmp;
+
+
+PROCEDURE [stdcall] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN;
+VAR
+ res: INTEGER;
+ bRes: BOOLEAN;
+ c: WCHAR;
+
+BEGIN
+ res := strncmpw(str1, str2, MIN(len1, len2));
+ IF res = minint THEN
+ IF len1 > len2 THEN
+ SYSTEM.GET(str1 + len2 * 2, c);
+ res := ORD(c)
+ ELSIF len1 < len2 THEN
+ SYSTEM.GET(str2 + len1 * 2, c);
+ res := -ORD(c)
+ ELSE
+ res := 0
+ END
+ END;
+
+ CASE op OF
+ |0: bRes := res = 0
+ |1: bRes := res # 0
+ |2: bRes := res < 0
+ |3: bRes := res <= 0
+ |4: bRes := res > 0
+ |5: bRes := res >= 0
+ END
+
+ RETURN bRes
+END _strcmpw;
+
+
+PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR);
+VAR
+ c: CHAR;
+ i: INTEGER;
+
+BEGIN
+ i := 0;
+ REPEAT
+ SYSTEM.GET(pchar, c);
+ s[i] := c;
+ INC(pchar);
+ INC(i)
+ UNTIL c = 0X
+END PCharToStr;
+
+
+PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR);
+VAR
+ i, a: INTEGER;
+
+BEGIN
+ i := 0;
+ a := x;
+ REPEAT
+ INC(i);
+ a := a DIV 10
+ UNTIL a = 0;
+
+ str[i] := 0X;
+
+ REPEAT
+ DEC(i);
+ str[i] := CHR(x MOD 10 + ORD("0"));
+ x := x DIV 10
+ UNTIL x = 0
+END IntToStr;
+
+
+PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR);
+VAR
+ n1, n2: INTEGER;
+
+BEGIN
+ n1 := LENGTH(s1);
+ n2 := LENGTH(s2);
+
+ ASSERT(n1 + n2 < LEN(s1));
+
+ SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2);
+ s1[n1 + n2] := 0X
+END append;
+
+
+PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER);
+VAR
+ s, temp: ARRAY 1024 OF CHAR;
+
+BEGIN
+ CASE err OF
+ | 1: s := "assertion failure"
+ | 2: s := "NIL dereference"
+ | 3: s := "bad divisor"
+ | 4: s := "NIL procedure call"
+ | 5: s := "type guard error"
+ | 6: s := "index out of range"
+ | 7: s := "invalid CASE"
+ | 8: s := "array assignment error"
+ | 9: s := "CHR out of range"
+ |10: s := "WCHR out of range"
+ |11: s := "BYTE out of range"
+ END;
+
+ append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp);
+ append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp);
+
+ API.DebugMsg(SYSTEM.ADR(s[0]), name);
+
+ API.exit_thread(0)
+END _error;
+
+
+PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): BOOLEAN;
+BEGIN
+ (* r IS t0 *)
+ WHILE (t1 # 0) & (t1 # t0) DO
+ SYSTEM.GET(types + t1 * WORD, t1)
+ END
+
+ RETURN t1 = t0
+END _isrec;
+
+
+PROCEDURE [stdcall] _is* (t0, p: INTEGER): BOOLEAN;
+VAR
+ t1: INTEGER;
+
+BEGIN
+ (* p IS t0 *)
+ IF p # 0 THEN
+ SYSTEM.GET(p - WORD, t1);
+ WHILE (t1 # 0) & (t1 # t0) DO
+ SYSTEM.GET(types + t1 * WORD, t1)
+ END
+ ELSE
+ t1 := -1
+ END
+
+ RETURN t1 = t0
+END _is;
+
+
+PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): BOOLEAN;
+BEGIN
+ (* r:t1 IS t0 *)
+ WHILE (t1 # 0) & (t1 # t0) DO
+ SYSTEM.GET(types + t1 * WORD, t1)
+ END
+
+ RETURN t1 = t0
+END _guardrec;
+
+
+PROCEDURE [stdcall] _guard* (t0, p: INTEGER): BOOLEAN;
+VAR
+ t1: INTEGER;
+
+BEGIN
+ (* p IS t0 *)
+ SYSTEM.GET(p, p);
+ IF p # 0 THEN
+ SYSTEM.GET(p - WORD, t1);
+ WHILE (t1 # t0) & (t1 # 0) DO
+ SYSTEM.GET(types + t1 * WORD, t1)
+ END
+ ELSE
+ t1 := t0
+ END
+
+ RETURN t1 = t0
+END _guard;
+
+
+PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER;
+ RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved)
+END _dllentry;
+
+
+PROCEDURE [stdcall] _sofinit*;
+BEGIN
+ API.sofinit
+END _sofinit;
+
+
+PROCEDURE [stdcall] _exit* (code: INTEGER);
+BEGIN
+ API.exit(code)
+END _exit;
+
+
+PROCEDURE [stdcall] _init* (modname: INTEGER; _tcount, _types: INTEGER; code, param: INTEGER);
+BEGIN
+ SYSTEM.CODE(09BH, 0DBH, 0E3H); (* finit *)
+ API.init(param, code);
+ tcount := _tcount;
+ types := _types;
+ name := modname
+END _init;
+
+
+END RTL.
\ No newline at end of file
diff --git a/lib/KOSKER/API.ob07 b/lib/KOSKER/API.ob07
new file mode 100644
index 0000000..e32d2e4
--- /dev/null
+++ b/lib/KOSKER/API.ob07
@@ -0,0 +1,131 @@
+(*
+ BSD 2-Clause License
+
+ Copyright (c) 2023, Anton Krotov
+ All rights reserved.
+*)
+
+MODULE API;
+
+IMPORT SYSTEM;
+
+CONST
+ eol* = 0DX + 0AX;
+ BIT_DEPTH* = 32;
+
+ HEAP_SIZE = 3*1024;
+
+VAR
+ org*: INTEGER;
+
+ mem: ARRAY HEAP_SIZE OF BYTE;
+ heap: INTEGER;
+
+
+PROCEDURE [stdcall-] sysfunc3* (arg1, arg2, arg3: INTEGER): INTEGER;
+BEGIN
+ SYSTEM.CODE(
+ 053H, (* push ebx *)
+ 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *)
+ 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *)
+ 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *)
+ 0CDH, 040H, (* int 64 *)
+ 05BH, (* pop ebx *)
+ 0C9H, (* leave *)
+ 0C2H, 00CH, 000H (* ret 12 *)
+ )
+ RETURN 0
+END sysfunc3;
+
+
+PROCEDURE OutChar* (c: CHAR);
+BEGIN
+ sysfunc3(63, 1, ORD(c))
+END OutChar;
+
+
+PROCEDURE OutLn*;
+BEGIN
+ OutChar(0DX);
+ OutChar(0AX)
+END OutLn;
+
+
+PROCEDURE OutStr* (pchar: INTEGER);
+VAR
+ c: CHAR;
+BEGIN
+ IF pchar # 0 THEN
+ REPEAT
+ SYSTEM.GET(pchar, c);
+ IF c # 0X THEN
+ OutChar(c)
+ END;
+ INC(pchar)
+ UNTIL c = 0X
+ END
+END OutStr;
+
+
+PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER);
+BEGIN
+ IF lpCaption # 0 THEN
+ OutLn;
+ OutStr(lpCaption);
+ OutChar(":");
+ OutLn
+ END;
+ OutStr(lpText);
+ IF lpCaption # 0 THEN
+ OutLn
+ END
+END DebugMsg;
+
+
+PROCEDURE _NEW* (size: INTEGER): INTEGER;
+VAR
+ res: INTEGER;
+BEGIN
+ IF heap + size <= SYSTEM.ADR(mem[0]) + HEAP_SIZE THEN
+ res := heap;
+ INC(heap, size)
+ ELSE
+ res := 0
+ END
+ RETURN res
+END _NEW;
+
+
+PROCEDURE _DISPOSE* (ptr: INTEGER): INTEGER;
+ RETURN 0
+END _DISPOSE;
+
+
+PROCEDURE init* (reserved, _org: INTEGER);
+BEGIN
+ org := _org;
+ heap := SYSTEM.ADR(mem[0])
+END init;
+
+
+PROCEDURE exit* (code: INTEGER);
+BEGIN
+ sysfunc3(-1, 0, 0)
+END exit;
+
+
+PROCEDURE exit_thread* (code: INTEGER);
+BEGIN
+ sysfunc3(-1, 0, 0)
+END exit_thread;
+
+
+PROCEDURE dllentry* (param1, param2, param3: INTEGER): INTEGER;
+ RETURN 0
+END dllentry;
+
+
+PROCEDURE sofinit*;
+END sofinit;
+
+END API.
\ No newline at end of file
diff --git a/lib/KOSKER/Debug.ob07 b/lib/KOSKER/Debug.ob07
new file mode 100644
index 0000000..658fe39
--- /dev/null
+++ b/lib/KOSKER/Debug.ob07
@@ -0,0 +1,292 @@
+(*
+ Copyright 2016, 2018, 2022, 2023 Anton Krotov
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*)
+
+MODULE Debug;
+
+IMPORT API, sys := SYSTEM;
+
+CONST
+
+ d = 1.0 - 5.0E-12;
+
+VAR
+
+ Realp: PROCEDURE (x: REAL; width: INTEGER);
+
+PROCEDURE Char*(c: CHAR);
+VAR res: INTEGER;
+BEGIN
+ res := API.sysfunc3(63, 1, ORD(c))
+END Char;
+
+PROCEDURE String*(s: ARRAY OF CHAR);
+VAR n, i: INTEGER;
+BEGIN
+ n := LENGTH(s);
+ FOR i := 0 TO n - 1 DO
+ Char(s[i])
+ END
+END String;
+
+PROCEDURE WriteInt(x, n: INTEGER);
+VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN;
+BEGIN
+ i := 0;
+ IF n < 1 THEN
+ n := 1
+ END;
+ IF x < 0 THEN
+ x := -x;
+ DEC(n);
+ neg := TRUE
+ END;
+ REPEAT
+ a[i] := CHR(x MOD 10 + ORD("0"));
+ x := x DIV 10;
+ INC(i)
+ UNTIL x = 0;
+ WHILE n > i DO
+ Char(" ");
+ DEC(n)
+ END;
+ IF neg THEN
+ Char("-")
+ END;
+ REPEAT
+ DEC(i);
+ Char(a[i])
+ UNTIL i = 0
+END WriteInt;
+
+PROCEDURE IsNan(AValue: REAL): BOOLEAN;
+VAR h, l: SET;
+BEGIN
+ sys.GET(sys.ADR(AValue), l);
+ sys.GET(sys.ADR(AValue) + 4, h)
+ RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {}))
+END IsNan;
+
+PROCEDURE IsInf(x: REAL): BOOLEAN;
+ RETURN ABS(x) = sys.INF()
+END IsInf;
+
+PROCEDURE Int*(x, width: INTEGER);
+VAR i: INTEGER;
+BEGIN
+ IF x # 80000000H THEN
+ WriteInt(x, width)
+ ELSE
+ FOR i := 12 TO width DO
+ Char(20X)
+ END;
+ String("-2147483648")
+ END
+END Int;
+
+PROCEDURE OutInf(x: REAL; width: INTEGER);
+VAR s: ARRAY 5 OF CHAR; i: INTEGER;
+BEGIN
+ IF IsNan(x) THEN
+ s := "Nan";
+ INC(width)
+ ELSIF IsInf(x) & (x > 0.0) THEN
+ s := "+Inf"
+ ELSIF IsInf(x) & (x < 0.0) THEN
+ s := "-Inf"
+ END;
+ FOR i := 1 TO width - 4 DO
+ Char(" ")
+ END;
+ String(s)
+END OutInf;
+
+PROCEDURE Ln*;
+BEGIN
+ Char(0DX);
+ Char(0AX)
+END Ln;
+
+PROCEDURE _FixReal(x: REAL; width, p: INTEGER);
+VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN;
+BEGIN
+ IF IsNan(x) OR IsInf(x) THEN
+ OutInf(x, width)
+ ELSIF p < 0 THEN
+ Realp(x, width)
+ ELSE
+ len := 0;
+ minus := FALSE;
+ IF x < 0.0 THEN
+ minus := TRUE;
+ INC(len);
+ x := ABS(x)
+ END;
+ e := 0;
+ WHILE x >= 10.0 DO
+ x := x / 10.0;
+ INC(e)
+ END;
+ IF e >= 0 THEN
+ len := len + e + p + 1;
+ IF x > 9.0 + d THEN
+ INC(len)
+ END;
+ IF p > 0 THEN
+ INC(len)
+ END
+ ELSE
+ len := len + p + 2
+ END;
+ FOR i := 1 TO width - len DO
+ Char(" ")
+ END;
+ IF minus THEN
+ Char("-")
+ END;
+ y := x;
+ WHILE (y < 1.0) & (y # 0.0) DO
+ y := y * 10.0;
+ DEC(e)
+ END;
+ IF e < 0 THEN
+ IF x - FLT(FLOOR(x)) > d THEN
+ Char("1");
+ x := 0.0
+ ELSE
+ Char("0");
+ x := x * 10.0
+ END
+ ELSE
+ WHILE e >= 0 DO
+ IF x - FLT(FLOOR(x)) > d THEN
+ IF x > 9.0 THEN
+ String("10")
+ ELSE
+ Char(CHR(FLOOR(x) + ORD("0") + 1))
+ END;
+ x := 0.0
+ ELSE
+ Char(CHR(FLOOR(x) + ORD("0")));
+ x := (x - FLT(FLOOR(x))) * 10.0
+ END;
+ DEC(e)
+ END
+ END;
+ IF p > 0 THEN
+ Char(".")
+ END;
+ WHILE p > 0 DO
+ IF x - FLT(FLOOR(x)) > d THEN
+ Char(CHR(FLOOR(x) + ORD("0") + 1));
+ x := 0.0
+ ELSE
+ Char(CHR(FLOOR(x) + ORD("0")));
+ x := (x - FLT(FLOOR(x))) * 10.0
+ END;
+ DEC(p)
+ END
+ END
+END _FixReal;
+
+PROCEDURE Real*(x: REAL; width: INTEGER);
+VAR e, n, i: INTEGER; minus: BOOLEAN;
+BEGIN
+ IF IsNan(x) OR IsInf(x) THEN
+ OutInf(x, width)
+ ELSE
+ e := 0;
+ n := 0;
+ IF width > 23 THEN
+ n := width - 23;
+ width := 23
+ ELSIF width < 9 THEN
+ width := 9
+ END;
+ width := width - 5;
+ IF x < 0.0 THEN
+ x := -x;
+ minus := TRUE
+ ELSE
+ minus := FALSE
+ END;
+ WHILE x >= 10.0 DO
+ x := x / 10.0;
+ INC(e)
+ END;
+ WHILE (x < 1.0) & (x # 0.0) DO
+ x := x * 10.0;
+ DEC(e)
+ END;
+ IF x > 9.0 + d THEN
+ x := 1.0;
+ INC(e)
+ END;
+ FOR i := 1 TO n DO
+ Char(" ")
+ END;
+ IF minus THEN
+ x := -x
+ END;
+ Realp := Real;
+ _FixReal(x, width, width - 3);
+ Char("E");
+ IF e >= 0 THEN
+ Char("+")
+ ELSE
+ Char("-");
+ e := ABS(e)
+ END;
+ IF e < 100 THEN
+ Char("0")
+ END;
+ IF e < 10 THEN
+ Char("0")
+ END;
+ Int(e, 0)
+ END
+END Real;
+
+PROCEDURE FixReal*(x: REAL; width, p: INTEGER);
+BEGIN
+ Realp := Real;
+ _FixReal(x, width, p)
+END FixReal;
+
+PROCEDURE Open*;
+TYPE
+
+ info_struct = RECORD
+ subfunc: INTEGER;
+ flags: INTEGER;
+ param: INTEGER;
+ rsrvd1: INTEGER;
+ rsrvd2: INTEGER;
+ fname: ARRAY 1024 OF CHAR
+ END;
+
+VAR info: info_struct; res: INTEGER;
+BEGIN
+ info.subfunc := 7;
+ info.flags := 0;
+ info.param := sys.SADR(" ");
+ info.rsrvd1 := 0;
+ info.rsrvd2 := 0;
+ info.fname := "/sys/develop/board";
+ res := API.sysfunc3(70, sys.ADR(info), 0)
+END Open;
+
+END Debug.
\ No newline at end of file
diff --git a/lib/KOSKER/RTL.ob07 b/lib/KOSKER/RTL.ob07
new file mode 100644
index 0000000..22e0c63
--- /dev/null
+++ b/lib/KOSKER/RTL.ob07
@@ -0,0 +1,548 @@
+(*
+ BSD 2-Clause License
+
+ Copyright (c) 2018-2021, 2023, Anton Krotov
+ All rights reserved.
+*)
+
+MODULE RTL;
+
+IMPORT SYSTEM, API;
+
+
+CONST
+
+ minint = ROR(1, 1);
+
+ WORD = API.BIT_DEPTH DIV 8;
+
+
+VAR
+
+ name, types, tcount: INTEGER;
+
+
+PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER);
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *)
+ 085H, 0C0H, (* test eax, eax *)
+ 07EH, 019H, (* jle L *)
+ 0FCH, (* cld *)
+ 057H, (* push edi *)
+ 056H, (* push esi *)
+ 08BH, 075H, 010H, (* mov esi, dword [ebp + 16] *)
+ 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *)
+ 089H, 0C1H, (* mov ecx, eax *)
+ 0C1H, 0E9H, 002H, (* shr ecx, 2 *)
+ 0F3H, 0A5H, (* rep movsd *)
+ 089H, 0C1H, (* mov ecx, eax *)
+ 083H, 0E1H, 003H, (* and ecx, 3 *)
+ 0F3H, 0A4H, (* rep movsb *)
+ 05EH, (* pop esi *)
+ 05FH (* pop edi *)
+ (* L: *)
+ )
+END _move;
+
+
+PROCEDURE [stdcall] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN;
+VAR
+ res: BOOLEAN;
+
+BEGIN
+ IF len_src > len_dst THEN
+ res := FALSE
+ ELSE
+ _move(len_src * base_size, dst, src);
+ res := TRUE
+ END
+
+ RETURN res
+END _arrcpy;
+
+
+PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER);
+BEGIN
+ _move(MIN(len_dst, len_src) * chr_size, dst, src)
+END _strcpy;
+
+
+PROCEDURE [stdcall] _rot* (Len, Ptr: INTEGER);
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- Len *)
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- Ptr *)
+ 049H, (* dec ecx *)
+ 053H, (* push ebx *)
+ 08BH, 018H, (* mov ebx, dword [eax] *)
+ (* L: *)
+ 08BH, 050H, 004H, (* mov edx, dword [eax + 4] *)
+ 089H, 010H, (* mov dword [eax], edx *)
+ 083H, 0C0H, 004H, (* add eax, 4 *)
+ 049H, (* dec ecx *)
+ 075H, 0F5H, (* jnz L *)
+ 089H, 018H, (* mov dword [eax], ebx *)
+ 05BH, (* pop ebx *)
+ 05DH, (* pop ebp *)
+ 0C2H, 008H, 000H (* ret 8 *)
+ )
+END _rot;
+
+
+PROCEDURE [stdcall] _set* (b, a: INTEGER); (* {a..b} -> eax *)
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- b *)
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- a *)
+ 039H, 0C8H, (* cmp eax, ecx *)
+ 07FH, 033H, (* jg L1 *)
+ 083H, 0F8H, 01FH, (* cmp eax, 31 *)
+ 07FH, 02EH, (* jg L1 *)
+ 085H, 0C9H, (* test ecx, ecx *)
+ 07CH, 02AH, (* jl L1 *)
+ 083H, 0F9H, 01FH, (* cmp ecx, 31 *)
+ 07EH, 005H, (* jle L3 *)
+ 0B9H, 01FH, 000H, 000H, 000H, (* mov ecx, 31 *)
+ (* L3: *)
+ 085H, 0C0H, (* test eax, eax *)
+ 07DH, 002H, (* jge L2 *)
+ 031H, 0C0H, (* xor eax, eax *)
+ (* L2: *)
+ 089H, 0CAH, (* mov edx, ecx *)
+ 029H, 0C2H, (* sub edx, eax *)
+ 0B8H, 000H, 000H, 000H, 080H, (* mov eax, 0x80000000 *)
+ 087H, 0CAH, (* xchg edx, ecx *)
+ 0D3H, 0F8H, (* sar eax, cl *)
+ 087H, 0CAH, (* xchg edx, ecx *)
+ 083H, 0E9H, 01FH, (* sub ecx, 31 *)
+ 0F7H, 0D9H, (* neg ecx *)
+ 0D3H, 0E8H, (* shr eax, cl *)
+ 05DH, (* pop ebp *)
+ 0C2H, 008H, 000H, (* ret 8 *)
+ (* L1: *)
+ 031H, 0C0H, (* xor eax, eax *)
+ 05DH, (* pop ebp *)
+ 0C2H, 008H, 000H (* ret 8 *)
+ )
+END _set;
+
+
+PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *)
+BEGIN
+ SYSTEM.CODE(
+ 031H, 0C0H, (* xor eax, eax *)
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *)
+ 083H, 0F9H, 01FH, (* cmp ecx, 31 *)
+ 077H, 003H, (* ja L *)
+ 00FH, 0ABH, 0C8H (* bts eax, ecx *)
+ (* L: *)
+ )
+END _set1;
+
+
+PROCEDURE [stdcall] _divmod* (y, x: INTEGER); (* (x div y) -> eax; (x mod y) -> edx *)
+BEGIN
+ SYSTEM.CODE(
+ 053H, (* push ebx *)
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- x *)
+ 031H, 0D2H, (* xor edx, edx *)
+ 085H, 0C0H, (* test eax, eax *)
+ 074H, 018H, (* je L2 *)
+ 07FH, 002H, (* jg L1 *)
+ 0F7H, 0D2H, (* not edx *)
+ (* L1: *)
+ 089H, 0C3H, (* mov ebx, eax *)
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- y *)
+ 0F7H, 0F9H, (* idiv ecx *)
+ 085H, 0D2H, (* test edx, edx *)
+ 074H, 009H, (* je L2 *)
+ 031H, 0CBH, (* xor ebx, ecx *)
+ 085H, 0DBH, (* test ebx, ebx *)
+ 07DH, 003H, (* jge L2 *)
+ 048H, (* dec eax *)
+ 001H, 0CAH, (* add edx, ecx *)
+ (* L2: *)
+ 05BH (* pop ebx *)
+ )
+END _divmod;
+
+
+PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER);
+BEGIN
+ ptr := API._NEW(size);
+ IF ptr # 0 THEN
+ SYSTEM.PUT(ptr, t);
+ INC(ptr, WORD)
+ END
+END _new;
+
+
+PROCEDURE [stdcall] _dispose* (VAR ptr: INTEGER);
+BEGIN
+ IF ptr # 0 THEN
+ ptr := API._DISPOSE(ptr - WORD)
+ END
+END _dispose;
+
+
+PROCEDURE [stdcall] _length* (len, str: INTEGER);
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *)
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *)
+ 048H, (* dec eax *)
+ (* L1: *)
+ 040H, (* inc eax *)
+ 080H, 038H, 000H, (* cmp byte [eax], 0 *)
+ 074H, 003H, (* jz L2 *)
+ 0E2H, 0F8H, (* loop L1 *)
+ 040H, (* inc eax *)
+ (* L2: *)
+ 02BH, 045H, 00CH (* sub eax, dword [ebp + 0Ch] *)
+ )
+END _length;
+
+
+PROCEDURE [stdcall] _lengthw* (len, str: INTEGER);
+BEGIN
+ SYSTEM.CODE(
+ 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *)
+ 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *)
+ 048H, (* dec eax *)
+ 048H, (* dec eax *)
+ (* L1: *)
+ 040H, (* inc eax *)
+ 040H, (* inc eax *)
+ 066H, 083H, 038H, 000H, (* cmp word [eax], 0 *)
+ 074H, 004H, (* jz L2 *)
+ 0E2H, 0F6H, (* loop L1 *)
+ 040H, (* inc eax *)
+ 040H, (* inc eax *)
+ (* L2: *)
+ 02BH, 045H, 00CH, (* sub eax, dword [ebp + 0Ch] *)
+ 0D1H, 0E8H (* shr eax, 1 *)
+ )
+END _lengthw;
+
+
+PROCEDURE [stdcall] strncmp (a, b, n: INTEGER): INTEGER;
+BEGIN
+ SYSTEM.CODE(
+ 056H, (* push esi *)
+ 057H, (* push edi *)
+ 053H, (* push ebx *)
+ 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *)
+ 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *)
+ 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *)
+ 031H, 0C9H, (* xor ecx, ecx *)
+ 031H, 0D2H, (* xor edx, edx *)
+ 0B8H,
+ 000H, 000H, 000H, 080H, (* mov eax, minint *)
+ (* L1: *)
+ 085H, 0DBH, (* test ebx, ebx *)
+ 07EH, 017H, (* jle L3 *)
+ 08AH, 00EH, (* mov cl, byte[esi] *)
+ 08AH, 017H, (* mov dl, byte[edi] *)
+ 046H, (* inc esi *)
+ 047H, (* inc edi *)
+ 04BH, (* dec ebx *)
+ 039H, 0D1H, (* cmp ecx, edx *)
+ 074H, 006H, (* je L2 *)
+ 089H, 0C8H, (* mov eax, ecx *)
+ 029H, 0D0H, (* sub eax, edx *)
+ 0EBH, 006H, (* jmp L3 *)
+ (* L2: *)
+ 085H, 0C9H, (* test ecx, ecx *)
+ 075H, 0E7H, (* jne L1 *)
+ 031H, 0C0H, (* xor eax, eax *)
+ (* L3: *)
+ 05BH, (* pop ebx *)
+ 05FH, (* pop edi *)
+ 05EH, (* pop esi *)
+ 05DH, (* pop ebp *)
+ 0C2H, 00CH, 000H (* ret 12 *)
+ )
+ RETURN 0
+END strncmp;
+
+
+PROCEDURE [stdcall] strncmpw (a, b, n: INTEGER): INTEGER;
+BEGIN
+ SYSTEM.CODE(
+ 056H, (* push esi *)
+ 057H, (* push edi *)
+ 053H, (* push ebx *)
+ 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *)
+ 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *)
+ 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *)
+ 031H, 0C9H, (* xor ecx, ecx *)
+ 031H, 0D2H, (* xor edx, edx *)
+ 0B8H,
+ 000H, 000H, 000H, 080H, (* mov eax, minint *)
+ (* L1: *)
+ 085H, 0DBH, (* test ebx, ebx *)
+ 07EH, 01BH, (* jle L3 *)
+ 066H, 08BH, 00EH, (* mov cx, word[esi] *)
+ 066H, 08BH, 017H, (* mov dx, word[edi] *)
+ 046H, (* inc esi *)
+ 046H, (* inc esi *)
+ 047H, (* inc edi *)
+ 047H, (* inc edi *)
+ 04BH, (* dec ebx *)
+ 039H, 0D1H, (* cmp ecx, edx *)
+ 074H, 006H, (* je L2 *)
+ 089H, 0C8H, (* mov eax, ecx *)
+ 029H, 0D0H, (* sub eax, edx *)
+ 0EBH, 006H, (* jmp L3 *)
+ (* L2: *)
+ 085H, 0C9H, (* test ecx, ecx *)
+ 075H, 0E3H, (* jne L1 *)
+ 031H, 0C0H, (* xor eax, eax *)
+ (* L3: *)
+ 05BH, (* pop ebx *)
+ 05FH, (* pop edi *)
+ 05EH, (* pop esi *)
+ 05DH, (* pop ebp *)
+ 0C2H, 00CH, 000H (* ret 12 *)
+ )
+ RETURN 0
+END strncmpw;
+
+
+PROCEDURE [stdcall] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN;
+VAR
+ res: INTEGER;
+ bRes: BOOLEAN;
+ c: CHAR;
+
+BEGIN
+ res := strncmp(str1, str2, MIN(len1, len2));
+ IF res = minint THEN
+ IF len1 > len2 THEN
+ SYSTEM.GET(str1 + len2, c);
+ res := ORD(c)
+ ELSIF len1 < len2 THEN
+ SYSTEM.GET(str2 + len1, c);
+ res := -ORD(c)
+ ELSE
+ res := 0
+ END
+ END;
+
+ CASE op OF
+ |0: bRes := res = 0
+ |1: bRes := res # 0
+ |2: bRes := res < 0
+ |3: bRes := res <= 0
+ |4: bRes := res > 0
+ |5: bRes := res >= 0
+ END
+
+ RETURN bRes
+END _strcmp;
+
+
+PROCEDURE [stdcall] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN;
+VAR
+ res: INTEGER;
+ bRes: BOOLEAN;
+ c: WCHAR;
+
+BEGIN
+ res := strncmpw(str1, str2, MIN(len1, len2));
+ IF res = minint THEN
+ IF len1 > len2 THEN
+ SYSTEM.GET(str1 + len2 * 2, c);
+ res := ORD(c)
+ ELSIF len1 < len2 THEN
+ SYSTEM.GET(str2 + len1 * 2, c);
+ res := -ORD(c)
+ ELSE
+ res := 0
+ END
+ END;
+
+ CASE op OF
+ |0: bRes := res = 0
+ |1: bRes := res # 0
+ |2: bRes := res < 0
+ |3: bRes := res <= 0
+ |4: bRes := res > 0
+ |5: bRes := res >= 0
+ END
+
+ RETURN bRes
+END _strcmpw;
+
+
+PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR);
+VAR
+ c: CHAR;
+ i: INTEGER;
+
+BEGIN
+ i := 0;
+ REPEAT
+ SYSTEM.GET(pchar, c);
+ s[i] := c;
+ INC(pchar);
+ INC(i)
+ UNTIL c = 0X
+END PCharToStr;
+
+
+PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR);
+VAR
+ i, a: INTEGER;
+
+BEGIN
+ i := 0;
+ a := x;
+ REPEAT
+ INC(i);
+ a := a DIV 10
+ UNTIL a = 0;
+
+ str[i] := 0X;
+
+ REPEAT
+ DEC(i);
+ str[i] := CHR(x MOD 10 + ORD("0"));
+ x := x DIV 10
+ UNTIL x = 0
+END IntToStr;
+
+
+PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR);
+VAR
+ n1, n2: INTEGER;
+
+BEGIN
+ n1 := LENGTH(s1);
+ n2 := LENGTH(s2);
+
+ ASSERT(n1 + n2 < LEN(s1));
+
+ SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2);
+ s1[n1 + n2] := 0X
+END append;
+
+
+PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER);
+VAR
+ s, temp: ARRAY 1024 OF CHAR;
+
+BEGIN
+ CASE err OF
+ | 1: s := "assertion failure"
+ | 2: s := "NIL dereference"
+ | 3: s := "bad divisor"
+ | 4: s := "NIL procedure call"
+ | 5: s := "type guard error"
+ | 6: s := "index out of range"
+ | 7: s := "invalid CASE"
+ | 8: s := "array assignment error"
+ | 9: s := "CHR out of range"
+ |10: s := "WCHR out of range"
+ |11: s := "BYTE out of range"
+ END;
+
+ append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp);
+ append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp);
+
+ API.DebugMsg(SYSTEM.ADR(s[0]), name);
+
+ API.exit_thread(0)
+END _error;
+
+
+PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): BOOLEAN;
+BEGIN
+ (* r IS t0 *)
+ WHILE (t1 # 0) & (t1 # t0) DO
+ SYSTEM.GET(types + t1 * WORD, t1)
+ END
+
+ RETURN t1 = t0
+END _isrec;
+
+
+PROCEDURE [stdcall] _is* (t0, p: INTEGER): BOOLEAN;
+VAR
+ t1: INTEGER;
+
+BEGIN
+ (* p IS t0 *)
+ IF p # 0 THEN
+ SYSTEM.GET(p - WORD, t1);
+ WHILE (t1 # 0) & (t1 # t0) DO
+ SYSTEM.GET(types + t1 * WORD, t1)
+ END
+ ELSE
+ t1 := -1
+ END
+
+ RETURN t1 = t0
+END _is;
+
+
+PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): BOOLEAN;
+BEGIN
+ (* r:t1 IS t0 *)
+ WHILE (t1 # 0) & (t1 # t0) DO
+ SYSTEM.GET(types + t1 * WORD, t1)
+ END
+
+ RETURN t1 = t0
+END _guardrec;
+
+
+PROCEDURE [stdcall] _guard* (t0, p: INTEGER): BOOLEAN;
+VAR
+ t1: INTEGER;
+
+BEGIN
+ (* p IS t0 *)
+ SYSTEM.GET(p, p);
+ IF p # 0 THEN
+ SYSTEM.GET(p - WORD, t1);
+ WHILE (t1 # t0) & (t1 # 0) DO
+ SYSTEM.GET(types + t1 * WORD, t1)
+ END
+ ELSE
+ t1 := t0
+ END
+
+ RETURN t1 = t0
+END _guard;
+
+
+PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER;
+ RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved)
+END _dllentry;
+
+
+PROCEDURE [stdcall] _sofinit*;
+BEGIN
+ API.sofinit
+END _sofinit;
+
+
+PROCEDURE [stdcall] _exit* (code: INTEGER);
+BEGIN
+ API.exit(code)
+END _exit;
+
+
+PROCEDURE [stdcall] _init* (modname: INTEGER; _tcount, _types: INTEGER; code, param: INTEGER);
+BEGIN
+ SYSTEM.CODE(09BH, 0DBH, 0E3H); (* finit *)
+ API.init(param, code);
+ tcount := _tcount;
+ types := _types;
+ name := modname
+END _init;
+
+
+END RTL.
\ No newline at end of file
diff --git a/source/KOS.ob07 b/source/KOS.ob07
index 979a8cf..ec4f3b1 100644
--- a/source/KOS.ob07
+++ b/source/KOS.ob07
@@ -1,7 +1,7 @@
(*
BSD 2-Clause License
- Copyright (c) 2018-2020, Anton Krotov
+ Copyright (c) 2018-2020, 2023, Anton Krotov
All rights reserved.
*)
@@ -77,14 +77,11 @@ BEGIN
END Import;
-PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR);
-
+PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; kernel: BOOLEAN);
CONST
-
PARAM_SIZE = 2048;
FileAlignment = 16;
-
VAR
header: HEADER;
@@ -100,7 +97,7 @@ VAR
ImportTable: CHL.INTLIST;
ILen, libcount, isize: INTEGER;
- icount, dcount, ccount: INTEGER;
+ icount, dcount, ccount, glob32_size: INTEGER;
code: CHL.BYTELIST;
@@ -111,7 +108,11 @@ BEGIN
dcount := CHL.Length(program.data);
ccount := CHL.Length(program.code);
- text := base + HEADER_SIZE;
+ text := base;
+ IF ~kernel THEN
+ INC(text, HEADER_SIZE)
+ END;
+
data := WR.align(text + ccount, FileAlignment);
idata := WR.align(data + dcount, FileAlignment);
@@ -175,18 +176,19 @@ BEGIN
WR.Create(FileName);
- FOR i := 0 TO 7 DO
- WR.WriteByte(ORD(header.menuet01[i]))
+ IF ~kernel THEN
+ FOR i := 0 TO 7 DO
+ WR.WriteByte(ORD(header.menuet01[i]))
+ END;
+ WR.Write32LE(header.ver);
+ WR.Write32LE(header.start);
+ WR.Write32LE(header.size);
+ WR.Write32LE(header.mem);
+ WR.Write32LE(header.sp);
+ WR.Write32LE(header.param);
+ WR.Write32LE(header.path)
END;
- WR.Write32LE(header.ver);
- WR.Write32LE(header.start);
- WR.Write32LE(header.size);
- WR.Write32LE(header.mem);
- WR.Write32LE(header.sp);
- WR.Write32LE(header.param);
- WR.Write32LE(header.path);
-
CHL.WriteToFile(code);
WR.Padding(FileAlignment);
@@ -196,8 +198,15 @@ BEGIN
FOR i := 0 TO ILen - 1 DO
WR.Write32LE(CHL.GetInt(ImportTable, i))
END;
-
CHL.WriteToFile(program._import);
+ WR.Padding(FileAlignment);
+
+ IF kernel THEN
+ glob32_size := program.bss DIV 4 + ORD(program.bss MOD 4 # 0);
+ FOR i := 1 TO glob32_size DO
+ WR.Write32LE(0)
+ END
+ END;
WR.Close
END write;
diff --git a/source/TARGETS.ob07 b/source/TARGETS.ob07
index fb52518..e008a4f 100644
--- a/source/TARGETS.ob07
+++ b/source/TARGETS.ob07
@@ -28,6 +28,8 @@ CONST
STM32CM3* = 13;
RVM32I* = 14;
RVM64I* = 15;
+ KolibriOSKer* = 16;
+ KolibriOSDrv* = 17;
cpuX86* = 0; cpuAMD64* = 1; cpuMSP430* = 2; cpuTHUMB* = 3;
cpuRVM32I* = 4; cpuRVM64I* = 5;
@@ -57,7 +59,7 @@ TYPE
VAR
- Targets*: ARRAY 16 OF TARGET;
+ Targets*: ARRAY 18 OF TARGET;
CPUs: ARRAY 6 OF
RECORD
@@ -106,10 +108,10 @@ BEGIN
LibDir := Targets[i].LibDir;
FileExt := Targets[i].FileExt;
- Import := OS IN {osWIN32, osWIN64, osKOS};
+ Import := (OS IN {osWIN32, osWIN64, osKOS}) & (target # KolibriOSKer);
Dispose := ~(target IN noDISPOSE);
RTL := ~(target IN noRTL);
- Dll := target IN {Linux32SO, Linux64SO, Win32DLL, Win64DLL, KolibriOSDLL};
+ Dll := target IN {Linux32SO, Linux64SO, Win32DLL, Win64DLL, KolibriOSDLL, KolibriOSDrv};
WinLin := OS IN {osWIN32, osLINUX32, osWIN64, osLINUX64};
WordSize := BitDepth DIV 8;
AdrSize := WordSize
@@ -151,4 +153,6 @@ BEGIN
Enter( STM32CM3, cpuTHUMB, 4, osNONE, "stm32cm3", "STM32CM3", ".hex");
Enter( RVM32I, cpuRVM32I, 4, osNONE, "rvm32i", libRVM32I, ".bin");
Enter( RVM64I, cpuRVM64I, 8, osNONE, "rvm64i", libRVM64I, ".bin");
+ Enter( KolibriOSKer, cpuX86, 8, osKOS, "kosker", "KOSKER", ".bin");
+ Enter( KolibriOSDrv, cpuX86, 8, osKOS, "kosdrv", "KOSDRV", ".dll");
END TARGETS.
\ No newline at end of file
diff --git a/source/UTILS.ob07 b/source/UTILS.ob07
index 7ab8954..e6201ec 100644
--- a/source/UTILS.ob07
+++ b/source/UTILS.ob07
@@ -23,8 +23,8 @@ CONST
max32* = 2147483647;
vMajor* = 1;
- vMinor* = 65;
- Date* = "04-feb-2023";
+ vMinor* = 66;
+ Date* = "10-feb-2023";
FILE_EXT* = ".ob07";
RTL_NAME* = "RTL";
diff --git a/source/X86.ob07 b/source/X86.ob07
index 982943f..40a5c32 100644
--- a/source/X86.ob07
+++ b/source/X86.ob07
@@ -774,7 +774,7 @@ BEGIN
END LoadFltConst;
-PROCEDURE translate (pic: BOOLEAN; stroffs: INTEGER);
+PROCEDURE translate (pic: BOOLEAN; stroffs, target: INTEGER);
VAR
cmd, next: COMMAND;
@@ -1887,19 +1887,28 @@ BEGIN
|IL.opISREC:
PushAll(2);
- pushc(param2 * tcount);
+ IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
+ param2 := param2*tcount
+ END;
+ pushc(param2);
CallRTL(pic, IL._isrec);
GetRegA
|IL.opIS:
PushAll(1);
- pushc(param2 * tcount);
+ IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
+ param2 := param2*tcount
+ END;
+ pushc(param2);
CallRTL(pic, IL._is);
GetRegA
|IL.opTYPEGR:
PushAll(1);
- pushc(param2 * tcount);
+ IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
+ param2 := param2*tcount
+ END;
+ pushc(param2);
CallRTL(pic, IL._guardrec);
GetRegA
@@ -1907,7 +1916,10 @@ BEGIN
UnOp(reg1);
PushAll(0);
push(reg1);
- pushc(param2 * tcount);
+ IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
+ param2 := param2*tcount
+ END;
+ pushc(param2);
CallRTL(pic, IL._guard);
GetRegA
@@ -1915,14 +1927,20 @@ BEGIN
UnOp(reg1);
PushAll(0);
pushm(reg1, -4);
- pushc(param2 * tcount);
+ IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
+ param2 := param2*tcount
+ END;
+ pushc(param2);
CallRTL(pic, IL._guardrec);
GetRegA
|IL.opCASET:
push(ecx);
push(ecx);
- pushc(param2 * tcount);
+ IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN
+ param2 := param2*tcount
+ END;
+ pushc(param2);
CallRTL(pic, IL._guardrec);
pop(ecx);
test(eax);
@@ -2286,8 +2304,12 @@ BEGIN
mainLocVarSize := 0;
LocVarSize := 0;
- IF target = TARGETS.Win32DLL THEN
- pushm(ebp, 16);
+ IF target IN {TARGETS.Win32DLL, TARGETS.KolibriOSDrv} THEN
+ IF target = TARGETS.Win32DLL THEN
+ pushm(ebp, 16)
+ ELSE
+ pushc(0)
+ END;
pushm(ebp, 12);
pushm(ebp, 8);
CallRTL(pic, IL._dllentry);
@@ -2390,10 +2412,20 @@ BEGIN
movrc(eax, 1);
OutByte(0C9H); (* leave *)
OutByte3(0C2H, 0CH, 0) (* ret 12 *)
+ ELSIF target = TARGETS.KolibriOSDrv THEN
+ OutByte(0C9H); (* leave *)
+ ret;
+ SetLabel(dllret);
+ movrc(eax, 0);
+ OutByte(0C9H); (* leave *)
+ ret
ELSIF target = TARGETS.KolibriOSDLL THEN
movrc(eax, 1);
OutByte(0C9H); (* leave *)
ret
+ ELSIF target = TARGETS.KolibriOSKer THEN
+ OutByte(0C9H); (* leave *)
+ ret;
ELSIF target = TARGETS.Linux32SO THEN
OutByte(0C9H); (* leave *)
ret;
@@ -2474,6 +2506,10 @@ BEGIN
opt.pic := FALSE
END;
+ IF target IN {TARGETS.KolibriOSKer, TARGETS.KolibriOSDrv} THEN
+ opt.pic := TRUE
+ END;
+
IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32} THEN
opt.pic := TRUE
END;
@@ -2481,14 +2517,16 @@ BEGIN
REG.Init(R, push, pop, mov, xchg, {eax, ecx, edx});
dllinit := prolog(opt.pic, target, opt.stack, dllret);
- translate(opt.pic, tcount * 4);
+ translate(opt.pic, tcount * 4, target);
epilog(opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit);
BIN.fixup(program);
IF TARGETS.OS = TARGETS.osWIN32 THEN
PE32.write(program, outname, target = TARGETS.Win32C, target = TARGETS.Win32DLL, FALSE, opt.PE32FileAlignment)
- ELSIF target = TARGETS.KolibriOS THEN
- KOS.write(program, outname)
+ ELSIF target = TARGETS.KolibriOSDrv THEN
+ PE32.write(program, outname, FALSE, TRUE, FALSE, 512)
+ ELSIF target IN {TARGETS.KolibriOS, TARGETS.KolibriOSKer} THEN
+ KOS.write(program, outname, target = TARGETS.KolibriOSKer)
ELSIF target = TARGETS.KolibriOSDLL THEN
MSCOFF.write(program, outname, opt.version)
ELSIF TARGETS.OS = TARGETS.osLINUX32 THEN