1
0
forked from GitHub/lad
Files
lad/5.2/doc/manual.html
T
2013-08-04 10:41:28 -03:00

870 lines
29 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Lua Assembler/Disassembler</title>
<style type=text/css>
<!--
hr {
background-color: #BCAE79;
border-width: 1px;
color: #BCAE79;
height: 1px;
padding: 0;
width: 98%;
}
a {
text-decoration: none;
}
h3 {
color: #3175A2;
}
body {
background: #F4F4F4;
font-size: 12px;
line-height: 150%;
font-family: verdana, sans-serif
}
div#container {
width: 80%;
margin-left: 10%;
margin-right: 10%;
border: 1px solid #F0F0F0;
background: white;
}
div#logo {
margin: 2px 2px 2px 2px;
}
div#content {
margin: 20px 10px 10px 10px;
border: 1px solid #F0F0F0;
padding-left: 10px;
padding-right: 10px;
text-align: justify;
}
div#menu {
margin: 2px 2px 2px 20px;
}
div#footer {
margin: 2px 10px 20px 10px;
clear: both;
border: 1px solid #F0F0F0;
}
.lua-code {
background-color: #F4F4F4;
border: 1px solid silver;
font-family: "Andale Mono", monospace;
margin-left: 1em;
margin-right: 1em;
padding: 1em;
}
pre span {color:gray}
code {
font-size: medium;
font-weight: bold;
color: gray;
}
table#solid {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
}
table#solid th {
border: 1px solid black;
padding: 0.5em;
}
table#solid td {
border: 1px solid black;
padding: 0.5em;
}
span.function {
color: #00008BA2;
font-weight: bold;
}
table.func-parts {
padding-left: 10px;
padding-bottom: 10px;
}
table.func-parts td.part {
font-weight: bold;
}
div.api {
padding-left: 10px;
padding-top: 10px;
}
//
-->
</style>
</head>
<body>
<div id="container">
<div id="logo">
<center><img alt="xmlparser logo" src="logo1.png"></center>
<div id="menu">
<center>
<h3>Lua Assembler/Disassembler</h3>
<a href="#description">Description</a> | <a href="#requirements">Requirements</a> | <a href="#install">Install</a> |
<a href="#assembler">Assembler</a> | <a href="#disassembler">Disassembler</a> |
<a href="#how-to-use">How To Use</a> | <a href="#examples">Examples</a> | <a href="#syntax">Assembly Syntax</a> |
<a href="#opcodes">Instructions</a> | <a href="#notes">Notes</a> | <a href="#licence">Licence</a>
</center>
</div>
</div>
<div id="content">
<h3><a name="description">Description</a></h3>
<p><code>Lua Assembler/Disassembler</code> is a tool that can be used to generate Lua bytecode and Assembly code.
Lua bytecode is generated through the assembler provided, while Assembly code is generated by the disassembler,
which inspects Lua bytecode in order to reproduce it into an Assembly language.
The assembler uses <a href="http://www.inf.puc-rio.br/~roberto/lpeg/">Lpeg</a> in order to implement the parser
for our Assembly syntax, which is presented on this document.
</p>
<hr>
<h3><a name="requirements">Requirements</a></h3>
<code>Lua Assembler/Disassembler</code> is compatible with Lua version 5.2.0 and Lpeg version 0.10.2.
<hr />
<h3><a name="install">Install</a></h3>
<p>
To run <code>Lua Assembler/Disassembler</code> in your computer, first you need install the
<a href="http://www.lua.org/download.html">Lua language</a> and the
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/#download">Lpeg</a> library.
The <code>Lua Assembler/Disassembler</code> may be executed as an application/script and
can be used as a module in your Lua code too.
In order to install, please, <a href="">download</a> the source code, extract it and then
follow below instructions to have the applications/scripts and modules installed.
</p>
<h4><a name="install_script">Installing scripts</a></h4>
<p>
Just copy the following files to a directory in your computer or
to your $PATH (which will depend on the operating system).
</p>
<ul>
<li><code>luaa.lua</code></li>
<li><code>luad.lua</code></li>
</ul>
<p>
Since the applications/scripts use the modules to run assembler and disassembler
functions, please, do not forget to follow below steps in order to get them installed.
</p>
<h4><a name="install_module">Installing modules</a></h4>
<p>
Just copy the following files to the first directory that is set in <b>package.path</b>.
</p>
<ul>
<li><code>assembler.lua</code></li>
<li><code>disassembler.lua</code></li>
<li><code>ladconf.lua</code></li>
</ul>
<p>
You can also copy above files to other directory, if that's the case, please, do not
forget to change <b>package.path</b>, in your Lua code, in order to look for the modules
in the directory that you have installed them.
</p>
<hr />
<h3><a name="assembler">Assembler</a></h3>
<p>
The assembler might be used as a stand alone application/script or as a module that
you require in your code.
</p>
<h4><a name="assembler_script">Assembler script</a></h4>
The stand alone application/script is called <b>luaa.lua</b>.
The following synopsis should be used:
<pre class="lua-code">
lua luaa.lua [options] [filename]
</pre>
<p>Available options are listed below and must be separate.</p>
<a name="op-com"><h3 style="color:#00008B;">-h</h3></a>
<p>
Just prints a help message listing all available options and a brief explanation about them.
</p>
<!--
<a name="op-mat"><h3 style="color:#00008B;">-b</h3></a>
<p>
Output file on <b>big endian</b>, instead of the default <b>little endian</b>.
</p>
-->
<a name="op-ver"><h3 style="color:#00008B;">-o file</h3></a>
<p>
Output to <b>file</b>, instead of the default <b>luaa.out</b>.
Be careful to not overwrite precious files since you might specify the output file as an existent source file.
</p>
<h4><a name="assembler_module">Assembler module</a></h4>
<p>
The module is called <b>assembler</b> and something like below line should be used in order to make
its functions available.
</p>
<pre class="lua-code">
local assembler = require("assembler")
</pre>
<p>Available functions are listed below.</p>
<a name="op-com"><h3 style="color:#00008B;">assembler.parse(contents)</h3></a>
<p>
The function parse gets the contents of an Assembly source code as its only
argument and returns its Abstract Syntax Tree (AST).
</p>
<a name="op-mat"><h3 style="color:#00008B;">assembler.traverse(ast)</h3></a>
<p>
The function traverse gets the AST, returned by parse function, and inspects
the AST to find errors. If no errors were found, than all information inside
the AST are combined into a table that will be used to write the correspondent
Lua bytecode.
</p>
<a name="op-ver"><h3 style="color:#00008B;">assembler.write(filename, parsed)</h3></a>
<p>
The function write gets two parameters: the first one is the filename were
Lua bytecode should be written, while the second one is the table returned
by traverse function.
</p>
<a name="op-ver"><h3 style="color:#00008B;">assembler.print_ast(ast)</h3></a>
<p>
The function print_ast might be used for debug purposes. It receives the AST
as its only parameters and prints it.
</p>
<hr />
<h3><a name="disassembler">Disassembler</a></h3>
<p>
The disassembler might be used as a stand alone application/script or as a module that
you require in your code.
</p>
<h4><a name="disassembler_script">Disassembler script</a></h4>
The stand alone application/script is called <b>luad.lua</b>.
The following synopsis should be used:
<pre class="lua-code">
lua luad.lua [options] [filename]
</pre>
<p>Available options are listed below and must be separate.</p>
<a name="op-com"><h3 style="color:#00008B;">-h</h3></a>
<p>
Just prints a help message listing all available options and a brief explanation about them.
</p>
<a name="op-mat"><h3 style="color:#00008B;">-l</h3></a>
<p>
Produce a listing of the compiled bytecode for Lua's virtual machine on <b>luac -l</b> style.
Use -l -l for full listing.
</p>
<a name="op-ver"><h3 style="color:#00008B;">-o file</h3></a>
<p>
Output to <b>file</b>, instead of the default <b>luad.asm</b>.
Be careful to not overwrite precious files since you might specify the output file as an existent source file.
</p>
<h4><a name="disassembler_module">Disassembler module</a></h4>
<p>
The module is called <b>disassembler</b> and something like below line should be used in order to make
its functions available.
</p>
<pre class="lua-code">
local disassembler = require("disassembler")
</pre>
<p>Available functions are listed below.</p>
<a name="op-com"><h3 style="color:#00008B;">disassembler.parse(bytecode)</h3></a>
The function parse gets a chunk of Lua bytecode as its only
argument and returns a table containing all information that
are necessary to write its correspondent Assembly code.
<p>
</p>
<a name="op-mat"><h3 style="color:#00008B;">disassembler.write(filename, parsed)</h3></a>
The function write gets two parameters: the first one is the filename were
the Assembly code should be written, while the second one is the table returned
by parse function.
<p>
</p>
<a name="op-ver"><h3 style="color:#00008B;">disassembler.print_function(parsed, full)</h3></a>
<p>
The function print_function might be used for printing Lua bytecode in <b>luac -l</b> style.
It has two parameters: the first one is the table returned by parse function and
the second one is a boolean value indication if full listing is expected or not.
</p>
<hr/>
<h3><a name="how-to-use">How To Use</a></h3>
<p>The following command line shows how to use the <code>disassembler</code> in order to generate the assembly code
for a Lua source file:
<pre class="lua-code">
$ lua luad.lua -o hello.asm hello.lua
</pre>
The above command line outputs <b>hello.asm</b> which contains the assembly code for <b>hello.lua</b>.
<br><br>
It is important to remember that the <code>disassembler</code> can be used with a Lua bytecode too, as we shown below:
<pre class="lua-code">
$ lua luad.lua luac.out
</pre>
Notice that in this case we haven't specified the output file, in this way the output will be the default <b>luadd.asm</b>.
<br><br>
<p>The following command line shows how to use the <code>assembler</code> in order to generate Lua bytecode from
our assembly code:
<pre class="lua-code">
$ lua luaa.lua -o hello.out hello.asm
</pre>
The above command line outputs <b>hello.out</b> which contains Lua bytecode for <b>hello.asm</b> and can be executed using lua.
<br><br>
It is important to remember that if you do not specify the output file, then Lua bytecode will be generated as <b>luaa.out</b> by default.
<hr />
<h3><a name="examples">Examples</a></h3>
In this section we show some examples of our <b>assembly</b> language. The complete syntax can be checked
at <a href="#syntax">Assembly Syntax</a> as well as opcodes can be checked at <a href="#opcodes">Instructions</a>.
Here we show the assembly code that were generated, on above section, for <b>hello.lua</b> which is a simple
<b>hello world</b> program.
<pre class="lua-code">
function main(0):
1 [1] GETTABUP $0, _ENV, "print"
2 [1] LOADK $1, "hello world!"
3 [1] CALL $0, 2, 1
4 [1] RETURN $0, 1
</pre>
Once we use the <code>assembler</code> to output the Lua bytecode we can execute it using lua, as follows:
<pre class="lua-code">
$ lua hello.out
hello world!
$
</pre>
Now we define a recursive factorial in our Assembly language. Notice that <b>line number</b> and
<b>source line number</b> are not needed when we are writting the Assembly code. However, they are
generated when the <b>disassembler</b> process is performed.
<pre class="lua-code">
function main(0):
CLOSURE $0, fat
SETTABUP _ENV, fat, $0
GETTABUP $0, _ENV, print
GETTABUP $1, _ENV, fat
LOADK $2, 5
CALL $1, 2, 0
CALL $0, 0, 1
RETURN $0, 1
function fat(1):
EQ 0, $0, 0
JMP 0, label1 ; jump to label1
LOADK $1, 1
RETURN $1, 2
label1: GETTABUP $1, _ENV, fat ; create label1
SUB $2, $0, 1
CALL $1, 2, 2
MUL $1, $0, $1
RETURN $1, 2
RETURN $0, 1
</pre>
Notice that we have used a <b>label</b> in <b>fat</b> function since it is easier to check where to jump
when we are writing manual assembly code.
Also notice that a comment starts with a semicolon (<b>;</b>) and finishes at the end of the line.
A function <b>main</b> is necessary for all Assembly codes and the number of
parameters for the function that is being defined should be specified between
parenthesis.
<hr />
<h3><a name="syntax">Assembly Syntax</a></h3>
Here is the complete syntax of Assembly in <code>lpeg re</code> module.
<pre class="lua-code">
prog <- s function* !.
function <- header codelist
header <- "function" s name s "(" s n s ")" s ":" s
codelist <- code+
code <- autocode / manualcode
autocode <- n s ln s op s param s ("," s param s)*
manualcode <- (label s)? op s param s ("," s param s)*
n <- %d+
label <- name ":"
name <- !reserved {[a-zA-Z_][a-zA-Z0-9_]*}
ln <- "[" %d+ "]"
op <- !reserved %a+
param <- register / number / string
register <- "$" n
number <- hex / float / int
string <- name / shortstr
shortstr <- '"' ('\\' / '\"' / !'"' .)* '"' / "'" ("\\" / "\'" / !"'" .)* "'"
hex <- "-"? "0" [xX] %x+
float <- "-"? ( (%d+ "." %d* / "." %d+) e? / %d+ e )
e <- [eE] [+-]? n
int <- "-"? n
s <- (space / comment)*
space <- %s+
comment <- ";" (!%nl .)*
reserved <- "function"
</pre>
<hr />
<h3><a name="opcodes">Instructions</a></h3>
<p>
We have four main types of instructions, they are so called <b>iABC</b>, <b>iABx</b> , <b>iAsBx</b>
and <b>iAx</b>. The instructions should be used as follows:
</p>
<center>
<table id='solid'>
<tr>
<td><strong>Instruction type</strong></td>
<td><strong>Pattern</strong></td>
</tr>
<tr>
<td>iABC</td>
<td>OPCODE A, B, C</td>
</tr>
<tr>
<td>iABx</td>
<td>OPCODE A, Bx</td>
</tr>
<tr>
<td>iAsBx</td>
<td>OPCODE A, sBx</td>
</tr>
<tr>
<td>iAx</td>
<td>OPCODE Ax</td>
</tr>
</table>
</center>
<p>
Some <b>iABC</b> instructions do not use argument B or C and below we specify when that is the case.
Nonetheless, most of the <b>iABC</b> instructions follow the pattern described in above table.
</p>
<p>
It is also important to keep in mind that parameters should comply with the <a href="#syntax">Assembly Syntax</a>.
Here a some examples:
</p>
<center>
<table id='solid'>
<tr>
<td><strong>Parameter type</strong></td>
<td><strong>Example</strong></td>
</tr>
<tr>
<td>Register</td>
<td>$0, $1, $2, ...</td>
</tr>
<tr>
<td>Number</td>
<td>0, 1, 2, ... / -1, -2, ... / 0.1, 0.2, ..., 1.0, 1.1, ... / -0.1, -0.2, ..., -1.0, -1,1, ...</td>
</tr>
<tr>
<td>Name</td>
<td>F_0_1, blah, foo, ...</td>
</tr>
<!--
<tr>
<td>Nil</td>
<td>NIL</td>
</tr>
<tr>
<td>Boolean</td>
<td>TRUE / FALSE</td>
</tr>
-->
<tr>
<td>String</td>
<td>"oi, tudo bem?", "hello world", "%s, string", ...</td>
</tr>
</table>
</center>
<p>
We will use a instruction notation as follows to show how to use each opcode.
</p>
<center>
<table id='solid'>
<tr>
<td><strong>Notation</strong></td>
<td><strong>Meaning</strong></td>
</tr>
<tr>
<td>R(A), R(B), R(C)</td>
<td>Register specified in field A, B or C.</td>
</tr>
<tr>
<td>PC</td>
<td>Program Counter.</td>
</tr>
<tr>
<td>Kst(k)</td>
<td>A constant <b>k</b> that will be translated to a number.</td>
</tr>
<tr>
<td>Upvalue(name)</td>
<td>An upvalue <b>name</b> that will be translated to a number.</td>
</tr>
<tr>
<td>RK(B), RK(C)</td>
<td>A field that could be a register or a constant.</td>
</tr>
<tr>
<td>sBx</td>
<td>Signal displacement for all kinds of jumps. It can be a number or a label.</td>
</tr>
<tr>
<td>KPROTO(name)</td>
<td>A function <b>name</b> that will be used to create its closure.</td>
</tr>
</table>
</center>
<p>
Below we show each opcode that is available in our assembly language as well as their respective arguments.
</p>
<a name="op-com"><h3 style="color:#00008B;">MOVE R(A), R(B)</h3></a>
R(A) := R(B)
<p>
Copies the value of register R(B) into register R(A).
</p>
<a name="op-com"><h3 style="color:#00008B;">LOADK R(A), Kst(Bx)</h3></a>
R(A) := Kst(Bx)
<p>
Loads constant Kst(Bx) into register R(A). Constants can be numbers or strings.
</p>
<a name="op-com"><h3 style="color:#00008B;">LOADKX R(A)</h3></a>
R(A) := Kst(extra arg)
<p>
Loads extra arg into register R(A).
The next instruction is always EXTRAARG.
</p>
<a name="op-com"><h3 style="color:#00008B;">LOADBOOL R(A), B, C</h3></a>
R(A) := (Bool)B; if (C) pc++
<p>
Loads a boolean value B (<b>1</b> for <b>TRUE</b> or <b>0</b> for <b>FALSE</b> should be used as B) into register R(A).
If C is not zero then next instruction is skipped.
</p>
<a name="op-com"><h3 style="color:#00008B;">LOADNIL R(A), B</h3></a>
R(A), R(A+1), ..., R(A+B) := nil
<p>
Sets to <b>nil</b> a range of registers from register R(A) up to B.
</p>
<a name="op-com"><h3 style="color:#00008B;">GETUPVAL R(A), UpValue(B)</h3></a>
R(A) := UpValue[B]
<p>
Copies the value in UpValue[B] into register R(A).
</p>
<a name="op-com"><h3 style="color:#00008B;">GETTABUP R(A), UpValue(B), RK(C)</h3></a>
R(A) := UpValue[B][RK(C)]
<p>
Copies the value of field RK(C), from table UpValue[B], into register R(A).
Note that if you are getting globals, then UpValue(B) should be <b>_ENV</b>.
</p>
<a name="op-com"><h3 style="color:#00008B;">GETTABLE R(A), R(B), RK(C)</h3></a>
R(A) := R(B)[RK(C)]
<p>
Copies the value from a table element into register R(A).
The table is referenced by register R(B), while the index to the table is given by
RK(C), which may be register R(C) or a constant Kst(C).
</p>
<a name="op-com"><h3 style="color:#00008B;">SETTABUP UpValue(A), RK(B), RK(C)</h3></a>
UpValue[A][RK(B)] := RK(C)
<p>
Copies the value of RK(C) to the field RK(B) of table UpValue[A].
Note that if you are setting globals, then UpValue(A) should be <b>_ENV</b>.
</p>
<a name="op-com"><h3 style="color:#00008B;">SETUPVAL R(A), UpValue(B)</h3></a>
UpValue[B] := R(A)
<p>
Copies the value from register R(A) into UpValue[B].
</p>
<a name="op-com"><h3 style="color:#00008B;">SETTABLE R(A), RK(B), RK(C)</h3></a>
R(A)[RK(B)] := RK(C)
<p>
Copies the value from register R(C) or constant Kst(C) into a table element.
The table is referenced by register R(A), while the index to the table is given by
RK(B), which may be register R(B) or a constant Kst(B).
</p>
<a name="op-com"><h3 style="color:#00008B;">NEWTABLE R(A), B, C</h3></a>
R(A) := {} (size = B,C)
<p>
Creates a new empty table at register R(A).
Argument B is the size of the array part, while C is the size of the hash part.
</p>
<a name="op-com"><h3 style="color:#00008B;">SELF R(A), R(B), RK(C)</h3></a>
R(A+1) := R(B); R(A) := R(B)[RK(C)]
<p>
It is used for object-oriented programming using tables.
Retrieves a function reference from a table element and places it in register R(A),
then a reference to the table itself is placed in the next register R(A+1).
R(B) is the register holding the reference to the table with the method,
while the method function is found using the table index RK(C), that can be
a register R(C) or a constant Kst(C).
</p>
<a name="op-com"><h3 style="color:#00008B;">ADD R(A), RK(B), RK(C)</h3></a>
R(A) := RK(B) + RK(C)
<p>
Adds RK(B) and RK(C) and holds the result into register R(A).
Both RK(B) and RK(C) may be either registers or constants.
</p>
<a name="op-com"><h3 style="color:#00008B;">SUB R(A), RK(B), RK(C)</h3></a>
R(A) := RK(B) - RK(C)
<p>
Subtracts RK(B) and RK(C) and holds the result into register R(A).
Both RK(B) and RK(C) may be either registers or constants.
</p>
<a name="op-com"><h3 style="color:#00008B;">MUL R(A), RK(B), RK(C)</h3></a>
R(A) := RK(B) * RK(C)
<p>
Multiplies RK(B) and RK(C) and holds the result into register R(A).
Both RK(B) and RK(C) may be either registers or constants.
</p>
<a name="op-com"><h3 style="color:#00008B;">DIV R(A), RK(B), RK(C)</h3></a>
R(A) := RK(B) / RK(C)
<p>
Divides RK(B) and RK(C) and holds the result into register R(A).
Both RK(B) and RK(C) may be either registers or constants.
</p>
<a name="op-com"><h3 style="color:#00008B;">MOD R(A), RK(B), RK(C)</h3></a>
R(A) := RK(B) % RK(C)
<p>
Performs modulus between RK(B) and RK(C) and holds the result into register R(A).
Both RK(B) and RK(C) may be either registers or constants.
</p>
<a name="op-com"><h3 style="color:#00008B;">POW R(A), RK(B), RK(C)</h3></a>
R(A) := RK(B) ^ RK(C)
<p>
Performs exponentiation between RK(B) and RK(C) and holds the result into register R(A).
Both RK(B) and RK(C) may be either registers or constants.
</p>
<a name="op-com"><h3 style="color:#00008B;">UNM R(A), R(B)</h3></a>
R(A) := -R(B)
<p>
Performs unary minus where register R(B) is negated and the value is placed in register R(A).
</p>
<a name="op-com"><h3 style="color:#00008B;">NOT R(A), R(B)</h3></a>
R(A) := not R(B)
<p>
Applies a boolean <b>not</b> to the value in register R(B) and holds the result in register R(A).
</p>
<a name="op-com"><h3 style="color:#00008B;">LEN R(A), R(B)</h3></a>
R(A) := length of R(B)
<p>
Returns the length of object in register R(B) and holds the result in register R(A).
</p>
<a name="op-com"><h3 style="color:#00008B;">CONCAT R(A), R(B), R(C)</h3></a>
R(A) := R(B).. ... ..R(C)
<p>
Performs the concatenation among two or more strings. The start register is R(B) and the
final register is R(C), meaning that R(C) should always be greater then R(B).
The result is stored in register R(A).
</p>
<a name="op-com"><h3 style="color:#00008B;">JMP A, sBx</h3></a>
pc+=sBx; if (A) close all upvalues >= R(A) + 1
<p>
Performs a jump to sBx, which should be an instruction number or a label that should jump to.
If A is <b>true</b> then all upvalues up to R(A) + 1 are closed.
</p>
<a name="op-com"><h3 style="color:#00008B;">EQ A, RK(B), RK(C)</h3></a>
if ((RK(B) == RK(C)) ~= A) then pc++
<p>
Performs a <b>equality</b> test between RK(B) and RK(C), wich may be registers or constants.
If the boolean is not A then next instruction is skipped.
</p>
<a name="op-com"><h3 style="color:#00008B;">LT A, RK(B), RK(C)</h3></a>
if ((RK(B) < RK(C)) ~= A) then pc++
<p>
Performs a <b>less than</b> test between RK(B) and RK(C), wich may be registers or constants.
If the boolean is not A then next instruction is skipped.
</p>
<a name="op-com"><h3 style="color:#00008B;">LE A, RK(B), RK(C)</h3></a>
if ((RK(B) <= RK(C)) ~= A) then pc++
<p>
Performs a <b>less than or equal to</b> test between RK(B) and RK(C), wich may be registers or constants.
If the boolean is not A then next instruction is skipped.
</p>
<a name="op-com"><h3 style="color:#00008B;">TEST R(A), C</h3></a>
if not (R(A) <=> C) then pc++
<p>
Can be used to implement <b>and</b>/<b>or</b> logical operators, or for testing
a single register in a conditional statement.
TEST should be used when an assignment operation is not needed and works same way as TESTSET.
For more details, please, look at TESTSET.
</p>
<a name="op-com"><h3 style="color:#00008B;">TESTSET R(A), R(B), C</h3></a>
if (R(B) <=> C) then R(A) := R(B) else pc++
<p>
Also can be used to implement <b>and</b>/<b>or</b> logical operators, or for testing
a single register in a conditional statement.
Register R(B) is coerced into a boolean and compared to the boolean field C.
If R(B) matches C then next instruction is skipped, otherwise R(B) is assigned to R(A).
</p>
<a name="op-com"><h3 style="color:#00008B;">CALL R(A), B, C</h3></a>
R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
<p>
Performs a function call. R(A) holds the reference to the function object to be called.
Parameters to the function should be placed in the registers following R(A).
<br><br>
If B is 1 the function has no parameters. If B is 2 or more there are B-1 parameters.
If B is 0 the function parameters range from R(A+1) to the top of the stack.
<br><br>
Results returned by the function call are placed in a range of registers starting from R(A).
If C is 1 no return results. If C is 2 or more there will be C-1 results saved.
If C is 0 then multiple return results are saved.
</p>
<a name="op-com"><h3 style="color:#00008B;">TAILCALL R(A), B, C</h3></a>
return R(A)(R(A+1), ... ,R(A+B-1))
<p>
Performs a tail call which happens when a <b>return</b> statement has a single function call as the expression.
Exactly like CALL, register R(A) is the reference to the function object to be called,
while B encodes the number of paramenters. However, even tough C is not used by TAILCALL, 0 should be
used to denote multiple return results.
</p>
<a name="op-com"><h3 style="color:#00008B;">RETURN R(A), B</h3></a>
return R(A), ... ,R(A+B-2)
<p>
Returns to the calling function with options return values.
<br><br>
If B is 1 there are no return values. If B is 2 or more, there are B-1 return values.
If B is 0 the set of values from R(A) to the top of the stack is returned.
</p>
<a name="op-com"><h3 style="color:#00008B;">FORLOOP R(A) sBx</h3></a>
R(A)+=R(A+2) ; if R(A) <&#63= R(A+1) then pc+=sBx; R(A+3)=R(A)
<p>
Should be used to perform an iteration of a numeric <b>for</b> loop.
A numeric for loop requires 4 registers on the stack where R(A) hold the initial value,
R(A+1) is the limit, R(A+2) is the stepping value and R(A+3) is the actual loop variable
that is local to the <b>for</b> block.
The argument sBx should be an instruction number or a label that should jump unconditionally to.
</p>
<a name="op-com"><h3 style="color:#00008B;">FORPREP R(A), sBx</h3></a>
R(A)-=R(A+2); pc+=sBx
<p>
Should be used to initialize a numeric <b>for</b> loop.
The argument sBx should be an instruction number or a label that should jump back to the loop body.
</p>
<a name="op-com"><h3 style="color:#00008B;">TFORCALL R(A), C</h3></a>
R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2))
<p>
Should be used to initialize a generic <b>for</b> loop, where
R(A) is the iterator function, R(A+1) is the state and R(A+2) is the enumeration index.
The loop variables are specified at locations R(A+3) and their count is defined by operand C,
which should be at least 1.
</p>
<a name="op-com"><h3 style="color:#00008B;">TFORLOOP R(A), sBx</h3></a>
if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }
<p>
Should be used to perform an iteration of a generic <b>for</b> loop.
If register R(A+1) is not nil then it is stored in R(A) and jump back to sBx.
The argument sBx should be an instruction number or a label that should jump to.
</p>
<a name="op-com"><h3 style="color:#00008B;">SETLIST R(A), B, C</h3></a>
R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
<p>
Sets the values for a range of arrays elements in a table referenced by R(A),
argument B is the number of elements to set and argument C is the number of blocks
to be initialized.
If B is zero then B is the top. If C is zero then next instruction should be
EXTRAARG(real C).
</p>
<a name="op-com"><h3 style="color:#00008B;">CLOSURE R(A), KPROTO(Bx)</h3></a>
R(A) := closure(KPROTO[Bx])
<p>
Should be used to create an instance of a closure of a function where KPROTO[Bx] is the
function name and R(A) is the register that assigns the reference to the instantiated
function object.
</p>
<a name="op-com"><h3 style="color:#00008B;">VARARG R(A), B</h3></a>
R(A), R(A+1), ..., R(A+B-2) = vararg
<p>
Copies B-2 parameters into a number of registers starting from R(A).
If B is 0, VARARG copies as many values as it can based on the number of parameters passed.
If a fixed number of values is required, B is a value greater than 1.
If any number of values is required then B is 0.
</p>
<a name="op-com"><h3 style="color:#00008B;">EXTRAARG Ax</h3></a>
<p>
Sets an extra larger argument for previous opcode.
If previous opcode is <b>LOADKX</b> then Ax might be any constant, but
if previous opcode is <b>SETLIST</b> then Ax must be an integer.
</p>
<hr />
<h3><a name="notes">Notes</a></h3>
<p>
The current version of <code>Lua Assembler/Disassembler</code> is 0.2.
</p>
<hr />
<h3><a name="licence">Licence</a></h3>
<p>
Copyright &copy; 2012 Andre Murbach Maidl.
</p>
<p>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
</p>
<p>
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
</p>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</p>
</div>
<div id="footer">
<center>
<small>Last modified by Andre Murbach Maidl</small>
</center>
</div>
</div>
</body>
</html>