News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: [rusty asm] Call a routine from a routine  (Read 4834 times)

tryphon

  • Hero Member
  • *****
  • Posts: 722
    • View Profile
[rusty asm] Call a routine from a routine
« on: December 06, 2012, 04:54:48 am »
Hi,

my assembler is quite rusty, and I'd want confirmation for the following : let's call a routine some piece of code that is called by :
Code: [Select]
jal ROUTINEand ends with a :
Code: [Select]
jr ra
Suppose I want to call a routine from the inside of a routine.

I must save the ra value before, don't I ?

I can do (assuming t0 is left unmodified by ROUTINE, and without considering delay issues) :
Code: [Select]
mov t0, ra ; or the contrary, I never remember, but you the idea is t0 <- ra
jal ROUTINE
mov ra, t0

or putting ra in the stack ?

Sorry for the stupidness of the question.
« Last Edit: December 06, 2012, 05:01:56 am by tryphon »

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #1 on: December 06, 2012, 05:01:45 am »
Edit: nvm i was thinking in 6502.

That looks like assembly I learned in college. Yeah you would save ra.
« Last Edit: December 06, 2012, 05:09:00 am by Pikachumanson »

tryphon

  • Hero Member
  • *****
  • Posts: 722
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #2 on: December 06, 2012, 05:02:54 am »
That's entirely my fault, but you answered before I finished my question :)

Pikachumanson

  • Hero Member
  • *****
  • Posts: 607
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #3 on: December 06, 2012, 05:09:40 am »
Sorry about that lol

tryphon

  • Hero Member
  • *****
  • Posts: 722
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #4 on: December 06, 2012, 05:15:05 am »
It's MIPS assembler, I'm currently hacking a PS2 game.

Thanks for confirmation :)

PhOeNiX

  • Jr. Member
  • **
  • Posts: 85
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #5 on: December 06, 2012, 06:49:44 am »
Normally, ra it's stored in the stack together with other needed registers at the start of your routine, e.g.:
Code: [Select]
addi $sp, $sp, -20
sw  $ra, 16($sp)
sw $s3, 12($sp)
sw $s2, 8($sp)
sw $s1, 4($sp)
sw $s0, 0($sp)

ax registers like a0,a1 etc. are usually used for parameters to routines and vx registers like v0 etc. for return values. Temporary registers like t0 etc. are not guaranteed to contain the same value through routine calls, so they not need to be stored in the stack before the routine starts.

Zoinkity

  • Hero Member
  • *****
  • Posts: 565
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #6 on: December 06, 2012, 08:41:17 am »
RA (as in return address) is automatically set whenever you use a 'jump and link' or 'branch and link' opcode.  If you don't want to set RA you can use a different register via JALR. 


Doesn't typical design style always keep the first 0x10 of the stack free for use within the routine, sometimes explicitly marked volatile?  That's followed by any variables above A3 that get passed via the stack, and then variable storage would go after...

Pyriel

  • Jr. Member
  • **
  • Posts: 23
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #7 on: December 06, 2012, 10:59:38 am »
JALR still uses $RA to store the return address (PC+8).  It just lets you specify the address to jump to on a register instead encoding it into the OP.  If you're going to use any variant of JAL on a PS2, you need to ensure that $RA's value will be restored.  How you accomplish that depends on what you're doing.  If you're just writing code from scratch to assemble and run, you should follow the general rules and preserve on the stack.  If you're doing something like making cheat codes, or modifying the game by inserting code into the ELF somehow, you can get away with other tricks (I've stuffed it onto $S* registers that are saved by target routines before to save operations).  Although, if what you're doing is complex in any way, you'll probably be better off following the usual etiquette regardless of your goals.

Edit: I take that back.  There is a rarely used option in the JALR op-code that lets you specify the link register ("JALR link, target" as opposed to just "JALR target" with $RA being implied as the link register).  I've never even seen it in a game ELF.  It seems like doing that would just make things confusing.
« Last Edit: December 06, 2012, 11:12:54 am by Pyriel »

Gemini

  • Hero Member
  • *****
  • Posts: 2025
  • 時を越えよう、そして彼女の元に戻ろう
    • View Profile
    • Apple of Eden
Re: [rusty asm] Call a routine from a routine
« Reply #8 on: December 06, 2012, 12:11:51 pm »
"JALR link, target" isn't used at all because the convention doesn't bother to take advantage of anything but ra for subroutine return address, even if you're allowed to use whatever you want for your pure assembly code. Still, all compiled code ends with "jr ra" and using another return register could be potentially error prone when you start mixing up assembled and compiled.
I am the lord, you all know my name, now. I got it all: cash, money, and fame.

tryphon

  • Hero Member
  • *****
  • Posts: 722
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #9 on: December 06, 2012, 03:00:00 pm »
In fact, I modify an existing game and am affected by size issues, so enlarging the stack, storing ra then getting back its value and decreasing the stack would necessite more op.

jalr link, adress is not an option (although it's interesting and I did not know about that) because both routines are in the game and end both by jr ra.

Thanks for all these enlightenments :)

Zoinkity

  • Hero Member
  • *****
  • Posts: 565
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #10 on: December 06, 2012, 04:37:58 pm »
I can understand where the confusion would lie, since compilers will accept "JALR addr" and set target to RA if not provided.  Either is acceptable though, as is clearly noted in the MIPS manual.

That may be the case with PSX, but N64 uses JALR with different targets rather often.  Therein lies the difference in compilers though; the usual case is a sort of switch routine, jumping a table-ripped address and usually using a Tx variable to hold the return, and in this resepect is handled much the same way that the error handler might be.  This of course only works because you're controlling the situation, and I'd guess is a compiler-specific method of handling this particular case.

Actually, since when hacking you explicitly control the situation, you can always shuffle RA into another register (OR reg, R0, RA) to avoid stack overhead.  In fact you don't even need to shuffle it back necessarily, since you can also set what register is used for the jump back.
There's no threat of it being corrupted by threading or interrupts.  Both of those will make a complete copy of all the registers in use and swap them back before returning.  Only if a register is explicitly used in your code will it be corrupted.

Pyriel

  • Jr. Member
  • **
  • Posts: 23
    • View Profile
Re: [rusty asm] Call a routine from a routine
« Reply #11 on: December 06, 2012, 10:42:50 pm »
Personally, I just assumed it was another add-on operation like the supposedly EE-specific op codes for the PS2, until I thought about how many unused bits that would leave JALR with, and double-checked the instruction set.

In fact, I modify an existing game and am affected by size issues, so enlarging the stack, storing ra then getting back its value and decreasing the stack would necessite more op.

jalr link, adress is not an option (although it's interesting and I did not know about that) because both routines are in the game and end both by jr ra.

Thanks for all these enlightenments :)
What is it that you're doing?  It sounds like you're trying to add JALs to a routine that doesn't already have them, and it therefore doesn't bother saving $ra.  There are ways around that, but just how depends on whether you're doing run-time modification or patching the ELF.