06 April 2019, 11:03 | #1 |
Registered User
Join Date: Aug 2016
Location: germany
Posts: 67
|
amiga-gcc minimal output
Hello,
i'm using amiga-gcc from bebbo on a linux-machine. with this i'm trying to create a simple program using only amiga-native calls and making it as small and clean as possible. i compile with Code:
m68-amigaos-gcc -noixemul -s -g0 -O2 -m68020 main.c but i noticed that the output still contains more than my code (i just had a look at the hex-dump).. and i also saw that all libraries i open manually are in the output 2 times (like dos.library, mathieeedoubbas.lib.. etc). so it seems that the gcc adds the libs again although i want to do this. what am i doing wrong? or is there an extra option to avoid this? here is my main.c: Code:
#define __NOLIBBASE__ #include <proto/exec.h> #include <proto/dos.h> #include <proto/mathieeesingbas.h> #include <proto/mathieeedoubbas.h> #include <proto/mathieeedoubtrans.h> int __nocommandline=1; int __initlibraries=0; // needed for RawDoFmt: STATIC CONST ULONG StuffChar[] = { 0x16c04e75 }; struct ExecBase *SysBase; struct DosLibrary *DOSBase; struct MathIEEEBase *MathIeeeSingBasBase; struct MathIEEEBase *MathIeeeDoubBasBase; struct MathIEEEBase *MathIeeeDoubTransBase; int main(void) { int rc = 0; ULONG freemem = 0; char text[20]; ULONG array[2]; //-------------------------------------------------- SysBase = *((struct ExecBase **)4); DOSBase = (struct DosLibrary *) OpenLibrary("dos.library",0); MathIeeeSingBasBase = (struct MathIEEEBase *) OpenLibrary("mathieeesingbas.library", 0); MathIeeeDoubBasBase = (struct MathIEEEBase *) OpenLibrary("mathieeedoubbas.library", 0); MathIeeeDoubTransBase = (struct MathIEEEBase *) OpenLibrary("mathieeedoubtrans.library", 0); if ((DOSBase) && (MathIeeeSingBasBase) && (MathIeeeDoubBasBase) && (MathIeeeDoubTransBase)) { while (!(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)) { freemem = AvailMem(MEMF_CHIP); array[0] = (ULONG) freemem; /* create output-string */ (void) RawDoFmt("Chip: %10ld", &array, (void (*)(void))&StuffChar, text ); ... Delay(50*2); } } else { Printf("failed to open libraries!!!\n"); rc = RETURN_FAIL; } if (MathIeeeDoubTransBase) { CloseLibrary((struct Library *) MathIeeeDoubTransBase); } if (MathIeeeDoubBasBase) { CloseLibrary((struct Library *) MathIeeeDoubBasBase); } if (MathIeeeSingBasBase) { CloseLibrary((struct Library *) MathIeeeSingBasBase); } if (DOSBase) { CloseLibrary((struct Library *) DOSBase); } return rc; } |
06 April 2019, 11:13 | #2 |
Registered User
Join Date: Jan 2002
Location: Germany
Posts: 6,985
|
I think the option you seek is -nostdlib. Without you still get the ANSI C library. This has nothing to do with AmigaOS libraries, it contains functions such as strcpy and so on.
BTW, your program will crash if dos.library fails to open because then you call Printf which is part of dos.library. |
06 April 2019, 16:56 | #3 | ||
Registered User
Join Date: Aug 2016
Location: germany
Posts: 67
|
Quote:
now i run into problems like this: Code:
/opt/amiga/lib/gcc/m68k-amigaos/6.5.0b/../../../../m68k-amigaos/bin/ld: /tmp/ccUk9VnM.ltrans0.ltrans.o:(.text+0x56e): undefined reference to `__floatunsisf' /opt/amiga/lib/gcc/m68k-amigaos/6.5.0b/../../../../m68k-amigaos/bin/ld: /tmp/ccUk9VnM.ltrans0.ltrans.o:(.text+0x57a): undefined reference to `__muldf3' so i can not use something like float x = 1.623 * (float) y ? i need to pick the multiplication routine from mathieee.. lib ? Quote:
|
||
06 April 2019, 18:21 | #4 |
Semi-Retired
Join Date: Mar 2012
Location: Leiden / The Netherlands
Posts: 1,993
|
|
06 April 2019, 18:54 | #5 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
I don't know if it's possible opening dos library with required version of 0 to ever be able to fail. (Maybe when you don't have any memory left)
If you fail to open it though, you have (at least) two options: 1) #define THISPROC ((struct Process *)(SysBase->ThisTask)) #define Result2(x) THISPROC->pr_Result2 = x Result2(ERROR_INVALID_RESIDENT_LIBRARY); Not very visible to user. 2) Alert( AG_OpenLib | AO_DOSLib ); Pretty visible to user (with magic numbers with no meaning ofc) To still be able to "pull" standard functions (like strlen) you can go with -nostartfiles at linking instead of -nostdlib. Further to make your executable even more clean and mean you could not have any globals at all and allocate them on the heap. (thus having it "pure" and re-entrantable. you can have it resident) Something like that Code:
#include <proto/exec.h> #include <proto/dos.h> #include <exec/alerts.h> #include <string.h> struct globals { struct ExecBase *SysBase; struct DosLibrary *DOSBase; BPTR Stdout; }; #define SysBase gv->SysBase #define DOSBase gv->DOSBase STATIC const ULONG tricky=0x16c04e75; /* move.b d0,(a3)+ ; rts */ VOID myprintf(struct globals *gv, char *fmt,...) { unsigned char buf[256]; STRPTR *arg = (STRPTR *)(&fmt+1); RawDoFmt((STRPTR) fmt, arg, (void (*)())&tricky, buf); Write(gv->Stdout, buf, strlen((char *)buf)); } #undef SysBase #undef DOSBase int foo() { struct ExecBase *SysBase = (*((struct ExecBase **) 4)); struct globals *gv; if (!(gv=AllocMem(sizeof(struct globals), MEMF_ANY))) { Alert( AG_NoMemory ); return 20; } struct DosLibrary *DOSBase = (struct DosLibrary *)OpenLibrary((STRPTR)"dos.library",33); if (!DOSBase) { FreeMem(gv, sizeof(struct globals)); Alert( AG_OpenLib | AO_DOSLib ); return 20; } gv->SysBase = SysBase; gv->Stdout = Output(); gv->DOSBase = DOSBase; float x = 1.623 * (float) 100; myprintf(gv, "Just a hello world. If you cast x to integer is: %ld\n", (int)x); FreeMem(gv, sizeof(struct globals)); CloseLibrary((struct Library *) DOSBase); return 0; } Attached you can find a buildable make based sample. |
06 April 2019, 19:49 | #6 |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
|
Thomas answers so well and straight to the point. So I'm sure you're past this point but for what it's worth.
Here is the general information about Printf - see notes about default output as if it's not executed from a CLI/Shell window you have to open a window (to have something to print to, not really related to which Printf you prefer), and the length bug. Opening resources as you need them is best practice, and sometimes you don't see how they'd fail but you check anyway. If size requirements are very tight such as for an intro for an artificial size limit, some wisely selected checks as for opening dos.library might be skipped due to the "platform" - it's more or less expected that you've found all the ways to remove anything extraneous for it to impress for its size. In that hacky spirit, when the binary is ready for release, you can remove the 0 longword ending the hunk in a hex editor to save 4 bytes. |
06 April 2019, 20:30 | #7 |
Registered User
Join Date: Aug 2016
Location: germany
Posts: 67
|
thank you all for the good advice!
i will try the approach from alkis .. this "global"-idea was new to me.. the code itself is not for an intro or something as great.. it just a small programm that should read some sensor-data, process it and generate an output... this is why i need float-support, (maybe) dos-lib and for sure the RawDoFmt processing... have not yet figured out how to handle the floats right.. but i will .. for sure |
07 April 2019, 02:14 | #8 | |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
Quote:
amiga libraries (gcc integrated support). I've included a line that does float multiplication. It just can't print them, cause RawDoFmt hasn't any float support. If you want to print your floats then the libc and standard stdio's printf will do the trick. |
|
07 April 2019, 04:04 | #9 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
|
07 April 2019, 10:34 | #10 | |
Registered User
Join Date: Aug 2016
Location: germany
Posts: 67
|
Quote:
Code:
volatile int y = 32; float x = 1.623 * (float) y; i added this after the dos-opening inside the main routine: Code:
struct MathIEEEBase *MathIeeeSingBasBase = (struct MathIEEEBase *)OpenLibrary((STRPTR)"mathieeesingbas.library",0); struct MathIEEEBase *MathIeeeDoubBasBase = (struct MathIEEEBase *)OpenLibrary((STRPTR)"mathieeedoubbas.library",0); struct MathIEEEBase *MathIeeeDoubTransBase = (struct MathIEEEBase *)OpenLibrary((STRPTR)"mathieeedoubtrans.library",0); 00000000 00 00 03 f3 00 00 00 00 00 00 00 03 00 00 00 00 |................| 00000010 00 00 00 02 00 00 00 a0 00 00 00 18 00 00 00 02 |................| 00000020 00 00 03 e9 00 00 00 a0 4e f9 00 00 00 dc 00 00 |........N.......| 00000030 16 c0 4e 75 4e 55 ff 00 48 e7 30 3a 28 6d 00 08 |..NuNU..H.0m..| 00000040 2c 5c 20 6d 00 0c 43 ed 00 10 47 ed ff 00 45 fa |,\ m..C...G...E.| 00000050 ff e0 4e ae fd f6 26 2c 00 04 24 0b 2f 0b 4e b9 |..N...&,..$./.N.| 00000060 00 00 02 3c 2c 54 22 03 26 00 4e ae ff d0 4c ed |...<,T".&.N...L.| 00000070 5c 0c fe e8 4e 5d 4e 75 64 6f 73 2e 6c 69 62 72 |\...N]Nudos.libr| 00000080 61 72 79 00 6d 61 74 68 69 65 65 65 73 69 6e 67 |ary.mathieeesing| 00000090 62 61 73 2e 6c 69 62 72 61 72 79 00 6d 61 74 68 |bas.library.math| 000000a0 69 65 65 65 64 6f 75 62 62 61 73 2e 6c 69 62 72 |ieeedoubbas.libr| 000000b0 61 72 79 00 6d 61 74 68 69 65 65 65 64 6f 75 62 |ary.mathieeedoub| 000000c0 74 72 61 6e 73 2e 6c 69 62 72 61 72 79 00 4a 75 |trans.library.Ju| 000000d0 73 74 20 61 20 68 65 6c 6c 6f 20 77 6f 72 6c 64 |st a hello world| ... 00000280 20 2f 00 08 22 2f 00 0c 4e ae ff 9a 2c 5f 4e 75 | /.."/..N...,_Nu| 00000290 6d 61 74 68 69 65 65 65 64 6f 75 62 62 61 73 2e |mathieeedoubbas.| 000002a0 6c 69 62 72 61 72 79 00 00 00 03 ec 00 00 00 07 |library.........| 000002b0 00 00 00 00 00 00 00 02 00 00 00 38 00 00 01 6c |...........8...l| ... 00000310 00 00 00 00 00 00 02 68 00 00 00 00 00 00 00 2c |.......h.......,| 00000320 00 00 00 00 00 00 00 48 6d 61 74 68 69 65 65 65 |.......Hmathieee| 00000330 64 6f 75 62 74 72 61 6e 73 2e 6c 69 62 72 61 72 |doubtrans.librar| 00000340 79 00 00 00 6d 61 74 68 69 65 65 65 73 69 6e 67 |y...mathieeesing| 00000350 62 61 73 2e 6c 69 62 72 61 72 79 00 00 00 03 ec |bas.library.....| Last edited by Fook42; 07 April 2019 at 10:42. |
|
07 April 2019, 15:47 | #11 |
Registered User
Join Date: Aug 2016
Location: germany
Posts: 67
|
one more thing i found out:
if i declare the math-libs globally nothing changes about the double-opening. but (!) if i declare them globally AND set them to NULL there, only my openlib-calls will be used and i dont see the libs twice in the output-binary. with this "solution" i will save ~150Byte .. because of not having double-initialization of libraries. |
10 April 2019, 18:12 | #12 |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 680
|
My thoughts:
* I would not check for success after opening DOSBase, it's there, unless you specify a futile version, but 33 is always sufficient. * You could spare the AllocMem/FreeMem by using a global variable and it ends up in BSS. * use __entrypoint at your start function to omit push/pop of registers. Here you go: Code:
#include <proto/exec.h> #include <proto/dos.h> #include <exec/alerts.h> #include <string.h> struct globals { struct ExecBase *SysBase; struct DosLibrary *DOSBase; BPTR Stdout; } __g = {0}; // needed here to open/close libs __asm(".equ _SysBase, __g"); __asm(".equ _DOSBase, __g+4"); // needed everywhere ->put into header #define SysBase gv->SysBase #define DOSBase gv->DOSBase STATIC const ULONG tricky=0x16c04e75; /* move.b d0,(a3)+ ; rts */ VOID myprintf(struct globals *gv, char *fmt,...) { unsigned char buf[256]; STRPTR *arg = (STRPTR *)(&fmt+1); RawDoFmt((STRPTR) fmt, arg, (void (*)())&tricky, buf); Write(gv->Stdout, buf, strlen((char *)buf)); } __entrypoint int foo() { struct globals *gv = (struct globals *)&__g; SysBase = (*((struct ExecBase **) 4)); DOSBase = (struct DosLibrary *)OpenLibrary((STRPTR)"dos.library",33); gv->Stdout = Output(); float x = 1.623 * (float) 100; myprintf(gv, "Just a hello world. if you cast x to integer is: %ld\n", (int)x); CloseLibrary((struct Library *) DOSBase); return 0; } Last edited by bebbo; 10 April 2019 at 18:52. Reason: added da code |
01 May 2019, 11:17 | #13 |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 680
|
To get back to that: In my opinion, the simplest and most convenient way to get a tiny executable is the following:
The startup code Code:
#include <proto/exec.h> extern int main(void); extern void __initlibraries(); extern void __exitlibraries(); APTR __sp; register APTR __stkptr __asm("sp"); struct ExecBase * SysBase; __entrypoint int __startup(void) { asm("lea ___a4_init,a4"); __sp = __stkptr; SysBase = (*((struct ExecBase **) 4)); __initlibraries(); return main(); } static __attribute__((noinline)) void ___exit(int rc __asm("d0")) { __stkptr = __sp; } void exit(int rc) { __exitlibraries(); ___exit(rc); } Code:
#include <proto/dos.h> #include <string.h> extern void exit(int); BPTR Stdout; int N = 100; STATIC const ULONG tricky=0x16c04e75; /* move.b d0,(a3)+ ; rts */ VOID myprintf(char *fmt,...) { unsigned char buf[256]; STRPTR *arg = (STRPTR *)(&fmt+1); RawDoFmt((STRPTR) fmt, arg, (void (*)())&tricky, buf); Write(Stdout, buf, strlen((char *)buf)); } void main() { Stdout = Output(); float x = 1.623 * (float) N; myprintf("Just a hello world. if you cast x to integer is: %ld\n", (int)x); exit(0); } Code:
CFLAGS=-Os -noixemul -fomit-frame-pointer -fbaserel -msmall-code LDFLAGS=-nostartfiles -noixemul -fbaserel Code:
m68k-amigaos-gcc -nostartfiles -s -noixemul -fbaserel -o nshello startup.o nshello.o |
01 May 2019, 20:01 | #14 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
whats the byte size of the executable on that bebbo?
|
01 May 2019, 22:28 | #15 |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 680
|
|
01 May 2019, 23:17 | #16 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
kind of big, huh? malloc is pulled in?
|
02 May 2019, 08:54 | #17 |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 680
|
It's not big - just consider all the pulled in math functions. It uses mathieeedoubbas.library and mathieeedoubtrans.library plus the mandatory conversion functions to convert float to int and back etc.p.p.
Are you comparing apples with pears? EDIT: if you replace Code:
int N = 100; Code:
#define N 100 Last edited by bebbo; 02 May 2019 at 09:13. |
02 May 2019, 09:49 | #18 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
Ah, that makes sense.
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
AREXX - minimal requirements/setup? | solarmon | Coders. Scripting | 24 | 13 January 2019 18:39 |
Minimal config for multiview | jotd | support.Apps | 17 | 14 March 2016 22:38 |
Amiga GCC Where to find it? | _ThEcRoW | request.Apps | 10 | 02 March 2006 00:44 |
A minimal request | jobro | Amiga scene | 3 | 29 December 2005 03:24 |
Amiga GCC Where can i find? | _ThEcRoW | request.Apps | 1 | 22 October 2005 18:17 |
|
|