6a4aaf8eac
FossilOrigin-Name: 25cf19660ab7728d7bfee2722ea826a8a438faf92b2504b28d922d2958906aed
165 lines
8.3 KiB
HTML
165 lines
8.3 KiB
HTML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml"><head>
|
|
<title>.</title>
|
|
<style type="text/css">
|
|
|
|
* { color: #000; background: #fff; max-width: 700px; }
|
|
tt, pre { background: #dedede; color: #111; font-family: monospace;
|
|
white-space: pre; display: block; width: 100%; }
|
|
.indentedcode { margin-left: 2em; margin-right: 2em; }
|
|
.codeblock {
|
|
background: #dedede; color: #111; font-family: monospace;
|
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
|
padding: 7px;
|
|
display: block;
|
|
}
|
|
|
|
.indentedlist { margin-left: 2em; color: #000; }
|
|
|
|
span { white-space: pre; }
|
|
.text { color: #000; white-space: pre; background: #dedede; }
|
|
.colon { color: #000; background: #dedede; }
|
|
.note { color: #000; background: #dedede; }
|
|
.str { color: #000; text-decoration: underline; background: #dedede; }
|
|
.num { color: #000; background: #dedede; font-weight: bold; font-style: italic; }
|
|
.fnum { color: #000; font-weight: bold; background: #dedede; }
|
|
.ptr { color: #000; font-weight: bold; background: #dedede; }
|
|
.fetch { color: #000; font-style: italic; background: #dedede; }
|
|
.store { color: #000; font-style: italic; background: #dedede; }
|
|
.char { color: #000; background: #dedede; }
|
|
.inst { color: #000; background: #dedede; }
|
|
.defer { color: #000; background: #dedede; }
|
|
.imm { color: #000; font-weight: bold; background: #dedede; }
|
|
.prim { color: #000; font-weight: bolder; background: #dedede; }
|
|
|
|
.tt { white-space: pre; font-family: monospace; background: #dedede; }
|
|
|
|
.h1, .h2, .h3, .h4 { white-space: normal; }
|
|
.h1 { font-size: 125%; }
|
|
.h2 { font-size: 120%; }
|
|
.h3 { font-size: 115%; }
|
|
.h4 { font-size: 110%; }
|
|
.hr { display: block; height: 2px; background: #000000; }
|
|
</style>
|
|
</head><body>
|
|
<p><span class="h1">Working With Assembly Language</span>
|
|
<br/><br/>
|
|
RETRO runs on a virtual machine called Nga. It provides a
|
|
standard assembler for this called <strong>Muri</strong>.
|
|
<br/><br/>
|
|
Muri is a simple, multipass model that's not fancy, but
|
|
suffices for RETRO's needs.
|
|
<br/><br/>
|
|
<span class="h2">Assembling A Standalone File</span>
|
|
<br/><br/>
|
|
A small example (<strong>test.muri</strong>)
|
|
<br/><br/>
|
|
<tt class='indentedcode'>~~~</tt>
|
|
<tt class='indentedcode'>i liju....</tt>
|
|
<tt class='indentedcode'>r main</tt>
|
|
<tt class='indentedcode'>: c:put</tt>
|
|
<tt class='indentedcode'>i liiire..</tt>
|
|
<tt class='indentedcode'>i 0</tt>
|
|
<tt class='indentedcode'>: main</tt>
|
|
<tt class='indentedcode'>i lilica..</tt>
|
|
<tt class='indentedcode'>d 97</tt>
|
|
<tt class='indentedcode'>i liju....</tt>
|
|
<tt class='indentedcode'>r main</tt>
|
|
<tt class='indentedcode'>~~~</tt>
|
|
<br/><br/>
|
|
Assembling it:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>retro-muri test.muri</tt>
|
|
<br/><br/>
|
|
So breaking down: Muri extracts the assembly code blocks to
|
|
assemble, then proceeds to do the assembly. Each source line
|
|
starts with a directive, followed by a space, and then ending
|
|
with a value.
|
|
<br/><br/>
|
|
The directives are:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>: value is a label</tt>
|
|
<tt class='indentedcode'>i value is an instruction bundle</tt>
|
|
<tt class='indentedcode'>d value is a numeric value</tt>
|
|
<tt class='indentedcode'>r value is a reference</tt>
|
|
<tt class='indentedcode'>s value is a string to inline</tt>
|
|
<br/><br/>
|
|
Instructions for Nga are provided as bundles. Each memory
|
|
location can store up to four instructions. And each instruction
|
|
gets a two character identifier.
|
|
<br/><br/>
|
|
From the list of instructions:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>0 nop 5 push 10 ret 15 fetch 20 div 25 zret</tt>
|
|
<tt class='indentedcode'>1 lit 6 pop 11 eq 16 store 21 and 26 halt</tt>
|
|
<tt class='indentedcode'>2 dup 7 jump 12 neq 17 add 22 or 27 ienum</tt>
|
|
<tt class='indentedcode'>3 drop 8 call 13 lt 18 sub 23 xor 28 iquery</tt>
|
|
<tt class='indentedcode'>4 swap 9 ccall 14 gt 19 mul 24 shift 29 iinvoke</tt>
|
|
<br/><br/>
|
|
This reduces to:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>0 .. 5 pu 10 re 15 fe 20 di 25 zr</tt>
|
|
<tt class='indentedcode'>1 li 6 po 11 eq 16 st 21 an 26 ha</tt>
|
|
<tt class='indentedcode'>2 du 7 ju 12 ne 17 ad 22 or 27 ie</tt>
|
|
<tt class='indentedcode'>3 dr 8 ca 13 lt 18 su 23 xo 28 iq</tt>
|
|
<tt class='indentedcode'>4 sw 9 cc 14 gt 19 mu 24 sh 29 ii</tt>
|
|
<br/><br/>
|
|
Most are just the first two letters of the instruction name. I
|
|
use <span class="tt">..</span> instead of <span class="tt">no</span> for <span class="tt">NOP</span>, and the first letter of
|
|
each I/O instruction name. So a bundle may look like:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>dumure..</tt>
|
|
<br/><br/>
|
|
(This would correspond to <span class="tt">dup multiply return nop</span>).
|
|
<br/><br/>
|
|
<span class="h2">Runtime Assembler</span>
|
|
<br/><br/>
|
|
RETRO also has a runtime variation of Muri that can be used
|
|
when you need to generate more optimal code. So one can write:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>:n:square dup * ;</tt>
|
|
<br/><br/>
|
|
Or:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>:n:square \dumure.. ;</tt>
|
|
<br/><br/>
|
|
The second one will be faster, as the entire definition is one
|
|
bundle, which reduces memory reads and decoding by 2/3.
|
|
<br/><br/>
|
|
Doing this is less readable, so I only recommend doing so after
|
|
you have finalized working RETRO level code and determined the
|
|
best places to optimize.
|
|
<br/><br/>
|
|
The runtime assembler has the following directives:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>i value is an instruction bundle</tt>
|
|
<tt class='indentedcode'>d value is a numeric value</tt>
|
|
<tt class='indentedcode'>r value is a reference</tt>
|
|
<br/><br/>
|
|
Additionally, in the runtime assembler, these are reversed:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>'dudumu.. i</tt>
|
|
<br/><br/>
|
|
Instead of:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>i dudumu..</tt>
|
|
<br/><br/>
|
|
The runtime assembler also provides three sigils for use in
|
|
inlining machine code into a definition. These are:
|
|
<br/><br/>
|
|
<tt class='indentedcode'> \ Treat token as an assembly sequence</tt>
|
|
<tt class='indentedcode'> ` Treat token as a numeric value</tt>
|
|
<tt class='indentedcode'> ^ Treat token as a reference</tt>
|
|
<br/><br/>
|
|
E.g., instead of doing something like:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>:n:square as{ 'dumu.... i }as ;</tt>
|
|
<tt class='indentedcode'>:test as{ 'lilica.... i #22 d 'n:square r }as ;</tt>
|
|
<br/><br/>
|
|
Just write:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>:n:square \dumu.... ;</tt>
|
|
<tt class='indentedcode'>:test \lilica.. `22 ^n:square ; </tt>
|
|
</p>
|
|
</body></html>
|