forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

return values in assembly subroutine

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
serige



Joined: 26 Nov 2007
Posts: 35

PostPosted: Wed Nov 28, 2007 6:11 pm    Post subject: return values in assembly subroutine Reply with quote

For those who have decompiled allegrex assembly code before, i got another question for you, but i think it's a pretty general assembly code question tho =P

$v0 and $v1 are the return value registers, but why would you ever want to use both of them for the return value? the only instance i can think of is when you want to return a 64bit long double value, are there any other instances you will need to make use of both registers? and when determining the return value, if i see both $v0 and $v1 are used as a target register for some instructions, can i say that the subroutine is using both of them as return values for sure (that is, can i assume that the subroutine will not use any v registers for temp variable if the subroutine isn't returning any values)?

also, i came across something that doesn't make sense to me at the entry point of a subroutine:

addiu $sp, $sp, -4144
sw $ra, 4128($sp)
jal foo
lw $ra, 4128($sp)
jr $ra
addiu $sp, $sp, 4144

how come it reserves so many stack space but only to store a single return address register?!?!?

assembly isn't easy to learn, and i appreciate any related helps.
Back to top
View user's profile Send private message
StrmnNrmn



Joined: 14 Feb 2007
Posts: 46
Location: London, UK

PostPosted: Wed Nov 28, 2007 7:05 pm    Post subject: Reply with quote

I wouldn't assume it's doing anything clever. It could just be unoptimised (or poorly optimised) code generated by the compiler:

Code:
void blah()
{
  char buf[4140];
  //sprintf( buf, "in blah, about to call foo: %s", some_other_stuff );
  //Display( buf );
  foo();
}


or even

Code:
void Blah()
{
  void * buf = alloca(4140);
  // Did something with buf, commented out
  foo();
}


Or maybe they were occassionally stomping on their stack in foo and 'fixed' it by allocating a chunk of unused memory on the stack? :)
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Wed Nov 28, 2007 7:09 pm    Post subject: Reply with quote

Quote:
$v0 and $v1 are the return value registers, but why would you ever want to use both of them for the return value? the only instance i can think of is when you want to return a 64bit long double value, are there any other instances you will need to make use of both registers?


A structure that fits in both regs will be returned that way as well.
Back to top
View user's profile Send private message AIM Address
serige



Joined: 26 Nov 2007
Posts: 35

PostPosted: Wed Nov 28, 2007 7:22 pm    Post subject: Reply with quote

J.F. wrote:
Quote:
$v0 and $v1 are the return value registers, but why would you ever want to use both of them for the return value? the only instance i can think of is when you want to return a 64bit long double value, are there any other instances you will need to make use of both registers?


A structure that fits in both regs will be returned that way as well.


like...? i think a pointer is enough for any kind of structures
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Thu Nov 29, 2007 5:07 am    Post subject: Reply with quote

serige wrote:
J.F. wrote:
Quote:
$v0 and $v1 are the return value registers, but why would you ever want to use both of them for the return value? the only instance i can think of is when you want to return a 64bit long double value, are there any other instances you will need to make use of both registers?


A structure that fits in both regs will be returned that way as well.


like...? i think a pointer is enough for any kind of structures


Like obviously simple structures... ones less than or equal to 64 bits. You could do it via pointer as well, but gcc does allow the passing of structures directly in paired registers on certain platforms - ones with lots of regs, like RISC platforms.
Back to top
View user's profile Send private message AIM Address
serige



Joined: 26 Nov 2007
Posts: 35

PostPosted: Fri Nov 30, 2007 8:25 am    Post subject: Reply with quote

come across another weird place:

here is the function call:
; ======================================================
; Subroutine sub_0013AD58 - Address 0x0013AD58
sub_0013AD58: ; Refs: 0x0013AC8C 0x0013ACD0
0x0013AD58: 0x27BDFFE0 '...'' - addiu $sp, $sp, -32
0x0013AD5C: 0xAFB3000C '....' - sw $s3, 12($sp)
0x0013AD60: 0x00C09821 '!...' - move $s3, $a2
0x0013AD64: 0xAFB10004 '....' - sw $s1, 4($sp)
0x0013AD68: 0x00A08821 '!...' - move $s1, $a1
0x0013AD6C: 0x24050012 '...$' - li $a1, 18
0x0013AD70: 0xAFB00000 '....' - sw $s0, 0($sp)
0x0013AD74: 0x00808021 '!...' - move $s0, $a0
0x0013AD78: 0x00E02021 '! ..' - move $a0, $a3
0x0013AD7C: 0xAFB20008 '....' - sw $s2, 8($sp)
0x0013AD80: 0xAFBF0010 '....' - sw $ra, 16($sp)
0x0013AD84: 0x0C04EBFB '....' - jal sub_0013AFEC <------
0x0013AD88: 0x00E09021 '!...' - move $s2, $a3
0x0013AD8C: 0x0233182B '+.3.' - sltu $v1, $s1, $s3
....



and here is the function definition:



; ======================================================
; Subroutine sub_0013AFEC - Address 0x0013AFEC
sub_0013AFEC: ; Refs: 0x0013AD84 0x0013AEA0
0x0013AFEC: 0x24031000 '...$' - li $v1, 4096
0x0013AFF0: 0x00651023 '#.e.' - subu $v0, $v1, $a1
0x0013AFF4: 0x00805021 '!P..' - move $t2, $a0
0x0013AFF8: 0x18400007 '..@.' - blez $v0, loc_0013B018
0x0013AFFC: 0x00005821 '!X..' - move $t3, $zr
0x0013B000: 0x00402021 '! @.' - move $a0, $v0

loc_0013B004: ; Refs: 0x0013B010
0x0013B004: 0x014B1021 '!.K.' - addu $v0, $t2, $t3
0x0013B008: 0x256B0001 '..k%' - addiu $t3, $t3, 1
0x0013B00C: 0x0164282A '*(d.' - slt $a1, $t3, $a0
0x0013B010: 0x14A0FFFC '....' - bnez $a1, loc_0013B004
0x0013B014: 0xA0400000 '..@.' - sb $zr, 0($v0)

loc_0013B018: ; Refs: 0x0013AFF8
0x0013B018: 0x00004821 '!H..' - move $t1, $zr
0x0013B01C: 0x00005821 '!X..' - move $t3, $zr

loc_0013B020: ; Refs: 0x0013B084
0x0013B020: 0x252D0001 '..-%' - addiu $t5, $t1, 1
0x0013B024: 0x25AC0001 '...%' - addiu $t4, $t5, 1
0x0013B028: 0x25840001 '...%' - addiu $a0, $t4, 1
0x0013B02C: 0x24820001 '...$' - addiu $v0, $a0, 1
0x0013B030: 0x24450001 '..E$' - addiu $a1, $v0, 1
0x0013B034: 0x24A70001 '...$' - addiu $a3, $a1, 1
0x0013B038: 0x0149C821 '!.I.' - addu $t9, $t2, $t1
0x0013B03C: 0x014D4021 '!@M.' - addu $t0, $t2, $t5
0x0013B040: 0x014C3021 '!0L.' - addu $a2, $t2, $t4
0x0013B044: 0x0144C021 '!.D.' - addu $t8, $t2, $a0
0x0013B048: 0x01427821 '!xB.' - addu $t7, $t2, $v0
0x0013B04C: 0x01457021 '!pE.' - addu $t6, $t2, $a1
0x0013B050: 0x01476821 '!hG.' - addu $t5, $t2, $a3
0x0013B054: 0xA32B0000 '..+.' - sb $t3, 0($t9)
0x0013B058: 0x24E30001 '...$' - addiu $v1, $a3, 1
0x0013B05C: 0x01436021 '!`C.' - addu $t4, $t2, $v1
0x0013B060: 0xA1000000 '....' - sb $zr, 0($t0)
0x0013B064: 0x24690001 '..i$' - addiu $t1, $v1, 1
0x0013B068: 0xA0CB0000 '....' - sb $t3, 0($a2)
0x0013B06C: 0xA3000000 '....' - sb $zr, 0($t8)
0x0013B070: 0xA1EB0000 '....' - sb $t3, 0($t7)
0x0013B074: 0xA1C00000 '....' - sb $zr, 0($t6)
0x0013B078: 0xA1AB0000 '....' - sb $t3, 0($t5)
0x0013B07C: 0x256B0001 '..k%' - addiu $t3, $t3, 1
0x0013B080: 0x29640100 '..d)' - slti $a0, $t3, 256
0x0013B084: 0x1480FFE6 '....' - bnez $a0, loc_0013B020
0x0013B088: 0xA1800000 '....' - sb $zr, 0($t4)
0x0013B08C: 0x24090800 '...$' - li $t1, 2048
0x0013B090: 0x00005821 '!X..' - move $t3, $zr
0x0013B094: 0x240CFFFF '...$' - li $t4, -1

loc_0013B098: ; Refs: 0x0013B0F0
0x0013B098: 0x252F0001 '../%' - addiu $t7, $t1, 1
0x0013B09C: 0x25EE0001 '...%' - addiu $t6, $t7, 1
0x0013B0A0: 0x25CD0001 '...%' - addiu $t5, $t6, 1
0x0013B0A4: 0x25A40001 '...%' - addiu $a0, $t5, 1
0x0013B0A8: 0x24870001 '...$' - addiu $a3, $a0, 1
0x0013B0AC: 0x24E80001 '...$' - addiu $t0, $a3, 1
0x0013B0B0: 0x01491021 '!.I.' - addu $v0, $t2, $t1
0x0013B0B4: 0x014F3021 '!0O.' - addu $a2, $t2, $t7
0x0013B0B8: 0x014E2821 '!(N.' - addu $a1, $t2, $t6
0x0013B0BC: 0x014DC821 '!.M.' - addu $t9, $t2, $t5
0x0013B0C0: 0x01441821 '!.D.' - addu $v1, $t2, $a0
0x0013B0C4: 0x0147C021 '!.G.' - addu $t8, $t2, $a3
0x0013B0C8: 0x01487821 '!xH.' - addu $t7, $t2, $t0
0x0013B0CC: 0xA04B0000 '..K.' - sb $t3, 0($v0)
0x0013B0D0: 0xA0CC0000 '....' - sb $t4, 0($a2)
0x0013B0D4: 0xA0AB0000 '....' - sb $t3, 0($a1)
0x0013B0D8: 0xA32C0000 '..,.' - sb $t4, 0($t9)
0x0013B0DC: 0xA06B0000 '..k.' - sb $t3, 0($v1)
0x0013B0E0: 0xA30C0000 '....' - sb $t4, 0($t8)
0x0013B0E4: 0xA1EB0000 '....' - sb $t3, 0($t7)
0x0013B0E8: 0x256B0001 '..k%' - addiu $t3, $t3, 1
0x0013B0EC: 0x296E0100 '..n)' - slti $t6, $t3, 256
0x0013B0F0: 0x15C0FFE9 '....' - bnez $t6, loc_0013B098
0x0013B0F4: 0x25090001 '...%' - addiu $t1, $t0, 1
0x0013B0F8: 0x03E00008 '....' - jr $ra
0x0013B0FC: 0x00000000 '....' - nop
0x0013B100: 0x3C02004C 'L..<' - lui $v0, 0x4C
; Data ref 0x004BF8F7 ... 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0013B104: 0x9044F8F7 '..D.' - lbu $a0, -1801($v0)
0x0013B108: 0x03E00008 '....' - jr $ra
0x0013B10C: 0x308200FF '...0' - andi $v0, $a0, 0xFF

//end of Subroutine sub_0013AFEC

as you can see $ra has not been modified in any way before the function returns, but it has 2 'jr $ra' instructions at the end!

i am assuming the original c code would look something like this:

sub_0013AFEC(){
...
...
...
t1 = t0 + 1; //0x0013B0F4
return;

v0 = 0x004C0000;
a0 = v0[-1801];
v0 = a0 & 0xFF;
return;
}

and of course, the code after the first return would never be executed. can anyone justify this? or the compiler is doing something fancy that i somehow fail to notice?
Back to top
View user's profile Send private message
moonlight



Joined: 26 Oct 2005
Posts: 567

PostPosted: Fri Nov 30, 2007 10:10 am    Post subject: Reply with quote

13B100 seems to be other function.

I don't know which disassembler you are using but be careful, for example some dissasemblers like prxtool only detect the begin of a function when they are called, when there is a jal.

But you won't see the start of functions that are called through pointers, or that are passed to kernel functions as parameters (for example, the thread function for sceKernelCreateThread).

Anyways there must be a reference to the function. Just look for "b100" and you may find the reference. If it is not referenced, then it is a dead function, a function that the programmer implemented but didn't use.
Back to top
View user's profile Send private message
serige



Joined: 26 Nov 2007
Posts: 35

PostPosted: Fri Nov 30, 2007 11:27 am    Post subject: Reply with quote

yeah, i am using prxtool, and i have searched through the whole program (using '0013B100') but didn't see any reference pointing at that location or anywhere near there...
Back to top
View user's profile Send private message
moonlight



Joined: 26 Oct 2005
Posts: 567

PostPosted: Fri Nov 30, 2007 12:08 pm    Post subject: Reply with quote

serige wrote:
yeah, i am using prxtool, and i have searched through the whole program (using '0013B100') but didn't see any reference pointing at that location or anywhere near there...


search B100, as the reference is probably splitted between 0013 and B100 ;)
Back to top
View user's profile Send private message
serige



Joined: 26 Nov 2007
Posts: 35

PostPosted: Fri Nov 30, 2007 3:31 pm    Post subject: Reply with quote

moonlight wrote:
serige wrote:
yeah, i am using prxtool, and i have searched through the whole program (using '0013B100') but didn't see any reference pointing at that location or anywhere near there...


search B100, as the reference is probably splitted between 0013 and B100 ;)


it wouldn't work for B100 as its a big file and there are 4645 occurrences come out when i do the search. so its almost impossible to find out.

maybe you can suggest a better tool?
Back to top
View user's profile Send private message
TyRaNiD



Joined: 18 Jan 2004
Posts: 918

PostPosted: Sat Dec 01, 2007 3:09 am    Post subject: Reply with quote

prxtool should find functions which are called through static pointers and implicit pointers such as for createthread as long as you are disassembling a prx with relocations. This alas does not apply to 3.7X where they have changed the relocaiton format and I am far too lazy to reverse it ;)
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group