The purpose of this virtual machine is to create a new, general purpose,
hardware independent environment to speed up application development.
Imagine that applications could be developed in any (high level) language.
The compiler first generates code for this virtual machine and in the
second step, an other simply assembler generates working code for
existing processors. The main advantage of this technique is that
high level compilers do not require modification to support new
hardware environment, and every application could compile to any
hardware without modification. So we can say that once we have
a good compiler, it can compile for any (possible not yet existing)
hardware environments. To do this, a simple assembler is needed
to generate machine specific code. It means that this virtual
machine code could be used as an intermediate language between
higher level languages and the machine code. Because of this,
virtual machine is defined with minimal set of instructions and
registers, so every existing (and hopefully future) processors
could used as target machine.
The only things what higher level compilers should know about
target environment are the size of address, and the default integer
size, but of course this knowledge is not required, a well chosen
address size could be enough for every platform.
Another partition of this idea is the way how applications make
system calls (such as file handling, etc). To make a general purpose
virtual machine, we need to define these complex things at 'processor'
level. This is done through the syscall instruction. Once an application
wants to do something with the system, puts the appropriate syscall to
the virtual machine code, and the assembler generates the hardware
specific code to binary output.
add |
size |
reg |
reg/num |
adding op2 to op1 |
sub |
size |
reg |
reg/num |
subtract op2 from op1 |
mul |
sign size |
reg |
reg/num |
multiply op1 by op2 |
div |
sign size |
reg |
reg/num |
divide op1 by op2 |
mod |
sign size |
reg |
reg/num |
remainder from dividing op1 by op2 |
or |
size |
reg |
reg/num |
bitwise oring op1 by op2 |
xor |
size |
reg |
reg/num |
bitwise xoring op1 by op2 |
and |
size |
reg |
reg/num |
bitwise anding op1 by op2 |
not |
size |
reg |
|
bitwise noting op1 |
neg |
size |
reg |
|
negating op1 |
shl |
size |
reg |
reg/num |
shift left op1 by op2 bits |
shr |
size |
reg |
reg/num |
shift right op1 by op2 bits |
push |
size |
reg |
|
put op1 to top of stack |
pop |
size |
reg |
|
get value from top of stack to op1 |
comp |
sign size |
reg |
reg/num |
compare op1 to op2 |
move |
op1.sign op1.size op2.sign op2.size |
reg |
reg/num |
move op2 to op1 |
movr |
format op1.sign op1.size op2.sign op2.size |
reg |
mem |
read op1 from memory |
movw |
format op1.sign op1.size op2.sign op2.size |
mem |
reg |
write op2 to memory |
call |
label |
|
|
jump to label, push offset to stack |
cllr |
src/trg |
|
|
jump to an address, push offset to stack |
ret |
|
|
|
return to saved offset |
jump |
label |
|
|
jump to label |
jmpr |
src/trg |
|
|
jump to an address |
jmpc |
condition |
label |
|
jump to label if condition is true |
setc |
condition |
size |
reg |
set the register to 1 if condition is true, else 0 |
xchg |
size |
mem |
reg |
exchange value in op2 register with op1 memory |
addrLod |
src/trg |
mem |
|
load address from memory to op1 |
addrSav |
mem |
src/trg |
|
save address from op2 to memory |
procAddr |
src/trg |
num |
|
setup op1 to beginning of op2 subroutine's data block |
procAllocBeg |
num |
num |
|
begin allocating op2 bytes to op1 subroutine; use the - as number |
procAllocEnd |
num |
num |
|
finish allocating op2 bytes to op1 subroutine |
procFree |
num |
num |
|
release op2 bytes from op1 subroutine |
codeOfs |
src/trg |
label |
|
get offset of label in code |
sysCall |
function |
|
|
do the function, parameters are in registers |
startup |
|
|
starts the code here [maxproc] [maxstack] [maxheap] |
terminate |
w:a |
|
terminates the code withe error code a |
sleep |
|
|
sleeps the process for a while |
memCopy |
src trg d:c |
|
copy c bytes from [src] to [trg] in memory |
memCopy2 |
src trg d:c |
|
copy c bytes from [src] to [trg] in memory, cares on overlapping |
memFillByte |
trg b:a d:c |
|
fill a byte to trg c times |
memResize |
d:c |
d:c trg |
resize the memory to c, returns the size, and beginning |
getMemInfo |
|
d:c trg |
returns the size, and beginning of extended memory |
codeCopy |
src trg d:c |
|
copy c bytes from code [src] to memory [trg] |
console.write |
src d:c |
|
write c bytes from src to the console |
console.iskey |
|
b:a |
test for char on console (1=yes, 0=no) |
console.read |
trg d:c |
d:c |
read c bytes to trg from the console, returns number of bytes read in c |
console.size |
|
w:a w:b |
read console size (a=x, b=y) |
console.clear |
|
|
clears the console |
console.gotoXY |
w:a w:b |
|
set the cursor to a column and b row |
console.setColor |
b:a |
|
set the pen color to ibm attributes |
console.getDate |
|
w:a w:b w:c |
returns current date, a-year, b-month, c-day |
console.getTime |
|
w:a w:b w:c |
returns current time, a-hour, b-minute, c-second |
console.execWait |
src trg |
w:a w:b |
execute process in trg with src parameter, wait until terminate, returns exitcode in a (b=error) |
file.maxName |
|
w:a |
returns maximum name length |
file.myName |
trg |
w:c |
returns pathname of running process |
file.myParam |
trg |
w:c |
returns parameters of running process |
file.open |
src d:a |
d:a w:b |
open file on pascii name src with a rights, handler returned in a (b=error)
|
file.read |
d:a trg d:c |
d:c w:b |
read c bytes to trg memory from file handler a, return c bytes read,
(b=error) |
file.write |
d:a src d:c |
w:b |
write c bytes from src memory to file handler a (b=error) |
file.seek |
d:a d:c |
w:b |
seek to c position in file handler a (b=error) |
file.getSize |
d:a |
d:c w:b |
get file size to c from handler a (b=error) |
file.getPos |
d:a |
d:c w:b |
get file position to c from handler a (b=error) |
file.truncate |
d:a |
w:b |
truncate file handler a (b=error) |
file.close |
d:a |
w:b |
close the file handler a (b=error) |
file.create |
src |
w:b |
create pascii src named file (b=error) |
file.erase |
src |
w:b |
erase pascii src named file (b=error) |
dir.current |
trg |
w:b |
get working directory to trg in pascii (b=error) |
dir.change |
src |
w:b |
change working directory from src in pascii (b=error) |
dir.statistic |
|
d:a d:b d:c d:d |
get disk statistics: a-free, b-used, c-bad, d-blocksize |
dir.setRights |
src d:a d:b |
w:b |
set directory entry access rights to a and owner to b (b=error) |
dir.setDate |
src trg |
w:b |
set src directory entry create,modify date to trg (b=error) |
dir.reName |
src trg |
w:b |
rename src directory entry to trg name (b=error) |
dir.makeLink |
src trg |
w:b |
create link to src directory entry under trg name (b=error) |
dir.open |
src |
d:a w:b |
open directory on pascii src name, handler returned in a (b=error) |
dir.read |
d:a trg |
w:b |
read dir entry to trg memory from dir handler a (b=error)
format: d:size, d:rights, d:owner, t:create, t:modify, pascii:name
t: w:year, b:month, b:day, b:hour, b:minute, b:second |
dir.close |
d:a |
w:b |
close the directory handler a (b=error) |
dir.create |
src |
w:b |
create pascii src named directory (b=error) |
dir.erase |
src |
w:b |
erase pascii src named directory (b=error) |
pipeline.startListen |
|
w:b |
start listening for incoming pipelines (b=error) |
pipeline.stopListen |
|
w:b |
stop listening for incoming pipelines (b=error) |
pipeline.getIncoming |
|
w:b d:a |
get next incoming pipeline number in a (b=error) |
pipeline.create |
d:a d:c b:b |
w:b d:a |
create c bytes pipe to a process b=1 if block mode, pipe id a (b=error) |
pipeline.close |
d:a |
w:b |
close pipeline a (b=error) |
pipeline.info |
d:a |
d:a d:c d:d w:b |
pipeline info, a=process, c=freeTx, d=usedRx (b=error) |
pipeline.receive |
d:a trg d:c |
d:c w:b |
receive c bytes to trg from a pipeline, c bytes received (b=error) |
pipeline.send |
d:a src d:c |
w:b |
send c bytes from src to a pipeline (b=error) |
system.getPID |
|
d:a d:b d:c |
returns a=process id, b=parent process id, c=rights |
system.getUID |
|
d:a d:b |
returns my user id in a, original in b |
system.sysInfoNum |
|
d:a d:c d:d |
returns a=#of proc, c=#of pipes, d=#of files |
system.sysInfoMem |
|
d:a d:c d:d |
returns memory in byte a=total, c=kernel, d=free |
system.sysInfoProc |
|
d:a d:b d:c d:d |
returns process starts a=idles, b=rounds, c=full rounds, d=active start |
system.procInfoNam |
d:a trg |
d:a d:c d:d |
returns info about [a] process, trg=pathname+param, a=uid, c=parent pid, d=rights |
system.procInfoNum |
d:a |
d:a d:c d:d |
returns info about [a] process, a=bytes, c=pipes, d=files |
system.procInfoRun |
d:a |
d:a d:b d:c |
returns process runs a=working since, b=times was busy, c=times run |
system.findProcNum |
d:a |
d:a |
find process by number (0..max-1) |
system.findProcNam |
src |
d:a |
find process by name |
system.cpuInfo |
d:a trg |
d:a d:c |
get cpu info (0..max-1), a=max, c=number |
system.kernelInfo |
trg |
|
get kernel info to trg in asciiZ |
system.kernelLogo |
trg |
|
get kernel logo to trg in asciiZ |
system.procLive |
d:a |
d:b |
check process existence, 0=no, 1=yes |
system.uptimeInfo |
|
d:a d:c d:d |
get uptime info, a=days, c=ticks, d=ticks/day |
system.killProcess |
d:a |
d:b |
kill another process |
syscalls require extra privileges:
1 |
change directory |
dir, fn1, uid |
2 |
drive statistics |
data: free,used,bad,blockSize:dword |
3 |
create directory |
dir, fn1, uid |
4 |
erase directory |
dir, fn1, uid |
5 |
create file |
dir, fn1, uid |
6 |
erase file |
dir, fn1, uid |
7 |
rename |
dir, fn1, fn2, uid |
8 |
create link |
dir, fn1, fn2, uid |
9 |
set rights |
dir, fn1, uid, data: rights,owner:dword |
10 |
set date |
dir, fn1, uid, data: create,modify:time |
11 |
open directory |
dir, fn1, uid, hdr, data: inode,rights:dword; name:string |
12 |
read directory |
hdr, data: size,right,own:dword; create,modify:time; name:string |
13 |
open file |
dir, fn1, right, uid, hdr, data: inode,rights:dword; name:string |
14 |
read file |
hdr, size, data |
15 |
write file |
hdr, size, data |
16 |
seek file |
hdr, data: position:dword |
17 |
get file size |
hdr, data: filesize:dword |
18 |
get file position |
hdr, data: position:dword |
19 |
truncate file |
hdr |