Toggle search
Search
Toggle menu
notifications
Toggle personal menu
Editing
Basic Assembly Programming
(section)
From Turing Complete
Views
Read
Edit
Edit source
View history
associated-pages
Page
Discussion
More actions
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Getting Started == Let’s focus on the OVERTURE architecture, for now. Like almost every assembly language, OVERTURE executes instructions in a straight line, one by one, unless a jump instruction changes where we are in the program. OVERTURE doesn’t have a <code>not</code> instruction. Let’s examine how we could compute the bitwise complement of the value in register 0. Recall that all OVERTURE logic operations take their arguments from registers 1 and 2, and put the result in register 3. We don’t have a <code>not</code> instruction, but we do have <code>and</code>, <code>or</code>, <code>nand</code>, and <code>nor</code>, as well as <code>add</code> and <code>sub</code>. We could invert a byte by <code>nand</code>ing it with itself, but for the purposes of demonstration, let’s do something a bit more exotic. <span id="xor-as-a-bit-toggle"></span> ===== XOR As a Bit Toggle ===== Remember the level Bit Inverter? We can use a bitwise XOR (written <code>^</code>) to selectively invert bits. The operation <code>m ^ w</code> “toggles” all the bits in <code>w</code> that match up with the ones in <code>m</code>, and leave the rest unchanged. We call <code>w</code> the “word” or “argument” and <code>m</code> the “mask.” Note that these names are specific to this use case and do not apply to all uses of XOR. So if we want to completely invert a byte, we want to XOR it with a mask which is all ones. To do that, we’ll need to construct the mask. We can’t simply <code>loadi</code>, because our mask has the value <code>255</code> and immediates must be less than 64. <span id="multi-purpose-subtraction"></span> ===== Multi-Purpose Subtraction ===== To do this, we must take advantage of the fact that computers do not care where a value came from. They only care what the value ''is''. What we want is a completely logical object, a mask that refers to ''every'' bit. But we can get it in a completely arithmetic way - the value is <code>255</code>, which in 8-bit arithmetic is the same as <code>-1</code>. What’s the easiest way to get <code>-1</code>? <code>0 - 1</code>! We can <code>loadi</code> those values. But there’s one catch. <span id="moving-data-around"></span> ===== Moving Data Around ===== We said we want to complement the value in register 0. <code>loadi</code> would overwrite that value, so we need to save it in a different register first. Registers 1, 2, and 3 will be used for logical operations, so we’ll save it in register 4. Turing Complete should have automatically given you the mnemonic <code>0to4</code> for “moving” the value in register 0 to register 4. Note that this overwrites register 4, but ''does not'' change register 0. The operation is a copy-and-paste, not a cut-and-paste. Despite this, the typical assembly term for this operation is a '''data move''', '''register move''', or simply '''move'''. I recommend using the bitwise-or trick discussed above to make mnemonics for each source register and each destination register and then write <code>move|s0|d4</code>. Some architectures use the mnemonic <code>mov</code> instead of <code>move</code>, and others use <code>load</code>. <span id="putting-the-first-pieces-together"></span> ===== Putting The First Pieces Together ===== So let’s get our value from register 0 to register 4, and set up for the XOR: <pre>move|s0|d4 loadi|0 move|s0|d1 loadi|1 move|s0|d2 sub</pre> This gets us our mask in register 3. But hold on… we don’t have an XOR instruction, either! <span id="complex-operations-from-simple-ones-xor"></span> ===== Complex Operations From Simple Ones (XOR) ===== We can break the XOR operation into smaller steps. Recall that the XOR of <code>a</code> and <code>b</code> is <code>a ^ b = (a | b) & ~(a & b)</code>. In words, the XOR of two bits is 1 if their OR is 1, ''and'' their AND is 0. We have OR and NAND operations, so we can do these things. We need to save some intermediate values while we’re working. We’ll use register 0 since it’s free. Notice how we shuffle data around into the correct registers as needed. <pre>move|s4|d1 # the value we saved earlier move|s3|d2 # the mask we just computed or # their bitwise OR move|s3|d0 # save that so it isn't overwritten by... nand # their bitwise NAND move|s0|d1 # prepare to operate on their OR... move|s3|d2 # and their NAND... and # the result of the XOR.</pre> Now we have the bitwise complement of the value that was in register 0. It’s in register 3, but from here we could move it wherever we want. <span id="control-flow"></span>
Summary:
Please note that all contributions to Turing Complete are considered to be released under the Creative Commons Attribution-ShareAlike (see
TuringComplete:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)