forked from GitHub/lad
870 lines
29 KiB
HTML
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) <?= 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 © 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>
|