English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 12 December 2015, 16:41   #1
sodapop
Registered User
 
sodapop's Avatar
 
Join Date: Oct 2010
Location: France
Posts: 99
movem.l d0-d7/a0-a6,-(SP) inside a subroutine ?

Hi !

Could someone with a better knowledge than mine explain me why a "movem.l d0-d7/a0-a6,-(SP)" inside my SAVE_ALL subroutine will cause a guru, whereas it will work ok when outside the subroutine (put in between "bsr SAVE_ALL" and "bsr InitMusic"). BTW, don't pay any attention at my code pertinency (only for testing purposes !)
Thank you !

Code:
    move.l $4,a6
    lea gfxname,a1
    jsr -408(a6)
    move.l d0,a1

    bsr SAVE_ALL
    bsr InitMusic
    bsr RESTORE_ALL
    rts

InitMusic:
    move.w #%1000001000001111,$dff096    ; DMA Sound
    bsr mt_init
VBL:    
    move.l    $dff004,d7
    and.l    #$1ff00,d7
    cmp.l    #303<<8,d7
    bne.s    VBL
    bsr mt_music
    btst #6,$bfe001
    bne.s VBL
    bsr mt_end    
    rts

SAVE_ALL:
    move.l $26(a1),old_COP1        ; save old copperlist 1
    move.l $32(a1),old_COP2        ; save old copperlist 2
    jsr -414(a6)            ; close lib

    move.w $DFF01c,old_IRQ        ; Save IRQ enable flags
    move.w $DFF002,old_DMA        ; Save DMACON register

    move.w #%0111111111111111,$DFF09a    ; Disable IRQs
    move.w #%0111111111111111,$DFF096    ; Disable DMAs
    movem.l d0-d7/a0-a6,-(SP)
    rts
    
RESTORE_ALL:
    move.l old_COP1,$DFF080        ; restore copperlist 1
    move.l old_COP2,$DFF084        ; restore copperlist 2
    move.w old_DMA,d0        ; restore dma control register
    ori.w #$8000,d0            ; Set high bit to enable 'set'
    move.w d0,$DFF096        ; Re-enable DMAs

    move.w old_IRQ,d0        ; Restore IRQ enabled register
    ori.w #$8000,d0
    move.w d0,$DFF09a        ; Re-enable IRQs
    movem.l (SP)+,d0-d7/a0-a6
    rts

gfxname:
    dc.b "graphics.library",0
    even

old_COP1: ds.l 1
old_COP2: ds.l 1
old_IRQ: ds.w 1
old_DMA: ds.w 1

Last edited by sodapop; 12 December 2015 at 16:47.
sodapop is offline  
Old 12 December 2015, 16:57   #2
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,997
Quote:
Originally Posted by sodapop View Post
Hi !

Could someone with a better knowledge than mine explain me why a "movem.l d0-d7/a0-a6,-(SP)" inside my SAVE_ALL subroutine will cause a guru, whereas it will work ok when outside the subroutine (put in between "bsr SAVE_ALL" and "bsr InitMusic"). BTW, don't pay any attention at my code pertinency (only for testing purposes !)
Thank you !

Code:
    move.l $4,a6
    lea gfxname,a1
    jsr -408(a6)
    move.l d0,a1

    bsr SAVE_ALL
    bsr InitMusic
    bsr RESTORE_ALL
    rts

InitMusic:
    move.w #%1000001000001111,$dff096    ; DMA Sound
    bsr mt_init
VBL:    
    move.l    $dff004,d7
    and.l    #$1ff00,d7
    cmp.l    #303<<8,d7
    bne.s    VBL
    bsr mt_music
    btst #6,$bfe001
    bne.s VBL
    bsr mt_end    
    rts

SAVE_ALL:
    move.l $26(a1),old_COP1        ; save old copperlist 1
    move.l $32(a1),old_COP2        ; save old copperlist 2
    jsr -414(a6)            ; close lib

    move.w $DFF01c,old_IRQ        ; Save IRQ enable flags
    move.w $DFF002,old_DMA        ; Save DMACON register

    move.w #%0111111111111111,$DFF09a    ; Disable IRQs
    move.w #%0111111111111111,$DFF096    ; Disable DMAs
    movem.l d0-d7/a0-a6,-(SP)
    rts
    
RESTORE_ALL:
    move.l old_COP1,$DFF080        ; restore copperlist 1
    move.l old_COP2,$DFF084        ; restore copperlist 2
    move.w old_DMA,d0        ; restore dma control register
    ori.w #$8000,d0            ; Set high bit to enable 'set'
    move.w d0,$DFF096        ; Re-enable DMAs

    move.w old_IRQ,d0        ; Restore IRQ enabled register
    ori.w #$8000,d0
    move.w d0,$DFF09a        ; Re-enable IRQs
    movem.l (SP)+,d0-d7/a0-a6
    rts

gfxname:
    dc.b "graphics.library",0
    even

old_COP1: ds.l 1
old_COP2: ds.l 1
old_IRQ: ds.w 1
old_DMA: ds.w 1
Return from bsr is trashed by movem command. You must use both movem in same subroutine.
Don_Adan is offline  
Old 12 December 2015, 17:19   #3
sodapop
Registered User
 
sodapop's Avatar
 
Join Date: Oct 2010
Location: France
Posts: 99
Wow ! totally beyond my comprehension...
sodapop is offline  
Old 12 December 2015, 17:46   #4
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,997
Quote:
Originally Posted by sodapop View Post
Wow ! totally beyond my comprehension...
bsr/jsr put return address (longword) on stack.
rts reads first longword from stack.
Don_Adan is offline  
Old 12 December 2015, 19:48   #5
sodapop
Registered User
 
sodapop's Avatar
 
Join Date: Oct 2010
Location: France
Posts: 99
Thank you Don Adan, that makes sense now !
sodapop is offline  
Old 14 December 2015, 22:57   #6
sodapop
Registered User
 
sodapop's Avatar
 
Join Date: Oct 2010
Location: France
Posts: 99
Ok, I found out that a ADD.L #60,SP / SUB.L #60,SP before their respective RTS solved the problem (15 registers saved and restored x 4 bytes = 60)... stupid me !
sodapop is offline  
Old 15 December 2015, 10:19   #7
demolition
Unregistered User
 
demolition's Avatar
 
Join Date: Sep 2012
Location: Copenhagen / DK
Age: 43
Posts: 4,190
I'm no expert on 68k asm, but that sounds like kind of a hack.
demolition is offline  
Old 15 December 2015, 10:21   #8
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,627
Quote:
Originally Posted by demolition View Post
I'm no expert on 68k asm, but that sounds like kind of a hack.
agreed :-)

this is the sort of thing that will come back and bite you, once your attention is not pointing to this 100%..
hooverphonique is offline  
Old 15 December 2015, 10:47   #9
sodapop
Registered User
 
sodapop's Avatar
 
Join Date: Oct 2010
Location: France
Posts: 99
I'm not a 68k expert by any means neither ! But for now, I can't see any reasons why this could go wrong... I only assumed the "return address" kept its place in the stack... and I'm quite an optimistic guy
sodapop is offline  
Old 15 December 2015, 10:54   #10
demolition
Unregistered User
 
demolition's Avatar
 
Join Date: Sep 2012
Location: Copenhagen / DK
Age: 43
Posts: 4,190
After doing the ADD.L instruction, your saved registers might get overwritten by some other instruction which puts stuff on the stack.

I think this kind of operation is better suited for a macro, thus you won't need to use BSR/RTS. This also allows the content to remain on the stack.

Alternatively you can copy the return address 60 bytes ahead in the stack instead of doing ADD.L. Also a hack, but a bit safer.
Edit: You'd probably want to remove the orphan address as well - but generally it is not good practice to do direct stack manipulation unless you really need to.
demolition is offline  
Old 15 December 2015, 11:13   #11
sodapop
Registered User
 
sodapop's Avatar
 
Join Date: Oct 2010
Location: France
Posts: 99
@demolition: yeah, you're probably right
sodapop is offline  
Old 15 December 2015, 18:42   #12
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
But, why would you want to do it like that?

I mean, the normal is to save regs at the beginning of a subroutine and restore them at exit

Code:
superduperSubroutine:
	movem.l d0-d7/a0-a6,-(sp)
	bla-bla subroutine staff here
	bla-bla more
	bla-bla
	movem.l (sp)+,d0-d7/a0-a6
	rts
...or you can move the saving/restoring to the caller...
Code:
	...
	...
	movem.l d0-d7/a0-a6,-(sp)
	bsr	anothersuperdupersubroutine
	movem.l (sp)+,d0-d7/a0-a6
	...
	...
If you really want to save in one routine and restore to another you could instead of the stack use a memory location

Code:
	;; save regs wherever you want
	movem.l d0-d7/a0-a6,saveregs


	;; restore regs wherever you want
	movem.l saveregs,d0-d7/a0-a6

	
	section foo,data
	;; hold space for 15 registers
saveregs:	ds.l 15
alkis is offline  
Old 15 December 2015, 21:28   #13
sodapop
Registered User
 
sodapop's Avatar
 
Join Date: Oct 2010
Location: France
Posts: 99
Quote:
Originally Posted by alkis View Post
But, why would you want to do it like that?
It was for testing purposes, as I said in my 1st post.
I tried to do it with the maximum of modularity and versatility, with the main part consisting in BSR/RTS only...
sodapop is offline  
Old 16 December 2015, 00:33   #14
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,269
As long as you allocate, use, and deallocate, in the right order, it doesn't really matter.

One thing that could be good to know if you're playing with the stack like this: Exec uses your own stack when it switches tasks, so if you ever make multi-tasking programs then you can't use A7 as a general purpose register, it must always point to the top of your stack.

In your example here it's not necessary to save any registers, neither for the CLI nor the Workbench, you only need to remember to pass a return value in D0 for CLI programs, typically 0.
Leffmann is offline  
Old 16 December 2015, 16:33   #15
sodapop
Registered User
 
sodapop's Avatar
 
Join Date: Oct 2010
Location: France
Posts: 99
@Leffmann: thank you for the enlightment. The purpose was only to put some "context saving" lines in a single subroutine (including "movem.l d0-d7..."). Need to put other things into it also, like the usual forbid to avoid multitasking, and so on...
sodapop is offline  
Old 18 December 2015, 18:45   #16
Mrs Beanbag
Glastonbridge Software
 
Mrs Beanbag's Avatar
 
Join Date: Jan 2012
Location: Edinburgh/Scotland
Posts: 2,243
Quote:
Originally Posted by demolition View Post
Alternatively you can copy the return address 60 bytes ahead in the stack instead of doing ADD.L. Also a hack, but a bit safer.
Edit: You'd probably want to remove the orphan address as well - but generally it is not good practice to do direct stack manipulation unless you really need to.
I don't personally see anything wrong with this sort of thing, although the specific example is a strange use case for it. I often push the address of error handling routines onto the stack. Really that's no different from passing a function pointer as a stack-based parameter, like you can do in C.
Mrs Beanbag is offline  
Old 18 December 2015, 18:58   #17
demolition
Unregistered User
 
demolition's Avatar
 
Join Date: Sep 2012
Location: Copenhagen / DK
Age: 43
Posts: 4,190
What I mean is that when you put stuff on the stack, make sure it is always pulled off again and in the intended order. Doing more advanced stack manipulation can be fine, but better think properly about it when it is implemented to make sure you don't get any unintended issues.

If you push the address of the error-handling routine (and maybe some parameters) on the stack it should never cause problems as long as the error handler cleans up whatever was put for it on the stack.
demolition is offline  
Old 18 December 2015, 19:14   #18
Mrs Beanbag
Glastonbridge Software
 
Mrs Beanbag's Avatar
 
Join Date: Jan 2012
Location: Edinburgh/Scotland
Posts: 2,243
yes indeed. a subroutine that puts stuff on the stack and leaves it there when it returns is a very strange and dangerous beast.
Mrs Beanbag is offline  
Old 18 December 2015, 20:03   #19
frank_b
Registered User
 
Join Date: Jun 2008
Location: Boston USA
Posts: 466
Quote:
Originally Posted by Mrs Beanbag View Post
yes indeed. a subroutine that puts stuff on the stack and leaves it there when it returns is a very strange and dangerous beast.
The only valid use case is a C function which takes the address of a local to calculate how much of the stack is free. Ie returning the address of a local variable is insane otherwise
frank_b is offline  
Old 18 December 2015, 20:32   #20
Mrs Beanbag
Glastonbridge Software
 
Mrs Beanbag's Avatar
 
Join Date: Jan 2012
Location: Edinburgh/Scotland
Posts: 2,243
yes, although we are not talking about returning the address of a local variable, but a function not leaving the stack in the same place it found it when it returns*, which means if the caller is doing relative (SP) addressing to access its own local variables, it will go completely out of whack and do nasty things.

Unless you have some specific, strict coding style that handles this sort of thing, i've thought before about what if you want a function to return an object whose size isn't known to the caller and might not be a constant... but i can't think of a neat way to do that anyway without using two stacks.

(*which is impossible for a C function anyway)

Quote:
Originally Posted by Leffmann View Post
One thing that could be good to know if you're playing with the stack like this: Exec uses your own stack when it switches tasks, so if you ever make multi-tasking programs then you can't use A7 as a general purpose register, it must always point to the top of your stack.
now that is good to know, it also means you shouldn't keep any temporary data before the stack pointer, because it could get written over at any point.

Last edited by Mrs Beanbag; 18 December 2015 at 22:21.
Mrs Beanbag is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Inside the Amiga Washac support.Hardware 14 19 February 2010 17:52
movem in debugger Ratte support.WinUAE 2 15 August 2009 23:10
Movem Pickout Amiga fun issue 06 AliasXZ support.Games 0 12 August 2009 00:32
Something like Movem MarlboroMan Looking for a game name ? 2 10 October 2004 12:47
Movem & 3D Motorrad (Amiga Mania) andreas request.Old Rare Games 6 26 September 2004 01:29

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 05:26.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10318 seconds with 15 queries