View Single Post
Old 28 April 2017, 18:57   #3
phx
Natteravn

phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 1,689
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  
 
Page generated in 0.04313 seconds with 11 queries