1
0
Fork 0
mirror of https://github.com/notwa/lips synced 2024-05-15 14:43:23 -07:00

add something resembling documentation

This commit is contained in:
Connor Olding 2016-01-18 12:56:06 -08:00
parent e7fe9d972c
commit 9e4167e04a
3 changed files with 198 additions and 3 deletions

View File

@ -9,14 +9,106 @@ It does little more than output hex.
Not for production. Much of the code and syntax is untested and likely to change. Not for production. Much of the code and syntax is untested and likely to change.
Even this README is incomplete. Even this README is incomplete.
## Usage
Copy the lips directory to somewhere Lua's `package.path` can find it.
If you're using it locally, you will need to write something like:
```
package.path = package.path..";./?/init.lua"
```
You can then use it as such:
[example.lua][elua] — [example.asm][easm]
[elua]: ./example.lua
[easm]: ./example.asm
By default, lips will print the assembled word values in hex:
```
18800017
00001025
2401002F
10810002
0081082A
10200012
2488FFFF
00084080
etc...
```
Since lips is designed to assist with ROM/RAM hacking,
it cannot produce executable files on its own.
Instead, it is meant to be integrated with an existing executable or memory dump.
For instance, consider [this injection routine][inject.lua]
written for the Nintendo 64 Zelda games.
[inject.lua]: https://github.com/notwa/mm/blob/master/Lua/inject.lua
## Syntax ## Syntax
(TODO) lips uses a derivative of [CajeASM's][caje] syntax.
It takes a couple notes from more traditional assemblers as well.
A derivative of [CajeASM's][caje] syntax.
[caje]: https://github.com/Tarek701/CajeASM/ [caje]: https://github.com/Tarek701/CajeASM/
A run-down of various syntax elements:
```
// this is a comment
/* this is a block comment */
// this is comparible to C's #define my_const 0xDEADBEEF
[my_const]: 0xDEADBEEF
// we can then use it in instructions with a @ prefix
li a0, @my_const
// whitespace is optional
li a0,@myconst
// commas can be optional too,
// but this feature will likely be removed in the future.
li a0 @myconst
// instruction/register names are case-insensitive, as are hex digits
LI A0, @my_const
LuI a0, 0xDeAd
// coprocessor 0 registers are case-insensitive as well,
// though this may change in the future.
mfc0 a1, CouNT
// labels are defined with a colon and referenced without prefix, as such:
my_label:
b my_label
nop
// directives are prefixed with a dot.
// also, labels may be used in .word directives.
.word my_label, 1, 2, 3, 0x4567
// octal numbers are supported
.short 0177, 0404
.align // implied argument of 2, for a 2**n=4 byte alignment
// loading and storing can be written in several ways (addressing modes)
lw s0, label
lw s1, (s0)
lw s2, 256(s0)
lw s3, label(s0)
// this is currently unsupported however
sw s2, label+4
sw s3, label+4(s0)
// relative labels, borrowed from asw (except ours require a suffixing colon)
-:
b ++
nop
+:
-:
b --
nop
+:
b -
nop
// TODO: more examples!
```
## Instructions ## Instructions
Instructions were primarily referenced from [the N64 Toolkit: Opcodes.][n64op] Instructions were primarily referenced from [the N64 Toolkit: Opcodes.][n64op]

100
example.asm Normal file
View File

@ -0,0 +1,100 @@
/* lips example code: fibonacci numbers
* this isn't a particularily useful or realistic example,
* but it demonstrates syntax and various features in lips.
*/
[max_n]: 47
fib:
// calculate the nth fibonacci number, caching results 1 to 47 to a table
// only valid for values of n between 0 and 47 inclusive.
// a0: n
// v0: Fn
// branch to return 0 if a0 <= 0.
// the + refers to the next + label, relative to here.
// ++ would refer to the + label after that, and so on.
blez a0, +
// note that this executes even if the branch is taken,
// due to the single delay slot of this MIPS CPU.
// pseudo-instruction clears (sets to 0) the 32-bit value of a register:
cl v0
// check if the input is within the bounds specified earlier.
// pseudo-instruction to branch if register > immediate:
bgti a0, @max_n, +
// offset the input for use with the look-up table.
// note that this executes even if the branch is taken,
// but won't break the functionality of the routine either way.
// pseudo-instruction translates into an addiu with a negated immediate:
subiu t0, a0, 1
// multiply by sizeof(word) which is 4, or 1 << 2.
sll t0, t0, 2
// load the value from the look-up table.
// pseudo-instruction utilizing addressing modes:
lw t9, fib_cache(t0)
// branch to return the look-up value if it's non-zero, meaning it has been cached.
bnez t9, +
// once again, note that this is the delay slot of the branch instruction.
// pseudo-instruction to copy the 32-bit value of one register to another:
mov v0, t9
// set up the following loop to calculate the fibonacci number.
// pseudo-instruction to load a 32-bit value into a register:
li t1, 0 // F(0)
li t2, 1 // F(1)
-: // here's a - label referred to later.
// - labels are like + labels, except
// they look upwards in the file instead of downwards.
// calculate the next fibonacci number.
addu t3, t1, t2
// push the previous values back, part 1.
mov t1, t2
// iterate to the next number.
subiu a0, a0, 1
// loop if it hasn't yet reached the nth fibonacci number.
bnez a0, -
// push the previous values back, part 2.
// this is put in the branch delay as a simple optimization.
mov t2, t3
// loop finished, copy the result to return.
mov v0, t1
// cache the result for next time.
// pseudo-instruction not unlike the previous lw:
sw v0, fib_cache(t0)
// here's the + label used at the start of the routine.
+:
// return to the function that called this routine.
// when jr is given without any arguments, `jr ra` is implied.
jr
// there's nothing to do in the delay slot, so don't do anything.
// this is necessary, otherwise the next instruction or data
// following the routine would be executed.
// pseudo-instruction to do nothing:
nop
// set up initial values in the look-up table.
fib_cache:
// lips doesn't yet have a way to specify "x, n times",
// so this will do for now.
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0

3
example.lua Normal file
View File

@ -0,0 +1,3 @@
package.path = package.path..";./?/init.lua"
local lips = require "lips"
lips('example.asm')