English Amiga Board


Go Back   English Amiga Board > Coders > Coders. System > Coders. Nextgen

 
 
Thread Tools
Old 24 April 2017, 00:16   #1
patrik
Registered User
patrik's Avatar
 
Join Date: Jan 2005
Location: Umeå
Age: 37
Posts: 398
AROS startup code

Hi,

I would like to learn how to write my own startup code for AROS.

On classic AmigaOS, it is very simple - it executes the first function found in an executable file, you just need to setup SysBase before calling any exec.library functions. An hello world example with own startup code would look like this:
Code:
#include <exec/exec.h>
#include <dos/dos.h>

#include <proto/exec.h>
#include <proto/dos.h>

struct ExecBase *SysBase = NULL;
struct DosLibrary *DOSBase = NULL;

LONG Something(void) {
	SysBase = *(struct ExecBase **) 4;
	DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 36);
	if(NULL != DOSBase) {
		Printf("Hello Amiga!\n");
	}
	CloseLibrary((struct Library *) DOSBase);
	return 0;
}
Compiles with:
Code:
vc +aos68k -c99 -nostdlib -o helloamiga helloamiga.c
For MorphOS, you just need to add the __abox__ symbol, for AmigaOS4 the function needs to be named _start and have a specific signature and there is some more code required for the exec iface, but basically it is no big problem, atleast not with vbcc.

With gcc things seem a bit trickier, but it is doable - there is for example an excellent guide for writing your own startup code in MorphOS using gcc, with a complete example attached at the end.

If I try something similar on AROS and compile the above code with:
Code:
gcc -nostdlib -nostartfiles -o helloamiga helloamiga.c
I do get an executable without producing any warnings or anything, but it will crash if I try to execute it, so obviously I'm missing something required which I am unaware of.

Haven't been able to find any information similar to the MorphOS guide for AROS, so I'm hoping someone can point me in the right direction.
patrik is offline  
AdSense AdSense  
Old 24 April 2017, 23:09   #2
patrik
Registered User
patrik's Avatar
 
Join Date: Jan 2005
Location: Umeå
Age: 37
Posts: 398
Responding to myself in case someone else searches for this in the future. This is how you do it for the above example:
Code:
#include <exec/exec.h>
#include <dos/dos.h>

#include <proto/exec.h>
#include <proto/dos.h>

struct ExecBase *SysBase = NULL;
struct DosLibrary *DOSBase = NULL;

__startup AROS_PROCH(Something, arguments, argumentsLength, sysBase) {
	AROS_PROCFUNC_INIT

	SysBase = sysBase;
	DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 0);
	if(NULL != DOSBase) {
		Printf("Hello world!\n");
	}
	CloseLibrary((struct Library *) DOSBase);
	return 0;

	AROS_PROCFUNC_EXIT
}
And compile with:
Code:
gcc -nostartfiles -o helloamiga helloamiga.c

Last edited by patrik; 24 April 2017 at 23:46.
patrik is offline  
Old 28 April 2017, 18:57   #3
phx
Natteravn

phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 1,096
As you mentioned vbcc, here is the vclib startup code for the i386-aros target, which I had to abandon about 10 years ago. Maybe declaring __startup_entry as global is important for the loader, but I don't remember.

Code:
#
# vbcc/AROS386 startup
# Written by Frank Wille <frank@phoenix.owl.de> 2006
#

# Version
.set    VERSION,1
.set    REVISION,01
.macro  VBCC_VER
        .byte   "VBCC 0.9"
.endm

        .extern __cstart

        .text

        .globl  __startup_entry
__startup_entry:
# Entered with:
#  0(%esp)  return address to DOS
#  4(%esp)  argument string pointer
#  8(%esp)  argument string length
# 12(%esp)  SysBase pointer
        movl    $__save_regs,%eax
        mov     %esp,(%eax)
        mov     %ebx,4(%eax)
        mov     %ebp,8(%eax)
        mov     %esi,12(%eax)
        mov     %edi,16(%eax)
        mov     12(%esp),%eax
        mov     %eax,SysBase
        jmp     __cstart

        VBCC_VER

        .type   __startup_entry,@function
        .size   __startup_entry,.-__startup_entry


        .globl  __asmexit
__asmexit:
        mov     4(%esp),%eax
        movl    $__save_regs,%edx
        mov     (%edx),%esp
        mov     4(%edx),%ebx
        mov     8(%edx),%ebp
        mov     12(%edx),%esi
        mov     16(%edx),%edi
        ret

        .type   __asmexit,@function
        .size   __asmexit,.-__asmexit

        .byte   "startup V"
        .byte   '0'+VERSION,'.','0'+(REVISION/10),'0'+(REVISION%10),0


        .lcomm  __save_regs,20
        .comm   SysBase,4
As I am quite unexperienced in x86 assembler, I switched to C as soon as possible. Command line parsing and WB-startup follows in __cstart():
Code:
/*
** vbcc/AROS386 startup
** Written by Frank Wille <frank@phoenix.owl.de> 2006
*/
#include <dos/dosextens.h>
#include <workbench/startup.h>
#include <proto/exec.h>
#include <proto/dos.h>

struct SVar {
  BPTR WbOutput;
  char *ArgvBufPtr;
  char *ArgvArray[1];
};

struct DosLibrary *DOSBase;
struct WBStartup *WBenchMsg,*_WBenchMsg;
BPTR _stdin,_stdout,_stderr;
static struct SVar *svar;

extern void __asmexit(int);
extern void __main(int,char **);


static int strlen(__reg("%edi") const char *) =
  "\tcld\n"
  "\txor\t%eax,%eax\n"
  "\tmov\t%eax,%ecx\n"
  "\tdec\t%ecx\n"
  "\trepne\n"
  "\tscasb\n"
  "\tnot\t%ecx\n"
  "\tlea\t-1(%ecx),%eax";


void __exit(int code)
{
  if (DOSBase) {
    if (svar) {
      if (svar->WbOutput)
        Close(svar->WbOutput);
      FreeVec(svar);
    }
    CloseLibrary((struct Library *)DOSBase);
  }
  if (WBenchMsg) {
    Forbid();
    ReplyMsg((struct Message *)WBenchMsg);
  }
  __asmexit(code);
}


static void getWbMsg(struct Process *this_proc)
{
  WaitPort(&this_proc->pr_MsgPort);
  WBenchMsg = _WBenchMsg = (struct WBStartup *)GetMsg(&this_proc->pr_MsgPort);
}


static void startup_failed(struct Process *this_proc)
{
  if (!this_proc->pr_CLI)
    getWbMsg(this_proc);

  __exit(RETURN_FAIL);
}


static int command_len(void)
{
  char buf[1024];

  if (GetProgramName(buf,1024))
    return strlen(buf) + 1;
  return 0;
}


void __cstart(unsigned char *argstr,int arglen)
{
  struct Process *this_proc = (struct Process *)FindTask(NULL);
  int argc,argc_est,len;
  char **argv;
  unsigned char *p;

  if (!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",39)))
    startup_failed(this_proc);

  /* estimate number of argv-slots */
  if (this_proc->pr_CLI) {
    for (argc_est=3,len=arglen,p=argstr; len>0 && *p!='\0'; len--,p++) {
      if (*p <= ' ')
        argc_est++;
    }
    len = command_len();
  }
  else {
    argc_est = 2;  /* two dummy arguments for WB-start */
    arglen = 8;
    len = 0;
  }

  if (!(svar = AllocVec(sizeof(struct SVar) +
                        argc_est*sizeof(char *) + len + arglen + 1,
                        MEMF_PUBLIC | MEMF_CLEAR))) {
    startup_failed(this_proc);
  }
  svar->ArgvBufPtr = (char *)&svar->ArgvArray[argc_est+1];

  if (this_proc->pr_CLI) {
    /* started from CLI */
    if (len)
      GetProgramName(svar->ArgvBufPtr,len);
    argv = svar->ArgvArray;
    *argv++ = svar->ArgvBufPtr;
    svar->ArgvBufPtr += len;
    argc = 1;

    /* eat trailing control characters on command line */
    for (len=arglen,p=argstr+arglen-1; len>0 && *p<=' '; len--,p--);
    *(p+1) = '\0';

    for (p=svar->ArgvBufPtr; *argstr!='\0' && argc<argc_est; ) {
      while (*argstr!='\0' && *argstr<=' ')
        argstr++;
      if (*argstr == '\0')
        break;
      argc++;
      *argv++ = p;

      if (*argstr == '\"') {
        unsigned char c;

        argstr++;
        while ((c = *argstr++) != '\"') {
          if (c == '\0') {
            argstr--;
            break;
          }
          else if (c == '*') {  /* BCPL escape character */
            switch (c = *argstr++) {
              case '\0': argstr--; break;
              case 'N': *p++ = '\n'; break;
              case 'E': *p++ = 27; break;
              default: *p++ = c; break;
            }
          }
          else
            *p++ = c;
        }
      }
      else {
        while (*argstr > ' ')
          *p++ = *argstr++;
      }
      *p++ = '\0';
    }
    *argv = NULL;
    argv = svar->ArgvArray;

    _stdin = Input();
    _stdout = Output();
    if (!(_stderr = this_proc->pr_CES))
      _stderr = _stdout;
  }

  else {
    /* started from Workbench */
    struct WBArg *wbarg;

    getWbMsg(this_proc);
    argv = (char **)WBenchMsg;
    argc = 0;
    if (wbarg = WBenchMsg->sm_ArgList)
      CurrentDir(wbarg->wa_Lock);

    /* set I/O to NIL: */
    if (svar->WbOutput = Open("NIL:",MODE_OLDFILE))
      _stdin = _stdout = _stderr = svar->WbOutput;
    else
      startup_failed(this_proc);

    #if 0 /* @@@ how to do this under AROS ??? */
    /* set console task, so Open("*",mode) will work */
    this_proc->pr_CIS = _stdin;
    this_proc->pr_COS = _stdout;
    this_proc->pr_ConsoleTask = ...
    #endif
  }

  __main(argc,argv);  /* vclib init, call main() */
  __exit(0);          /* although __main() should never return */
}
phx is offline  
Old 29 April 2017, 19:14   #4
patrik
Registered User
patrik's Avatar
 
Join Date: Jan 2005
Location: Umeå
Age: 37
Posts: 398
Interesting!

If I would compile the 80x86 versions of vbcc and vasm, could they be used to create an aros executable for something like the helloamiga above?
patrik is offline  
Old 29 April 2017, 23:06   #5
phx
Natteravn

phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 1,096
The hello-world in your first posting could work, provided you have got the proto and inline headers of vbcc's i386-aros target.

But you will run into all sorts of problems as soon as you include the original AROS headers files, which depend on gcc-specific extensions. This was the reason I abandoned AROS support.
phx is offline  
Old 30 April 2017, 21:13   #6
patrik
Registered User
patrik's Avatar
 
Join Date: Jan 2005
Location: Umeå
Age: 37
Posts: 398
Can the protos and inlines for aros-i386 be generated with the fd2pragma which is included with vbcc?
patrik is offline  
AdSense AdSense  
 


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

Similar Threads
Thread Thread Starter Forum Replies Last Post
AROS: Stable AROS ABI_V0-20161228 AMIGASYSTEM News 19 06 January 2017 00:06
non-system startup code time/clock problem modrobert Coders. Asm / Hardware 60 11 June 2016 10:08
New Video of my Aros 68k distribution "Aros Vision" OlafSch Amiga scene 26 16 February 2016 11:16
Startup Code (from Icon ) - Forbid function Asman Coders. System 2 04 January 2014 10:45
C/C++ WB friendly fullscreen game startup code NovaCoder Coders. Tutorials 0 04 November 2011 03:49

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 06:38.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.
Page generated in 0.06234 seconds with 14 queries