26 June 2008, 08:31 | #1 |
Global Moderator
Join Date: Nov 2001
Location: Derby, UK
Age: 48
Posts: 9,355
|
Lnk/Unlnk
Now I don't totally understand these commands other than they create temp workspace (Sounds like a procedure in c/basic)
If so why? The game I am WHDloading (Croak) is a complete game of lnk/unlk. every single routine is contained in one of these.. the game was written in C! I need lots of detailed info to understand thanks |
26 June 2008, 09:24 | #2 |
gone
Join Date: Apr 2007
Location: completely gone
Posts: 1,596
|
From what I understand from what I've read LINK/UNLK is there to make it easier to manage the stack in situations where subroutines call other subroutines that call other subroutines and so on where each of these subroutines needs space to store temporary data.
LINK/UNLK lets you store the temporary data on the stack itself but still maintain the integrity of the stack correctly for returns from those subroutines. LINK allocates a frame of memory (in bytes) on the stack and sets an address register as a pointer to that stack frame. link <address reg>,#-<value in bytes> The negative size of the value in bytes is cos the stack grows downwards. The values in bytes is a 16 bit signed number so max size of one stack frame is 32Kb. Each link command saves the address register used in the link command on the stack, then moves the value in the stack pointer to the address register and then subtracts the value in bytes from the stack pointer to grow the stack by that amount. Using an example address register of a5 and an example frame size of 512 bytes, link does this: move.l a5,-(a7) movea.l a7,a5 addq.l #-512,a7 The frame of memory created by link is now the space between the address register used in the link command and the current value of the stack pointer. Temporary data can be stored in this frame by moving data to where the address register is pointed to and the stack can also be used as normal without affecting this temporary frame data. An unlk command deallocates the frame space and restores the stack pointer. So, you can link space, call a subroutine, link more space if needed and then unlk space before returning control to the previous subroutine which can then in turn unlk its space and return from where it was called and each time the integrity of the stack is maintained. Sounds like your game maybe has lots of subroutines that all call each other and they've used link/unlk to make the stack management easier. Not sure if this helps in any way whatsoever but I hope it's helped you out! Last edited by pmc; 26 June 2008 at 09:31. |
26 June 2008, 13:26 | #3 |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,865
|
Nothing much to understand here, LINK/UNLK are for creating local workspace so subroutines that have to be re-entrant (or are just written in C or any other high level language) work correctly. If you don't write recursive/re-entrant routines, you can safely ignore these commands as you don't need them anyway. Pus, what PMC said except for the addq.l #-512,a7 bit (addq only works with 3 bit values where value >0 and <=8)
|
10 July 2008, 13:30 | #4 |
gone
Join Date: Apr 2007
Location: completely gone
Posts: 1,596
|
I've got a question about this. If I setup some variables (for want of a better word) like this:
var1: dc.w $1234 var2: dc.l $12345678 var3: dc.l $12345678 var4: dc.b $12 var5: dc.b $34 var6: dc.l $12345678 var7: dc.l $12345678 then link some space: link a4,#-20 and move the variables into the linked space like this: move.w var1,(a4) move.l var2,2(a4) move.l var3,6(a4) move.b var4,10(a4) move.b var5,11(a4) move.l var6,12(a4) move.l var7,16(a4) is it then faster (although, admittedly, less readable) later on in my code to do things like this: move.l $9abcdef0,2(a4) instead of things like this: move.l $9abcdef0,var2 Just curios - I'm trying to work out ways to make code quicker. While I'm on the subject of optimsation, is there a list of optimisations anywhere, such as "instead of clr.l d0, do a moveq.l #0,d0 cos it's faster..."? |
10 July 2008, 13:32 | #5 |
Global Moderator
Join Date: Nov 2001
Location: Derby, UK
Age: 48
Posts: 9,355
|
I'm guessing it'd be the same speed as it will be using the same ram, though I guess it might be closer together
|
10 July 2008, 13:59 | #6 | |
move.w #$4489,$dff07e
Join Date: Sep 2005
Location: Norfolk, UK
Age: 43
Posts: 2,351
|
Quote:
It would be saved as: move.l $9abcdef0,$xxxxxxxx with the $xxxxxxxx being filled in just before running by the AmigaDOS relocator. Although if these instructions are outside a main loop in reality there won't be much difference of course. |
|
10 July 2008, 14:08 | #7 | |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,865
|
musashi5150 is right! Use relative offsets whenever possible! Faster than using absolute 32 bit values.
Quote:
Code:
RSRESET s_var1: rs.w 1 s_var2: rs.l 1 s_var3: rs.l 1 s_var4: rs.b 1 .... etc |
|
10 July 2008, 14:20 | #8 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,574
|
Very simple 68000 rule: instruction takes at least "length of instruction in words" + "number of byte or word accesses, 1 byte = 1 word. 1 long = 2x word" memory cycles to complete.
(complex instructions like mul and addressing modes like -(ax) etc need more time. Or check the official 68000 pdf documentation, it includes timings.) 1 memory cycle is 1/4 of CPU clock on 68000 Amiga. |
10 July 2008, 14:46 | #9 |
gone
Join Date: Apr 2007
Location: completely gone
Posts: 1,596
|
@bippym: yeah, you're right they'll all still be RAM locations but I was anticipating that the increase in speed would come from referencing an offset of an address register cos it's faster to use registers than memory locations.
@mushash5150: watcha mate, good to hear from you - thanks for the confirmation. Yeah, I was aiming for these accesses to be in a main program loop hence setting them up first, and then accessing them on the offsets later. @StingRay: OK cool, so instead of linking space on the stack to an address register and then accessing offsets from that, I can setup an rs.x structure in the assembler and do the same. I take it I have to point an address register at this rs.x structure somewhere early on in my code so I can then use the offsets from that register later? @Toni: OK thanks for the info. If I was being very lazy though (), does anyone know if some kind soul has already worked all these time saving equivalents out and published a list somewhere? |
10 July 2008, 15:01 | #10 |
move.w #$4489,$dff07e
Join Date: Sep 2005
Location: Norfolk, UK
Age: 43
Posts: 2,351
|
Yeah, good to see you still playing around with metal banging Both of these are fairly interesting for optimising ideas - I bet Sting knows of better ones (Or just his voodoo 68k skills )
http://linux.cis.monroeccc.edu/~paul...c/trick68k.htm http://www.mways.co.uk/amiga/howtoco...optimising.php |
10 July 2008, 15:11 | #11 | |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,865
|
Quote:
the first approach would be something like this: Code:
lea VARS(pc),a5 move.l #$08154711,BORING(a5) move.l #$B00BBABE,STILL_BORING(a5) ... VARS RSRESET BORING rs.l 1 STILL_BORING rs.l 1 VARS_SIZE rs.b 0 ds.b VARS_SIZE ; important! space for the variables Code:
link a5,#-VARS_SIZE move.l #$08154711,BORING(a5) move.l #$B00BBABE,STILL_BORING(a5) ... unlk a5 VARS RSRESET BORING rs.l 1 STILL_BORING rs.l 1 VARS_SIZE rs.b 0 Notice that you don't have to reserve space for the variables here as you do that with the LINK instruction. Using these structures has also quite a big advantage: imagine you once change your variables, f.e. you remove the BORING variable (as you are not bored anymore :P), using the structure you can just delete it and that's all you have to do as the assembler automatically calculates the right offsets. If you would have used move.l #xxx,4(a5) you would have to change that everywhere in the source as 4(a5) is now 0(a5) for obvious reasons. I hope that was somewhat understandable. |
|
10 July 2008, 15:21 | #12 |
gone
Join Date: Apr 2007
Location: completely gone
Posts: 1,596
|
@musashi5150: nice one mate, I'll check those out.
@StingRay: Top man. Yeah, it was definitely understandable - and very timely, I was only looking at my code and thinking "if I ended up in a situation where I was having to change all those offsets it would be a pain in the arse!" and here you come posting the solution. |
10 July 2008, 15:27 | #13 |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,865
|
Perfect timing then. Happy coding =)
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
|
|