In an N64 program, addresses begin at `0x80000000`. As you create code, data, and the like, the compiler will add onto this base number and assign variables to an address.
The address of this could extend from `0x80000100` to `0x800000534`. However, you would not see data begin at `0x80000533`. The compiler generally aligns objects to 4, 8, 0xC, or 0x10. With the exception being when you're working with s16 and s8. If you have:
If `d` was set to 0x100, the final `0` would be written to the first bit of `e`. This could result in an invalid float value or perhaps flipping the signedness of an s32 (from negative to positive and vice-versa).
Issues such as this could result in glitches or crashes. Once humble math calculating to immeasurable values.
## Array Overflows
In the below example, my_func writes a value at the fifth index which does not exist. This results in writing 5.0f into the next variable lkely resulting in a crash. Array overflows may be easy to miss in complex programs and sometimes only crash on rare occasion.
The `lui, addiu, ori, etc.` are just representations of the machine-code. For example: `0x3C08800F` is what the cpu is actually running. Lets break down this one command:
`op-code, parameters`
0x3C is the op-code (lui or load-upper-immediate) this command loads an address. The `08` tells the CPU to use the register `t0` and the `0x800F` is the first-half of the address to load. So, in the register t0 (which is the size of an int: 0x00000000) the value `0x800F0000` is written.
Note that one machine-code command is the size of an int/s32/word. How do we load an address (which is the size of an int). There isn't enough room when you include the op-code and register: `0x3C08800F6990`. That no worky. As such, loading data at an address requires two commands. The first half of the address is called a hi and the second half is called a lo:
If you run the game and use a memory viewer at this location. You will quickly realize this region of data (it's actually .bss but lets not get into that), is the controller data. The data alters to reflect which controller buttons are pressed. So if I just wanted to read one of these values, the cpu will run two commands to put the address into the register. Then another command can read the address in that register to receive the value at that location. This value can be compared to see if the button is active. Ex. zero might mean not pressed, whereas one might mean pressed.
Now, earlier it was mentioned that code contains addresses. If I wanted to, I could do this: `Jump to: 0x80000410`. Which would make the CPU start running code at that location. Or I could read the value that exists there: `0x2129FFF8`. Not sure what I might do with that number, but it does act like a normal number. In decimal it is: `556,400,632`. I could add and subtract to it (Which would likely crash the game if it tried to run that command after). Now, jumping to any code address in the middle of a function would almost certainly crash the game or result in strange behaviour. The purpose of this explanation is really to show that everything is just a bunch of numbers or values, represented by an address. Even the code itself.