English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 23 December 2013, 21:22   #1
copse
Registered User
 
Join Date: Jul 2009
Location: Lala Land
Posts: 520
Executables and initial register values

I posted in another thread about my experiments with vamos/amitools. One of the things I've come up against, is a reliance by a C program on something I haven't found documented.

Specifically, the "main" executable from Pools of Radiance does the following:
Code:
movem.l    D1-D6/A0-A6, -(SP)
...
move.l      SP, D0
sub.l        4(SP), D0
...
move.l      D0, (hSPLower-DT,A4)
Now, it is documented that 4(SP) is the stack size. But the movem clobbers the initial stack address, and in turn moves the stack back a long word, places A6, moves the stack back long word, places A5 ............ moves the stack back a long word, places D6, .......... moves the stack back a long word, places D2, moves the stack back a long word, places D1.

So by what I assume is complete coincidence, the C compiler writer does not bother to save D0, leaving D1 at 0(SP) and D2 at 4(SP). And Amiga OS from 1.2 to 3.1 happen to have the stack size in D2.

Thoughts?
copse is offline  
Old 24 December 2013, 00:52   #2
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,269
I don't think it's a coincidence, the programmers probably found it to be the case on all versions of AmigaOS they tested and just assumed it would always work. It may not be the case on later versions of Dos and Exec, and it only works on the command line, not if you run from Workbench.

The only registers and values that are defined and reliable are, when on the command line, A0, pointer to the command string, and D0, the length of the command string.
Leffmann is offline  
Old 24 December 2013, 01:50   #3
copse
Registered User
 
Join Date: Jul 2009
Location: Lala Land
Posts: 520
Quote:
Originally Posted by Leffmann View Post
I don't think it's a coincidence, the programmers probably found it to be the case on all versions of AmigaOS they tested and just assumed it would always work. It may not be the case on later versions of Dos and Exec, and it only works on the command line, not if you run from Workbench.
Hmm. What OS calls are involved to run from Workbench? I'd like to look into this, but it's been so long that I do not recall what is involved.

Note that Pool of Radiance has a hard drive installer. This executable relies on D2 providing the stack size both when started from DOS, and from Workbench.

Quote:
Originally Posted by Leffmann View Post
The only registers and values that are defined and reliable are, when on the command line, A0, pointer to the command string, and D0, the length of the command string.
Quote:
Originally Posted by AmigaDOS Developer's Manual (1985)
AmigaDOS pushes a suitable return address onto the stack that tells the CLI to regain control and unload your program. Below this on the stack at 4(SP) is the size of the stack in bytes, which may be useful if you wish to perform stack checking.
And that is what the C program is doing, stack checking. Albeit I assume incompetently in a way that happens to work through coincidence.

Last edited by copse; 24 December 2013 at 01:52. Reason: Year for manual.
copse is offline  
Old 24 December 2013, 21:43   #4
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Quote:
Originally Posted by copse View Post
... the C compiler writer does not bother to save D0, leaving D1 at 0(SP) and D2 at 4(SP). And Amiga OS from 1.2 to 3.1 happen to have the stack size in D2.

Thoughts?
It's my understanding that AmigaShell expects the return code of the program in D0 (RC)...so, unless I missread you, the C compiler writer correctly doesn't save D0.
alkis is offline  
Old 24 December 2013, 22:33   #5
copse
Registered User
 
Join Date: Jul 2009
Location: Lala Land
Posts: 520
This is about the other side of the coin, the registers that are provided when the program starts. e.g. A0 for argument strings, D0 for argument count, 4(SP) for stack size, and perhaps D2 for stack size unofficially.
copse is offline  
Old 25 December 2013, 14:56   #6
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,269
Quote:
Originally Posted by copse View Post
Hmm. What OS calls are involved to run from Workbench? I'd like to look into this, but it's been so long that I do not recall what is involved.
In short, FindTask, WaitPort, GetMsg, Forbid and ReplyMsg. FindTask can be omitted if you want to get your task pointer from inside execbase instead.

Quote:
Originally Posted by copse View Post
Note that Pool of Radiance has a hard drive installer. This executable relies on D2 providing the stack size both when started from DOS, and from Workbench.
That's a mistake then, because as far as CPU registers goes A0 and D0 will be set as discussed, and that's it. Other registers are officially undefined, and if you run from Workbench then all registers are undefined (unless you use the CLI tooltype under 2.0 or later).
Leffmann is offline  
Old 01 January 2014, 21:09   #7
copse
Registered User
 
Join Date: Jul 2009
Location: Lala Land
Posts: 520
Quote:
Originally Posted by Leffmann View Post
In short, FindTask, WaitPort, GetMsg, Forbid and ReplyMsg. FindTask can be omitted if you want to get your task pointer from inside execbase instead.



That's a mistake then, because as far as CPU registers goes A0 and D0 will be set as discussed, and that's it. Other registers are officially undefined, and if you run from Workbench then all registers are undefined (unless you use the CLI tooltype under 2.0 or later).
You're right. I went back and checked the code, and it does something like:

Code:
    move.l ThisTask(A6), A3
    tst.l    pr_CLI(A3)
    beq.b  wbstartup
...
wbstartup:
    move.l pr_Task+TC_SPLOWER(A3), splower
Which would work fine for hd installs and whatnot.
copse is offline  
Old 10 May 2021, 19:23   #8
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
From what I remember there is a complete BCPL environment available for executables launched from the CLI.
I have no idea if the 3.1.4 ROMs continue to support it, but it was until 3.1 OS.
Some legacy TripOS commands from AmigaDos 1.x still used the environment, only to be deprecated (rightly..) by version 2.x.
Code:
INITIAL ENVIRONMENT

        Upon entry to any BCPL routine, the register contents are as follows:

        d0 - amount of global area currently in use
        d1-d4 - up to 4 parameters.  Further parameters can be passed on
                the stack (see below).
        d5-d7 - unused
        a0 - base of system address space - always 0.
                RAM addresses are computed as offsets from a0
        a1 - base of the current BCPL stack frame
        a2 - pointer to the BCPL Global Vector
        a3 - return address of the caller
        a4 - entry address
        a5 - pointer to a "caller" service routine
        a6 - pointer to a "returner" service routine
        a7 - stack for temporaries

        This register environment is available to any application program.
Not all parameters are available, also because it would not make sense to do so, and they have been reused by the CLI environment for passing parameters from the command line:
Code:
The parameters passed by the CLI to an application are:
        d0 - length of command line
        a0 - APTR to command line
The command itself may be found in the CLI->cli_Command field.
In practice all the Dx registers are useless (apart from the new use of D0) because the parameters are passed from the command line.
But interesting is that D1-D4, unused and unusable parameters, are still saved in the current BCPL stack frame (A1).
A0 instead of having the value 0, used in the ancient environment for funny addressing mode like (A0=0, Dx), with Dx=mem_address or BPTR (and this explains the absurd way of AmigaDos to have as parameters the addresses in the data registers..), is used for an APTR to command line.
The other values of the address registers retain their original function, apart from A3 and A4 which are 'scratch registers' and used by service routines.
Interesting is that A3 is used by practically all ROMs as a jump register within the starting hunk and some crunchers had used it for their purposes, but it was just a coincidence because it was one of the scratch registers available.
And in fact for AROS ROMs this is not true and there have been compatibility problems.

A long time ago I also tried to figure out if the initial setting of these registers could have any use for a generic program, but no, I couldn't even find a way to use them to get the base of dos.library without using OpenLibrary() from Exec..

So forget it and just use D0 and A0
ross is offline  
Old 23 June 2022, 14:04   #9
hop
Registered User
 
Join Date: Apr 2019
Location: UK
Posts: 172
Sorry to resurrect this old thread, but it seems related.

I just read in the Amiga Guru Book (p574) that for CLI programs:

Quote:
None of the register contents (with the possible exception of the stack pointer) need be preserved by the program and therefore need not be restored upon return.
I never realised this. I think I got in to a habit of doing this years ago after following a tutorial and it has stuck:

Code:
	movem.l	d1-d7/a0-a6,-(a7)
	<program>
	movem.l	(a7)+,d1-d7/a0-a6	
	moveq	#0,d0
	rts
I guess the same applies to programs launched from Workbench, and the only time it makes sense to preserve registers in a program is if you are going to
jsr
into it from your own code and need to respect calling conventions.
hop is offline  
Old 23 June 2022, 14:39   #10
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Quote:
Originally Posted by ross View Post

A long time ago I also tried to figure out if the initial setting of these registers could have any use for a generic program, but no, I couldn't even find a way to use them to get the base of dos.library without using OpenLibrary() from Exec..

So forget it and just use D0 and A0
Well, we found this when squeezing for the pi computation.

lea -$148(a2),a6 ; dos library from bcpl vector
alkis is offline  
Old 23 June 2022, 14:39   #11
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Quote:
Originally Posted by hop View Post
Sorry to resurrect this old thread, but it seems related.

I just read in the Amiga Guru Book (p574) that for CLI programs:



I never realised this. I think I got in to a habit of doing this years ago after following a tutorial and it has stuck:

Code:
	movem.l	d1-d7/a0-a6,-(a7)
	<program>
	movem.l	(a7)+,d1-d7/a0-a6	
	moveq	#0,d0
	rts
I guess the same applies to programs launched from Workbench, and the only time it makes sense to preserve registers in a program is if you are going to
jsr
into it from your own code and need to respect calling conventions.
That's correct.
alkis 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
The lesser-known Initial Chip Set (ICS) mystery andreas support.Hardware 26 17 July 2013 02:39
convert Color register values to html colors ?? Joe Maroni Coders. General 29 28 October 2010 07:04
Is there a way of creating "snapshot" executables? MethodGit Amiga scene 7 24 October 2010 22:14
Best games by initial letter alkis21 Nostalgia & memories 80 18 January 2008 23:32
Avoid ROM check on initial use Amichem support.WinUAE 4 04 October 2007 15:58

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 14:53.

Top

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