From d69455287d0f1d2843e2eae44d33025344ea6b97 Mon Sep 17 00:00:00 2001 From: Snorre Selmer Date: Tue, 10 Jan 2023 13:20:22 +0100 Subject: [PATCH 1/5] Add files via upload --- mips-programming-101.md | 197 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 mips-programming-101.md diff --git a/mips-programming-101.md b/mips-programming-101.md new file mode 100644 index 0000000..8676ee3 --- /dev/null +++ b/mips-programming-101.md @@ -0,0 +1,197 @@ +# MIPS Programming 101 + +# Introduction + +MIPS is a pretty basic assembler programming language. + +In Stationeers you have the following available to you: + +-
Six connectors (d0 through d5) on IC Housings, or two (d0 and d1) on selected devices, plus a connector for the chip-socket (db)
+-
Sixteen registers (r0 through r15)
+-
A special address register (ra)
+-
A stack (sp) that you can push 512 values into, and pop values out of. The stack is last-in-first-out.
+-
A maximum of 128 lines of code, each line has a maximum of 57 characters
+ +The address register (ra) is not meant to be written to by the user, it's only used for branching to code that needs to be accessed from multiple areas in your code (functions). + +
+ +# Registers? What are they and how do I use them? + +Registers are what most programming languages call variables. But where most programming languages let you create as many variables as you want, MIPS has 18 registers, but only 16 of them are intended for regular use. + +
**Register(s)****Alias****Purpose**
r0-r15(None)User register
r16raReturn address
r17spStack pointer
+ +## So what do you use a register for? + +Registers are for storing temporary data. They can be overwritten any time you want. + +Think of a register as a shoe-box. You write something on a piece of paper and store it in the box, you can open the box and look at what's written on the note, and you can write a new note and put it in there, but then you have to take out the old note. The shoe-box can only ever hold one note. + +In game-terms, registers are where you store things like pressure from a Gas Sensor, the horizontal angle of the Sun, etc. + +## How do you use them? + +If you want to read the pressure from a Gas Sensor, you'd use the following bit of code: + +``` +l r0 GasSensor Pressure +``` + +This ***l***oads ***Pressure*** from ***GasSensor***, and stores it into ***r0***. + +# Load? Set? What? + +In MIPS, two of the functions you'll use the most are ***l*** and ***s***. ***s*** also has a lot of logical comparators you can use to do boolean operations on the input. + +In short, ***l*** loads data from devices to registers, ***s*** sets (or saves) data from registers to registers or devices. + +## Examples + +### Loading + +``` +l r0 GasSensor Pressure +``` + +This ***l***oads ***Pressure ***from ***GasSensor ***into ***r0***. + +### Setting + +``` +s CeilingLight On r0 +``` + +This ***s***ets ***CeilingLight***'s ***On*** end-point to the value stored in ***r0***. + +This may sound a bit cryptic, but bear with me, I'll explain it all a bit further down. + +### Setting with boolean comparisons + +Boolean comparisons are comparisons made to be either true (1) or false (0). These are great at controlling the on/off state of devices like pumps and lights etc. + +Boolean comparisons are of the type "equal", "equal to zero", "less/great than", "less/greater than zero" and so on. + +If you use one of the operators that compare to zero, you do not need to supply two values for comparison, since the instruction already says one of the values will be zero. + +``` +sgt r2 CurrentPressure MaxPressure +``` + +This ***s***ets a 1 (true) in ***r2*** if ***CurrentPressure ***is ***g***reater ***t***han ***MaxPressure***, or a 0 (false) in r2 if it's not. + +``` +sgtz r2 CurrentTemperature +``` + +This ***s***ets a 1 (true) in ***r2*** if ***CurrentTemperature ***is ***g***reater ***t***han ***z***ero, or a 0 (false) in r2 if it's not. + +## Data end-points, and what can be loaded/set? + +When you want to automate something, the Stationpedia is your best friend! It contains a catalogue of all the things you can make, and lists all the data you can *load from* and/or *set to* it. Here's an example: + +[![2022-10-21 20_40_00-Stationeers v0.2.3657.17736.png](https://bookstack.snorreselmer.net/uploads/images/gallery/2022-10/scaled-1680-/2022-10-21-20-40-00-stationeers-v0-2-3657-17736.png)](https://bookstack.snorreselmer.net/uploads/images/gallery/2022-10/2022-10-21-20-40-00-stationeers-v0-2-3657-17736.png) + +The section we're interested in here is the ***Logic*** section. As you saw in the Setting-example above, I set the ***On ***end-point to the value stored in a register. As we can see in the picture above, ***On ***can be read (***l***oaded) or written (***s***et). ***On*** can take a 1 to turn on, or a 0 to turn off. + +Not all end-points can be written to, this makes sense when you think about it. + +- You can read ***On*** to see if the light is turned on or not, or you can write to ***On*** to turn it on or off. +- A light will always use the power it *needs* to work, so you can read ***Power*** to see how much it consumes, but you can't set the power it uses. + +Aha! But setting Power could be like making a dimmer for the light, right? That would have been nice, but that would more likely be done with an end-point called ***Setting***, which this variant of light doesn't have. To my knowledge, there are no dimmable lights in Stationeers (yet). + +# Making code more readable! + +> **Code is read much more often than it is written.** +> +> *- Guido Van Rossum (the guy that created the Python programming language)* + +While the MIPS implementation in Stationeers has some limitations (128 lines, with a maximum of 57 characters per line), I've rarely run into problems like running out of room. This is mostly because I try not to write "multi-mega-scripts" that do a ton of things. I'm a fan of the UNIX mantra of "do one thing, and do it well". This also means that I use ***aliases*** and ***defines*** a lot. They take more space than just writing things straight up, but they also make the code much easier to read! + +Compare these two lines of code: + +``` +slt r2 r0 r1 +``` + +and + +``` +slt HeaterOn CurrentTemperature MinimumTemperature +``` + +They could do the exact same thing, but the bottom one actually explains what's going on. And it's still shorter that 57 characters. + +If you're juggling 10+ registers in your code without naming them, the chances of getting them mixed up increases greatly. And if you do make a mistake somewhere, trying to follow the code can be more complicated than if you used named variables. + +This is not to say that you *have* to name variables. It's up to you. + +## Alias + +Making an ***alias*** is the act of giving a register or a device a more human-readable name. For devices, this has the added benefit of naming the pins on the IC housing, making it easier to remember what devices goes on what pin when you set up the housing. + +``` +alias Furnace d0 +alias FurnaceTemperature r0 +``` + +This gives the device on pin ***d0*** the ***alias*** (name) ***Furnace***, and the register ***r0*** the ***alias*** (name) ***FurnaceTemperature***. In the code you can now refer to Furnace instead of d0, and FurnaceTemperature instead of r0. Like this: + +``` +l FurnaceTemperature Furnace Temperature +``` + +This loads the ***Temperature*** in the ***Furnace (d0)*** into ***FurnaceTemperature*** **(r0)**. + +## Define + +A define is what we in other programming languages would call a constant. As the name implies, a constant is ... constant. It never changes. This is great for threshold-values and item-hashes (a unique number given to each type of item in the game, used for comparing items in sorting, and for reading from or writing to a lot of identical items, called batch-reading/-writing). + +``` +define MinimumTemperature 20 +define KelvinConvert 273.15 +``` + +This ***define***s ***MinimumTemperature ***as ***20*** (maybe for use as 20 Celsius in a temperature control circuit), and ***define***s ***KelvinConvert ***(the conversion-number from Kelvin to Celsius) as ***273.15***. + +# Branch/set matrix + +There is logic for relative jumping in code. I have yet to find a use for it that can't be done better with any of the other functions, so I won't cover it here. + +
SuffixPrefix
+ +b-b-als-
DescriptionBranch to lineBranch to line and store return addressSet register
<none>unconditionaljjals
-eqif a == bbeqbeqalseq
-eqzif a == 0beqzbeqzalseqz
-geif a >= bbgebgealsge
-gezif a >= 0bgezbgezalsgez
-gtif a > bbgtbgtalsgt
-gtzif a > 0bgtzbgtzalsgtz
-leif a ⇐ bbleblealsle
-lezif a ⇐ 0blezblezalslez
-ltif a < bbltbltalslt
-ltzif a < 0bltzbltzalsltz
-neif a != bbnebnealsne
-nezif a != 0bnezbnezalsnez
-dnsif d? is not setbdnsbdnsalsdns
-dseif d? is setbdsebdsealsdse
-apif a ~ bbapbapalsap
-apzif a ~ 0bapzbapzalsapz
-naif a !~ bbnabnaalsna
-nazif a !~ 0bnazbnazalsnaz
+ +
+ +# Indirect referencing + +Indirect referencing is when you use the value in one register to determine what other register or device to interact with. + +It looks like this: + +``` +move r0 2 +l r1 dr0 Setting +``` + +The indirect referencing is the `dr0` part. You can read it as `d(r0)`, which means it reads from device `d2` since `r0` is `2`. + +If you want, you can reference multiple times in the same reference, but that gets unreadable *fast!* + +``` +move r0 7 +move r1 2 +move r2 0 +l r15 drrr1 Setting +``` + +So what device are we addressing here? Let's break it down: + +- `drrr1` can be read as `d(r(r(r1)))` +- `r1` is `2`, so now we have `d(r(r2))` +- `r2` is `0`, so now we have `d(r0)` +- `r0` is `7`, so now we have `d7` + +Since the maximum number of devices an IC Housing can connect is 6 (d0-5), this would break the script. This is why multi-level referencing should be used extremely sparingly. \ No newline at end of file From 61cde1e42f4b515da1636d27054fb3a3676edaa9 Mon Sep 17 00:00:00 2001 From: Snorre Selmer Date: Wed, 11 Jan 2023 09:50:30 +0100 Subject: [PATCH 2/5] Cleaned up HTML-tags added by Bookstack export --- mips-programming-101.md | 97 ++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 54 deletions(-) diff --git a/mips-programming-101.md b/mips-programming-101.md index 8676ee3..ca2473a 100644 --- a/mips-programming-101.md +++ b/mips-programming-101.md @@ -1,28 +1,30 @@ # MIPS Programming 101 -# Introduction +## Introduction MIPS is a pretty basic assembler programming language. In Stationeers you have the following available to you: --
Six connectors (d0 through d5) on IC Housings, or two (d0 and d1) on selected devices, plus a connector for the chip-socket (db)
--
Sixteen registers (r0 through r15)
--
A special address register (ra)
--
A stack (sp) that you can push 512 values into, and pop values out of. The stack is last-in-first-out.
--
A maximum of 128 lines of code, each line has a maximum of 57 characters
+- Six connectors (d0 through d5) on IC Housings, or two (d0 and d1) on selected devices, plus a connector for the chip-socket (db) +- Sixteen registers (r0 through r15) +- A special address register (ra) +- A stack (sp) that you can push 512 values into, and pop values out of. The stack is last-in-first-out. +- A maximum of 128 lines of code, each line has a maximum of 57 characters The address register (ra) is not meant to be written to by the user, it's only used for branching to code that needs to be accessed from multiple areas in your code (functions). -
- -# Registers? What are they and how do I use them? +## Registers? What are they and how do I use them? Registers are what most programming languages call variables. But where most programming languages let you create as many variables as you want, MIPS has 18 registers, but only 16 of them are intended for regular use. -
**Register(s)****Alias****Purpose**
r0-r15(None)User register
r16raReturn address
r17spStack pointer
+| **Register(s)** | **Alias** | **Purpose** | +|-----------------|-----------|----------------| +| r0-r15 | (None) | User register | +| r16 | ra | Return address | +| r17 | sp | Stack pointer | -## So what do you use a register for? +### So what do you use a register for? Registers are for storing temporary data. They can be overwritten any time you want. @@ -30,7 +32,7 @@ Think of a register as a shoe-box. You write something on a piece of paper and s In game-terms, registers are where you store things like pressure from a Gas Sensor, the horizontal angle of the Sun, etc. -## How do you use them? +### How do you use them? If you want to read the pressure from a Gas Sensor, you'd use the following bit of code: @@ -38,36 +40,31 @@ If you want to read the pressure from a Gas Sensor, you'd use the following bit l r0 GasSensor Pressure ``` -This ***l***oads ***Pressure*** from ***GasSensor***, and stores it into ***r0***. +This ***l***oads ***Pressure*** from ***GasSensor***, and stores it into ***r0***. -# Load? Set? What? +## Load? Set? What? -In MIPS, two of the functions you'll use the most are ***l*** and ***s***. ***s*** also has a lot of logical comparators you can use to do boolean operations on the input. +In MIPS, two of the functions you'll use the most are ***l*** and ***s***. ***s*** also has a lot of logical comparators you can use to do boolean operations on the input. -In short, ***l*** loads data from devices to registers, ***s*** sets (or saves) data from registers to registers or devices. +In short, ***l*** loads data from devices to registers, ***s*** sets (or saves) data from registers to registers or devices. -## Examples - -### Loading +### Examples +#### Loading ``` l r0 GasSensor Pressure ``` +This ***l***oads ***Pressure*** from ***GasSensor*** into ***r0***. -This ***l***oads ***Pressure ***from ***GasSensor ***into ***r0***. - -### Setting - +#### Setting ``` s CeilingLight On r0 ``` - -This ***s***ets ***CeilingLight***'s ***On*** end-point to the value stored in ***r0***. +This ***s***ets ***CeilingLight***'s ***On*** end-point to the value stored in ***r0***. This may sound a bit cryptic, but bear with me, I'll explain it all a bit further down. -### Setting with boolean comparisons - +#### Setting with boolean comparisons Boolean comparisons are comparisons made to be either true (1) or false (0). These are great at controlling the on/off state of devices like pumps and lights etc. Boolean comparisons are of the type "equal", "equal to zero", "less/great than", "less/greater than zero" and so on. @@ -77,46 +74,40 @@ If you use one of the operators that compare to zero, you do not need to supply ``` sgt r2 CurrentPressure MaxPressure ``` - -This ***s***ets a 1 (true) in ***r2*** if ***CurrentPressure ***is ***g***reater ***t***han ***MaxPressure***, or a 0 (false) in r2 if it's not. +This ***s***ets a 1 (true) in ***r2*** if ***CurrentPressure*** is ***g***reater ***t***han ***MaxPressure***, or a 0 (false) in r2 if it's not. ``` sgtz r2 CurrentTemperature ``` +This ***s***ets a 1 (true) in ***r2*** if ***CurrentTemperature*** is ***g***reater ***t***han ***z***ero, or a 0 (false) in r2 if it's not. -This ***s***ets a 1 (true) in ***r2*** if ***CurrentTemperature ***is ***g***reater ***t***han ***z***ero, or a 0 (false) in r2 if it's not. - -## Data end-points, and what can be loaded/set? - +### Data end-points, and what can be loaded/set? When you want to automate something, the Stationpedia is your best friend! It contains a catalogue of all the things you can make, and lists all the data you can *load from* and/or *set to* it. Here's an example: -[![2022-10-21 20_40_00-Stationeers v0.2.3657.17736.png](https://bookstack.snorreselmer.net/uploads/images/gallery/2022-10/scaled-1680-/2022-10-21-20-40-00-stationeers-v0-2-3657-17736.png)](https://bookstack.snorreselmer.net/uploads/images/gallery/2022-10/2022-10-21-20-40-00-stationeers-v0-2-3657-17736.png) +***TODO: ADD IMAGE*** -The section we're interested in here is the ***Logic*** section. As you saw in the Setting-example above, I set the ***On ***end-point to the value stored in a register. As we can see in the picture above, ***On ***can be read (***l***oaded) or written (***s***et). ***On*** can take a 1 to turn on, or a 0 to turn off. +The section we're interested in here is the ***Logic*** section. As you saw in the Setting-example above, I set the ***On*** end-point to the value stored in a register. As we can see in the picture above, ***On*** can be read (***l***oaded) or written (***s***et). ***On*** can take a 1 to turn on, or a 0 to turn off. Not all end-points can be written to, this makes sense when you think about it. -- You can read ***On*** to see if the light is turned on or not, or you can write to ***On*** to turn it on or off. -- A light will always use the power it *needs* to work, so you can read ***Power*** to see how much it consumes, but you can't set the power it uses. +- You can read ***On*** to see if the light is turned on or not, or you can write to ***On*** to turn it on or off. +- A light will always use the power it *needs* to work, so you can read ***Power*** to see how much it consumes, but you can't set the power it uses. -Aha! But setting Power could be like making a dimmer for the light, right? That would have been nice, but that would more likely be done with an end-point called ***Setting***, which this variant of light doesn't have. To my knowledge, there are no dimmable lights in Stationeers (yet). +Aha! But setting Power could be like making a dimmer for the light, right? That would have been nice, but that would more likely be done with an end-point called ***Setting***, which this variant of light doesn't have. To my knowledge, there are no dimmable lights in Stationeers (yet). -# Making code more readable! +## Making code more readable! > **Code is read much more often than it is written.** > > *- Guido Van Rossum (the guy that created the Python programming language)* -While the MIPS implementation in Stationeers has some limitations (128 lines, with a maximum of 57 characters per line), I've rarely run into problems like running out of room. This is mostly because I try not to write "multi-mega-scripts" that do a ton of things. I'm a fan of the UNIX mantra of "do one thing, and do it well". This also means that I use ***aliases*** and ***defines*** a lot. They take more space than just writing things straight up, but they also make the code much easier to read! +While the MIPS implementation in Stationeers has some limitations (128 lines, with a maximum of 57 characters per line), I've rarely run into problems like running out of room. This is mostly because I try not to write "multi-mega-scripts" that do a ton of things. I'm a fan of the UNIX mantra of "do one thing, and do it well". This also means that I use ***aliases*** and ***defines*** a lot. They take more space than just writing things straight up, but they also make the code much easier to read! Compare these two lines of code: - ``` slt r2 r0 r1 ``` - and - ``` slt HeaterOn CurrentTemperature MinimumTemperature ``` @@ -127,25 +118,24 @@ If you're juggling 10+ registers in your code without naming them, the chances o This is not to say that you *have* to name variables. It's up to you. -## Alias +### Alias -Making an ***alias*** is the act of giving a register or a device a more human-readable name. For devices, this has the added benefit of naming the pins on the IC housing, making it easier to remember what devices goes on what pin when you set up the housing. +Making an ***alias*** is the act of giving a register or a device a more human-readable name. For devices, this has the added benefit of naming the pins on the IC housing, making it easier to remember what devices goes on what pin when you set up the housing. ``` alias Furnace d0 alias FurnaceTemperature r0 ``` -This gives the device on pin ***d0*** the ***alias*** (name) ***Furnace***, and the register ***r0*** the ***alias*** (name) ***FurnaceTemperature***. In the code you can now refer to Furnace instead of d0, and FurnaceTemperature instead of r0. Like this: +This gives the device on pin ***d0*** the ***alias*** (name) ***Furnace***, and the register ***r0*** the ***alias*** (name) ***FurnaceTemperature***. In the code you can now refer to Furnace instead of d0, and FurnaceTemperature instead of r0. Like this: ``` l FurnaceTemperature Furnace Temperature ``` -This loads the ***Temperature*** in the ***Furnace (d0)*** into ***FurnaceTemperature*** **(r0)**. - -## Define +This loads the ***Temperature*** in the ***Furnace (d0)*** into ***FurnaceTemperature (r0)***. +### Define A define is what we in other programming languages would call a constant. As the name implies, a constant is ... constant. It never changes. This is great for threshold-values and item-hashes (a unique number given to each type of item in the game, used for comparing items in sorting, and for reading from or writing to a lot of identical items, called batch-reading/-writing). ``` @@ -153,9 +143,9 @@ define MinimumTemperature 20 define KelvinConvert 273.15 ``` -This ***define***s ***MinimumTemperature ***as ***20*** (maybe for use as 20 Celsius in a temperature control circuit), and ***define***s ***KelvinConvert ***(the conversion-number from Kelvin to Celsius) as ***273.15***. +This ***define***s ***MinimumTemperature*** as ***20*** (maybe for use as 20 Celsius in a temperature control circuit), and ***define***s ***KelvinConvert*** (the conversion-number from Kelvin to Celsius) as ***273.15***. -# Branch/set matrix +## Branch/set matrix There is logic for relative jumping in code. I have yet to find a use for it that can't be done better with any of the other functions, so I won't cover it here. @@ -165,12 +155,11 @@ There is logic for relative jumping in code. I have yet to find a use for it tha -# Indirect referencing +## Indirect referencing Indirect referencing is when you use the value in one register to determine what other register or device to interact with. It looks like this: - ``` move r0 2 l r1 dr0 Setting @@ -194,4 +183,4 @@ So what device are we addressing here? Let's break it down: - `r2` is `0`, so now we have `d(r0)` - `r0` is `7`, so now we have `d7` -Since the maximum number of devices an IC Housing can connect is 6 (d0-5), this would break the script. This is why multi-level referencing should be used extremely sparingly. \ No newline at end of file +Since the maximum number of devices an IC Housing can connect is 6 (d0-5), this would break the script. This is why multi-level referencing should be used extremely sparingly. From bf24627b164d915b52ec0d92cd07f1641698f40f Mon Sep 17 00:00:00 2001 From: Snorre Selmer Date: Tue, 17 Jan 2023 10:54:53 +0100 Subject: [PATCH 3/5] Added bug-report instructions --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cfc34c5..0726c51 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ This repo contains ic10 code for the space survival sandbox Stationeers (https:/ All code should be used with caution. It should work:tm: but I can't guarantee it's not broken. Items needed are described in the comments at the top of each file. +## "I found a bug!" +Awesome! My code is probably not perfect, so please file an issue (https://github.com/SnorreSelmer/stationeers_ic10/issues) and I'll fix it! That's the best way to do it, it benefits everyone. + ## The scripts: - **auto_adv_furnace_library.ic10** - A fork of Elmotrix' furnace-library, removed Prev/Next buttons, added external On/Off-switch. - **auto_arc_furnace.ic10** - As long as there's ore in the input, the Arc Furnace will smelt. @@ -17,4 +20,4 @@ All code should be used with caution. It should work:tm: but I can't guarantee i - **heating_cooling.ic10** - Temperature regulator with optional temperature display. - **printer_countdown.ic10** - Uses a counter (Stacker or Dial) to order a given number of items. Stops printing when order is filled. - **solar_tracking.ic10** - Accurate two-axis solar-panel tracking for up to two types of panels. -- **storm_warning.ic10** - Monitors a Weather Station, announces incoming storms, sounds an alarm when the storm is 3 minutes from hitting, stops alarm when the storm is less than 1 minute from hitting. (Can be adjusted.) \ No newline at end of file +- **storm_warning.ic10** - Monitors a Weather Station, announces incoming storms, sounds an alarm when the storm is 3 minutes from hitting, stops alarm when the storm is less than 1 minute from hitting. (Can be adjusted.) From 635aadaf23362eaae5d9ec0e83bbdd3111fd5b7b Mon Sep 17 00:00:00 2001 From: Snorre Selmer Date: Wed, 18 Jan 2023 12:39:21 +0100 Subject: [PATCH 4/5] Fixed typo --- mips-programming-101.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mips-programming-101.md b/mips-programming-101.md index ca2473a..4724210 100644 --- a/mips-programming-101.md +++ b/mips-programming-101.md @@ -112,7 +112,7 @@ and slt HeaterOn CurrentTemperature MinimumTemperature ``` -They could do the exact same thing, but the bottom one actually explains what's going on. And it's still shorter that 57 characters. +They could do the exact same thing, but the bottom one actually explains what's going on. And it's still shorter than 57 characters. If you're juggling 10+ registers in your code without naming them, the chances of getting them mixed up increases greatly. And if you do make a mistake somewhere, trying to follow the code can be more complicated than if you used named variables. From 3035f103250e325a7f06f5590a1e489c53622c59 Mon Sep 17 00:00:00 2001 From: Snorre Selmer Date: Wed, 18 Jan 2023 12:44:22 +0100 Subject: [PATCH 5/5] Improved wording around relative branching --- mips-programming-101.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mips-programming-101.md b/mips-programming-101.md index 4724210..fb0ba51 100644 --- a/mips-programming-101.md +++ b/mips-programming-101.md @@ -147,7 +147,7 @@ This ***define***s ***MinimumTemperature*** as ***20*** (maybe for use as 20 Cel ## Branch/set matrix -There is logic for relative jumping in code. I have yet to find a use for it that can't be done better with any of the other functions, so I won't cover it here. +There is also logic for relative jumping in code, and it works by adding an 'r' after the 'b' when branching (so 'b' becomes 'br'). Instead of giving the branch a label to go to, you tell it the number of lines to jump (positive number jumps forwards, negative number jumps backwards).
SuffixPrefix