Jumping from a function to the beginning of another
Users browsing this thread: 1 Guest(s)

I'm working on a hack where when a cheat is entered, it loads in some data. I have a question about the registers in doing so: when I'm in the original function (the one that looks to see if the cheat is entered), all the registers are full with values relative to this function. I want to jump from this function once the cheat is triggered to another function that loads in data at a different part of the game. Initially I was just going to add a JAL or J to go to the new function but I realized once in the new func, it will start writing new values to the Regs that are necessary for it to work.

is this correct? Will the reg values for the original function be gone if I JAL out of it to the new function, go through that code, then JR RA back to the original one?
.

Register values that are needed later are normally saved to the calling function's stack frame before jumping

See this reference for standard register usage: http://n64dev.org/registers.html
And some more in-depth reading material: https://acm.sjtu.edu.cn/w/images/d/db/MIPSCallingConventionsSummary.pdf

Example C code:
void main(){
   u32 stack_variable = 5;
   PrintInt(stack_variable);
   PrintInt(stack_variable + 1);
}

MIPS equivalent:
main:
  addiu sp, sp, -8 ; allocate a new stack frame with 8 available bytes
  sw ra, 0x00(sp)  ; save return address to the stack
  ori a0, r0, 5    ; load 5 into the arg0 register
  sw a0, 0x04(sp)  ; save to the stack frame (set stack_variable to 5)
  jal PrintInt     ; call PrintInt(5)
  nop
  lw a0, 0x04(sp)  ; load stack_variable (a0 may have had garbage in it from the previous PrintInt call)
  addiu a0, a0, 1
  jal PrintInt
  nop
  lw ra, 0x00(sp)  ; load return address
  jr ra            ; return
  addiu sp, sp, 8  ; deallocate stack frame

Anything is possible while handwriting asm though. If you absolutely need to, you may opt for hacky non-standard callee preservation:
a_haram_function:
  addiu sp, sp, -16
  sw t0, 0x00(sp)
  sw t1, 0x04(sp)
  sw ra, 0x08(sp)
  nop
  nop   ; do whatever here
  nop
  lw t0, 0x00(sp) ; restore calling function's registers before returning
  lw t1, 0x04(sp)
  lw ra, 0x08(sp)
  jr ra
  addiu sp, sp, 16
(This post was last modified: 17-12-2016, 11:32 PM by shygoo.)

(17-12-2016, 11:11 PM)shygoo Wrote: Register values that are needed later are normally saved to the calling function's stack frame before jumping

See this reference for standard register usage: http://n64dev.org/registers.html
And some more in-depth reading material: https://acm.sjtu.edu.cn/w/images/d/db/MIPSCallingConventionsSummary.pdf

Example C code:
void main(){
   u32 stack_variable = 5;
   PrintInt(stack_variable);
   PrintInt(stack_variable + 1);
}

MIPS equivalent:
main:
  addiu sp, sp, -8 ; allocate a new stack frame with 8 available bytes
  sw ra, 0x00(sp)  ; save return address to the stack
  ori a0, r0, 5    ; load 5 into the arg0 register
  sw a0, 0x04(sp)  ; save to the stack frame (set stack_variable to 5)
  jal PrintInt     ; call PrintInt(5)
  nop
  lw a0, 0x04(sp)  ; load stack_variable (a0 may have had garbage in it from the previous PrintInt call)
  addiu a0, a0, 1
  jal PrintInt
  nop
  lw ra, 0x00(sp)  ; load return address
  jr ra            ; return
  addiu sp, sp, 8  ; deallocate stack frame

Anything is possible while handwriting asm though. If you absolutely need to, you may opt for hacky non-standard callee preservation:
a_haram_function:
  addiu sp, sp, -16
  sw t0, 0x00(sp)
  sw t1, 0x04(sp)
  sw ra, 0x08(sp)
  nop
  nop   ; do whatever here
  nop
  lw t0, 0x00(sp) ; restore calling function's registers before returning
  lw t1, 0x04(sp)
  lw ra, 0x08(sp)
  jr ra
  addiu sp, sp, 16

Thanks for these details. I think I'm a bit confused still. In your example, you have "addiu sp,sp,-16", and then sw for t0,t1, and ra. However, The function I am in has all the registers filled with values (by the time I need to jump) - does this mean I need to sw all of the registers in order to call them back later?

Do you think the following Would work in principle?

beginning of function 1
addiu sp, sp, $0028 <-- this is actually the value of the beginning of the real function
... code
... code using regs
... code
insert first part of your code here:
addiu sp, sp, -16
  sw t0, 0x00(sp)
  sw t1, 0x04(sp)
  sw ra, 0x08(sp)
jump to function 2 (which has completely different reg values)
...code
...code
...code
...code
insert next part of your code here:
lw t0, 0x00(sp)
  lw t1, 0x04(sp)
  lw ra, 0x08(sp)
  jr ra
  addiu sp, sp, 16

Is the location of your code correct in the above example?

Jumping from a function to the beginning of another
Users browsing this thread: 1 Guest(s)