Welcome to Hackers Alliance!

Calling Functions

  • Archived

    The forum is archived and used for testing. It is currently read-only to visitors.
    It has been upgraded from vBulletin 3.8.x to XenForo for security purposes and future-proofing. Proprietary code and modifications (such as code database and HA bot) are broken with XenForo and will stay only with vBulletin.

-LeetGamer-

Coder
Coder
Oct 17, 2010
66
2
0
This tutorial is going to be on how to call a function in MIPS. I'm not going to be telling you how to find a function(s), you will have to learn from another place.

The first thing you should know is what a functions is. A function is a block of code that does a specific job for you. This block of code is only used when it is needed. An example of this is the function to decrease your ammo when you shoot. That function is only used when we shoot. Its job is to decrease your ammo. Functions can also take in information that you give them, this information is called arguments. Registers a0, a1, a2, and a3 hold the arguments that are passed into the function.

Before I continue I need you to make sure you know:
* MIPS Commands Lui, Ori, Addi, Lw, Sw, Nop, Beq, Bne, Jr, Jal, and Jalr
* MIPS Registers zero, a0 - a3, t0 - t7, t8 & t9, and ra
* What the delay slot is and how it is used
* Basic to intermediate subroutine knowledge

If you don't know those then use google, or you can just continue on and you might learn what they are (I suggest reading a guide that will explain them though)
Here is a list of things that you will learn:
* Basic understanding of stack (Hopefully you will get it)
* How to call functions
* How to pass arguments into functions

So lets get started, there is a order that you need to do things in:
1. Find what argument registers are used
2. Find what values are in the argument registers when the function is called
3. Write a Stack routine which will call your function
4. Examples

1. Find what argument registers are used

To do this you need to understand that functions are called with a Jal, or Jalr command. Now we need to understand that a function can be called with a Jal or a Jalr command. First thing we need to do is find the jal or jalr that called the function. First we search for jal's by searching the value of jal $starting_address_of_your_function. If my function started at 0x00121234 then I would search the value of jal $08921234 which is 0x0E24848D. If I get any results then I copy the address and paste it into the decoder. Then I check for a few things:

1. Does it use an argument register in the delay slot (Example: ori a1 zero $0001)
2. If 1. is true then check for argument registers being used right above the jal (If there are more than one argument then they will be above the jal).

Example of this:

If statement 1. is only true it will look something like this: (Note: // is a comment on how the code works, it doesn't change the code at all though)
Code:
ori t0 zero $1100 // No argument register (a0, a1, a2, or a3) used here, so only one argument (if any) is passed, and it is in the jal's delay slot
jal $Function // Call the function
addu a1 s0 zero // Put s0 in a1, a1 is an argument register so it is passed into the function.
// a1 is used
If statement 2. is true it will look something like this:
Code:
ori a0 zero $0013 // a0 = 0x13
lw a1 $0090(t0) // a1 = value at t0 + 0x90
jal $Function // Call the function
ori a2 zero $0700 // a2 = 0x700
// a0, a1, and a2 are used
Those are just examples, you want to look for things similar to those examples. Write down all the argument registers that are used

2. Find what values are in the argument registers when the function is called

This is easy, you need to add this MIPS to the start of your function:

Code:
// If only a0 is used
lui t0 $0880
sw a0 $1000(t0)
jr ra
nop // Do NOT forget this!
Code:
// If a0, and a1 is used
lui t0 $0880
sw a0 $1000(t0)
sw a1 $1004(t0)
jr ra
nop // Do NOT forget this!
As you can see we are just storing the values in the argument registers to nop lines, and then we can check the values at those lines in the decoder to see the value that was passed into the function. You want to write down all the values for each argument that is passed into your function.

3. Write a Stack routine which will call your function

Now we get to the, somewhat, hart part. Here is an example code:

Code:
addiu sp sp $FFF0 // Subtract 0x10, or 16, from the stack pointer. We can now store the values of up to four registers to stack pointer offsets.
sw ra $0000(sp) // Store what ever is in ra to [[sp]+0].
lui a0 $08D8 // a0 = 0x8D8, this is the upper half of enemy one's pointer in mohh1.
lw a0 $3620(a0) // a0 = value at 0x8D83620, this is the lower half of enemy one's pointer in mohh1, a0 now holds the full enemy one pointer.
jal $08902BDC // Call the damage function, this function takes two arguments: a0 = Pointer to player to damage, a1 = amount to damage that player.
ori a1 zero $0200 // a1 = 0x200, which is enough to kill the player.
lw ra $0000(sp) // Load value at [[sp]+0] to ra.
jr ra // Jump to what ever address is in ra
addiu sp sp $0010 // Add 0x10, or 16, back to the stack pointer.
The above code will make an enemy in the game kill themself, this is for MOHH1.

So now I want to guide you through your own stack routine:

1. Subtract 0x10 (which is 16 in dec) from the stack pointer, there are two ways to do this:
Code:
addiu sp sp $FFF0
or
Code:
addiu sp sp -16
2. Store the value in ra to an offset of the stack pointer. If you do not know why we do this then learn what linking commands do to the ra register, and think about it.
Code:
sw ra $0000(sp)
We could use any offset, but why not start at zero.

3. Now we are going to load any arguments you have ONLY IF YOU HAVE MORE THAN ONE ARGUMENT. So let's say you have 0x6000 in argument register 2 (a2) I would do this:
Code:
ori a2 zero $60000
Lets say you have the value at address 08803400 in argument register 0 (a0) I would do this:
Code:
lui a0 $0880
lw a0 $3400(a0)
Hope fully you get it. IF YOU DO NOT HAVE MORE THAN ONE ARGUMENT THEN GO TO STEP 4.
Also note: If you have three or more arguments do this:
Code:
// a0 = 1, a1 = 2
ori a0 zero $0001
ori a1 zero $0002
Code:
// a0 = 1, a1 = 2, a2 = 3
ori a0 zero $0001
ori a1 zero $0002
ori a2 zero $0003
4. Now we need to jump and link to the function. Here is how:
Code:
jal $starting_address_of_function_in_true_addressing
Not that hard.

5. Now we need to pass in arguments in the delay slot
Code:
// If a0 = 1
jal $starting_address_of_function_in_true_addressing // Don't do this again, I am only showing that "ori a0 zero $0001" comes right after the jal"
ori a0 zero $0001
Its the same thing as in step 3 really.

6. Now we need to load back the value in [[sp]+0] which holds the address that our routine needs to link back to
Code:
lw ra $0000(sp)
But make sure you load from the right offset, which would be the one that you stored to in step 2.

7. Now we need to link back
Code:
jr ra
8. And in the delay slot of the jr ra we add 0x10 back to the stack pointer
Code:
addiu sp sp $0010
or
Code:
addiu sp sp 16

Examples
Function start address: 0x08801000
Function Argument values: a0 = 0x12, a1 = value at 0x08803FFC + 0 + 4, a2 = 0x1, a3 = 0x100
Code:
addiu sp sp $FFF0
sw ra $0000(sp)
ori a0 zero $0012
lui a1 $0880
lw a1 $3FFC(a1)
lw a1 $0000(a1)
lw a1 $0004(a1)
ori a2 zero $0001
jal $08801000
ori a3 zero $0100
lw ra $0000(sp)
jr ra
addiu sp sp $0010


Function start address: 0x08901234
Function arguments: a0 = 0x1, a1 - a3 = not used
Code:
addiu sp sp $FFF0
sw ra $0000(sp)
jal $08901234
ori a0 zero $0001
lw ra $0000(sp)
jr ra
addiu sp sp $0010


Function start address: 0x08918888
Function arguments: a1 = 1, a2 = value at 0x08900000 + 0, a0 & a3 = not used
Code:
addiu sp sp $FFF0
sw ra $0000(sp)
ori a1 zero $0001
lui a2 $0890
lw a2 $0000(a2)
jal $08918888
lw a2 $0000(a2)
lw ra $0000(sp)
jr ra
addiu sp sp $0010


Function start address: 0x08811234
Function arguments: none used
Code:
addiu sp sp $FFF0
sw ra $0000(sp)
jal $08811234
nop
lw ra $0000(sp)
jr ra
addiu sp sp $0010

If you have any questions reply here !

-Leet
 
This site has been archived and is no longer accepting new content.

About us

  • Hackers Alliance is a small community forum about gaming and console hacking. Join our humble community to share ideas, game cheats, mods, and be part of an amazing growing community!

Quick Navigation

User Menu