📄 appendix b the salvm instruction set.htm
字号:
<P>The second step involves matching the result of the comparison to the
particular instruction being executed. For instance, if we are executing a
<TT>GTRx</TT> instruction, and the result was greater than zero, then we can
return a true. If the result was equal to zero, or less than zero, then we would
return a false. The result that is returned is pushed onto the stack as a byte
containing a 1 for true and a zero for false.
<P>In these instructions, the EES ordering is the same as it has always been. In
other words, if we want to compare A to B, then we push A onto the EES and then
B. Let's have an example. See figure {COMPEX} <PRE> dword B --> | 257F9A01 | 4D8A2B09 | 01 |
dword A --> | 4D8A2B09 | - 257F9A01 | |
| | ---------- | |
| ... | 280A9108 | ... |
|____________| |____________|
EES Result is positive, EES
Before A > B After
<B>Figure {COMPEX}</B> A figure representing the comparison of two dwords
to see if A is greater than or equal to B.
</PRE>As of yet, there are no instructions to compare tenbytes and and quad
precision floats. These need to be done in blocks, starting with the most
significant block, and comparing while equal until the last block, much like a
string compare.
<P>
<H2>B.7 Flow Control Instructions</H2><!-------------------------------------------------------------------------------->The
flow control op-codes deal with branching: either conditional or unconditional.
The condidional jump instructions take one byte from the EES, and jump depending
on whether the byte is zero or nonzero. Some of the jump op-codes take a 32-bit
signed number designating the offset from the current PC to jump to. Table
{JMPINS} explains these instructions. <PRE> Op Name Description New PC computed by
========================================================================================
JMP JuMP Unconditional jump 32-bit immediate offset
SJMP Short JuMP Unconditional jump 16-bit immediate offset
JMPS Jump stack Unconditional jump New PC is on the EES
JPZ JumP if Zero Jump if EES byte is zero 32-bit immediate offset
JPNZ JumP if NonZero Jump if EES byte is nonzero 32-bit immediate offset
SJPZ Short JumP if Zero Jump if EES byte is zero 16-bit immediate offset
SJPNZ Short JumP if NonZero Jump if EES byte is nonzero 16-bit immediate offset
JSR Jump SubRoutine Jump to subroutine 32-bit immediate offset
JSRS Jump SubRoutine stack Jump to subroutine New PC is on the EES
RTS ReTurn from Subroutine Return from subroutine dword stored at S
<B>Table {JMPINS}</B> the flow control instructions.
</PRE>For the most part, these instructions are straightforward. The first three
branch unconditionally. <TT>JMPS</TT> jumps to a previously computed PC that is
on the EES. Such a value would be computed using the <TT>LPCA</TT> instruction.
The same goes for <TT>JSRS</TT>. The conditional jump instructions consume a
byte from the EES, that is usually the previous result of a comparison.
<P>A subroutine is a little different from a jump. In fact, it is kind of half
way between a jump and a procedure call. Upon executing a <TT>JSR</TT> or a
<TT>JSRS</TT> instruction, the current PC is placed on the stack at S, and S is
incremented by four bytes. Upon encountering a <TT>RTN</TT> instruction, the VM
will decrement S by four, and retrieve the old PC. With subroutines, local
variables are kept in scope, and a call to a subroutine is faster. In the SAL
compiler, subroutines are used to perform cleanup of local variables prior to
exiting a function. <TT>JMPS</TT> and <TT>JSRS</TT> are used in the compiler for
exception handeling. The conditional instructions are used in the branching and
looping statements in the compiler. These op-codes are fully explained in the
chapters where they apply.
<P>
<H2>B.8 Procedural Instructions</H2><!-------------------------------------------------------------------------------->The
procedural instructions are explained in chapter {Procedures and functions}. We
will only briefly cover these instructions here. They are listed in table
{PROCINS}. <PRE> Op Name
===============================================
CL Call Local
CX Call eXternal
CI Call Immediate
CF Call Formal
CV Call Virtual
RTN ReTurN from function/procedure
ENTR ENTeR procedure
ALLOC ALLOCate stack space
PCOP Parameter COPy
GM Get M register
GB Get Base local area
<B>Table {PROCINS}</B> The procedure-related op-codes.
</PRE><B><TT>CL</TT>: Call Local.</B> This instruction calls a procedure within
the current module. This instruction is used in the default calling mechanism,
i.e., neither the calling procedure or the procedure being called are nested,
and the procedure is within the current module, and so on.
<P><B><TT>CX</TT>: Call eXternal.</B> We use this op-code whenever we call a
procedure that is in another module. Usually, calling an external procedure
involves setting the M, G, F, and R registers. This differentiates <TT>CL</TT>
from <TT>CX</TT>.
<P><B><TT>CI</TT>: Call Immediate.</B> <TT>CI</TT> is used when both the calling
procedure and the procedure being called are nested within another procedure.
This instruction involves maintining the local variables of the last local call,
since nested procedures can see local variables of the parent procedure. Nested
procedures are rather like high-level subroutines. All local variables of the
parent procedure are visible, and the nested procedure can have local variables
of its own.
<P><B><TT>CF</TT>: Call Formal.</B> This op-code is used whenever we have a
pointer to a procedure. Procedures are usually called by specifying a procedure
number if the new procedure is local, or a module number and a procedure number
if the new procedure is external. With <TT>CF</TT>, we can call to a procedure
and begin execution at a specific address.
<P><B><TT>CV</TT>: Call Virtual.</B> This instruction calls a virtual function
for a class. It is explained in more detail in the chapter on virtual functions.
<P><B><TT>RTN</TT>: ReTurN.</B> Reguardless of the method used to call a
procedure or function, the method to return is the same. This instruction
returns to the previous point of execution.
<P><B><TT>ENTR</TT>: ENTeR.</B> This is the first instruction of all procedures
and functions. Its purpose is to reserve space on the stack for all local
variables. Its presence is manditory, as all calling instructions check for it
before continuing. If this instruction is not present, all of the <TT>Cx</TT>
instructions will fail, causing a native exception.
<P><B><TT>ALLOC</TT>: ALLOCate.</B> This instruction's purpose is to allocate
additional stack space for local copies of arrays, etc.
<P>
<H2>B.9 Mischellaneous Instructions</H2><!-------------------------------------------------------------------------------->The
last group of instructions is a really mixed bag. They do all sorts of things,
and they are spread throughout the instruction space. They are listed in table
{MISCINS}. <PRE> Op Name
=========================================================
TRON TRace On
TROFF TRace OFF
TRAP TRAP
DCAS
TS Test and Set
TR Teas and Reset
COPT COPy Top
POP POP
SWAP SWAP
RSYS Register SYStem call
SYS SYStem call
INCS INCrement S
DECS DECrement S
ASUB Array SUBtract
AINDX Array INDeX
NOP NO Operation
<B>Table {MISCINS}</B> All the rest of the VM op-codes.
</PRE><B><TT>TRON</TT>: TRace On.</B> This instruction puts the VM into debug
mode. The VM's software interface allows the programmer to set a native level
callback, which gets passed the current state of the VM. Using this feature, VM
developers can write an integrated debugger for the VM. In debug mode, the VM
will make a call to the callback after executing each instruction.
<P><B><TT>TROFF</TT>: TRace OFF.</B> This has the opposite effect of
<TT>TRON</TT>. If the VM is in debug mode, it will leave debug mode. Otherwise
it will have no effect.
<P><B><TT>TRAP</TT>: TRAP.</B> This instruction throws a native exception
signalling some fatal error within the VM. VM developers may also choose to set
a callback function to handle these errors. They are always fatal, and upon
returning from the callback, the VM will exit. The fatal errors of the VM are
listed in table {VMERRS} <PRE> Error Name Error Description
========================================================================
TRAP_NOERROR, No error has occurred
TRAP_INVALIDPROC, Tried to call an invalid procedure
TRAP_INVALIDOP, Tried to execute an invalid op-code
TRAP_INVALIDOPERAND, An operand was invalid for a particular op-code
TRAP_INVALIDSYS, Attempt to call some non-existant syscall
TRAP_ARRAYRANGE, Array subscript error
TRAP_EESUNDER, EES underflow
TRAP_EESOVER, EES overflow
TRAP_NOMALLOC, Unable to allocate memory
TRAP_INVALIDMOD, Reference to an invalid module
TRAP_STACKUNDER, Procedure stack underflow
TRAP_STACKOVER, Procedure stack overflow
TRAP_LSNULL, Tried to use LSx with a null pointer in EES
TRAP_INVALIDSUBFUNC, Attempt to call some non-existant syscall sub-function
TRAP_EXUNHANDLED, An unhandled SAL Exception was encountered
TRAP_EXCORRUPT, Exception stack not empty, or corrupt
TRAP_EXCEPTION An unknown SAL exception was thrown
<B>Table {VMERRS}</B> A listing of the fatal VM errors. These are typedefed in
an enumerated type, called EnumTrap.
</PRE><B><TT>DCAS</TT>: .</B> Double Compare And Swap.
<P>This instruction takes from the EES two addresses and 4 U32 values. If the
both values at the Addresses are equal to the first pair of U32 parameters, the
value at both addresses is set to the second pair of U32 values. <B><TT>TS</TT>:
Test and Set.</B> This instruction will test a byte at a given address found on
the EES. The byte will be set to true, and the previous value at that address
will be pushed onto the EES
<P><B><TT>TR</TT>: Test and Reset.</B> This instruction does a similar thing,
but it will set a byte to zero, instead. <TT>TS</TT> and <TT>TR</TT> are used to
design synchronization primitives. They are useful for making semaphores and
critical sections.
<P><B><TT>COPT</TT>: COPy Top.</B> This instruction will make a copy of the
topmost <I>n</I> bytes on the EES. The amount of bytes copies is a one-byte
immediate parameter, and must have the values 1, 2, 4, or 8. This instruction is
most useful for copying a pointer at the top of the EES.
<P><B><TT>POP</TT>: POP.</B> This op-code takes a two-byte immediate parameter,
designating the amount of bytes of the EES to be discarded.
<P><B><TT>SWAP</TT>: SWAP.</B> This instruction takes two word-sized immediate
parameters, <I>m</I> and <I>n</I>. It's function is to swap the topmost <I>m</I>
bytes of the EES with the <I>n</I> bytes underneath.
<P>This instruction is handy when working with stack-based architectures. Often,
a pointer will be buried at the bottom of the EES, and will need to be brought
to the top. Other times, data will get pushed onto the EES in the wrong order.
<P><B><TT>RSYS</TT>: Register SYStem call.</B> This procedure registers a SAL
function as a system call. (not yet defined how this will work)
<P><B><TT>SYS</TT>: SYStem call.</B> This op-code will invoke a native-level
service of some sort. Virtual machines by their nature are rather slow, and
often- repeated tasks, like converting data to text or moving blocks of memory
can be really slow, if done by the VM directly. The SYS calls are analogous to
the software interrupts in the Intel x86 architecture under DOS, except they are
more numerous, and include the functionality of the standard C library. They
perform math, string manipulation, file I/O, console input and output, network
communication, and a host of other services. This is how SAL programs can
interface with the rest of the computer.
<P><B><TT>INCS</TT>: INCrement S.</B> This instruction increments the S
register, effectively allocating more space within the local call frame. It
takes an immediate dword parameter.
<P><B><TT>DECS</TT>: DECrement S.</B> This op-code decrements the S register by
the value specified in an immediate dword parameter. The <TT>INCS</TT> and
<TT>DECS</TT> instructions are used for reserving stack space for functions that
return complex data by value, like an array or a record.
<P><B><TT>ASUB</TT>: Array SUBtract.</B> This and the <TT>AINDX</TT>
instructions are explained more in {Chapter on arrays and records}.
<TT>AINDX</TT> will take a dword on the EES, and test to see if it is within the
lower boundary of an array subscript. If so, it will subrtact the value by the
array's lower boundary. If not, it will throw a native exception.
<P><B><TT>AINDX</TT>: Array INDeX.</B> This instruction will take a zero-based
array index (a 32-bit value on the EES) and test it to see if it is within the
arrays upper limit. If it is, it will multiply the index by the size of one
element of the array, and add it to the current base address (also on the EES).
<P><B><TT>NOP</TT>: No Operation.</B> <TT>NOP</TT>'s job is to do nothing. It is
useful for word-aligning instructions, or for just filling in gaps in the code-
stream. Its presence in the instruction set is traditional, and it is not used
in the compiler.
<P><!-------------------------------------------------------------------------------->
<P>
<P></P></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -