Pelles C forum

C language => Tips & tricks => Topic started by: Vortex on September 14, 2004, 11:31:10 AM

Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 14, 2004, 11:31:10 AM
Hi friends,

Here (http://board.win32asmcommunity.net/viewtopic.php?p=149703#149703), you can find a tiny C run-time startup module with asm command line parser for various C/C++ compilers ( including Pelle's compiler )

Pelle, could you add the attachment feature to the forum?

Thanks,

Vortex
Title: Tiny C run-time startup module for console applications
Post by: TBD on September 14, 2004, 12:37:53 PM
Vortex: where is crtdll.lib ?  :D
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 14, 2004, 02:41:41 PM
Hi TBD,

Yes, you are right. Here is the solution:

Build.bat
Code: [Select]

call povars32.bat
polib /machine:ix86 /out:crtdll.lib /def:crtdll.def

\pellesc\bin\pocc /Zx /Ze /Zl /Os Test.c
\pellesc\bin\polink /SUBSYSTEM:CONSOLE /OUT:Test.exe ..\startc.obj Test.obj ..\ParseCmdLine.obj kernel32.lib crtdll.lib


crtdll.def
Code: [Select]

LIBRARY crtdll
EXPORTS
printf

...which normally is enough for this small example.

If you would like to get the zip file,y ou can send me a PM with your e.mail address.
Title: Tiny C run-time startup module for console applications
Post by: TBD on September 14, 2004, 02:59:48 PM
thanks Vortex.

I created the lib myself using podump.exe /exports, removing the extra, adding LIBRARY crtdll, EXPORTS.
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 15, 2004, 10:21:40 AM
Here is the attachment.
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 21, 2004, 08:06:53 PM
Here is the startup module for GUI applications.

The code in C:
Code: [Select]

#include <windows.h>

extern UINT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

HMODULE hInstance;

void WINAPI WinMainCRTStartup()
{
hInstance=GetModuleHandle(NULL);
ExitProcess(WinMain(hInstance,NULL,GetCommandLine(),SW_SHOWDEFAULT));
}


The equivalent code in asm with some manual optimizations, wcrt0.asm :
Code: [Select]

[cpu 486]
[global _WinMainCRTStartup]
[section .text]
[function _WinMainCRTStartup]
_WinMainCRTStartup:
push dword (0)
call dword [(__imp__GetModuleHandleA@4)]
mov dword [(_hInstance)],eax
call dword [(__imp__GetCommandLineA@0)]
push dword 10
push dword eax
push dword (0)
push dword [(_hInstance)]
call _WinMain@16
push dword eax
call dword [(__imp__ExitProcess@4)]
..?X_WinMainCRTStartup:
[section .bss]
[global _hInstance]
[common _hInstance 4]
[extern _WinMain@16]
[extern __imp__GetCommandLineA@0]
[extern __imp__GetModuleHandleA@4]
[extern __imp__ExitProcess@4]


No need to use an external assembler to generate the object code.
An example of building a GUI based application:
Code: [Select]

call "povars32.bat"
pocc wcrt0.asm
pocc /Ze /Zl /Os Window.c
polink /SUBSYSTEM:WINDOWS /OUT:Window.exe wcrt0.obj Window.obj kernel32.lib user32.lib


The attachment contains a demo using this tiny C run-time startup code, the size of the final executable - a simple window is only 2048 bytes.

Click here (http://www.geocities.com/wortex00/Wcrt0_2.zip) to download the attachment.
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 22, 2004, 04:48:36 PM
Bug fixed : The lpCmdLine parameter should point the first command line parameter not the filename.

Code: [Select]

[cpu 486]
[global _WinMainCRTStartup]
[section .text]
[function _WinMainCRTStartup]
_WinMainCRTStartup:
push dword (0)
call dword [(__imp__GetModuleHandleA@4)]
mov dword [(_hInstance)],eax
call dword [(__imp__GetCommandLineA@0)]
dec eax
@100:
inc eax
mov cl,byte [eax]
or cl,cl
jz @102
cmp cl,32
jne @100
dec eax
@101:
inc eax
mov cl,byte [eax]
cmp cl,32
je @101
@102:
push dword 10
push dword eax
push dword (0)
push dword [(_hInstance)]
call _WinMain@16
push dword eax
call dword [(__imp__ExitProcess@4)]
..?X_WinMainCRTStartup:
[section .bss]
[global _hInstance]
[common _hInstance 4]
[extern _WinMain@16]
[extern __imp__GetCommandLineA@0]
[extern __imp__GetModuleHandleA@4]
[extern __imp__ExitProcess@4]


New attachment uploaded at the top.
Title: Tiny C run-time startup module for console applications
Post by: Jibz on September 22, 2004, 09:14:32 PM
Nice work vortex :).

I am not quite sure, but I think that code might fail if the filename or path at the start of the string returned by GetCommandLine contains spaces?
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 22, 2004, 09:31:11 PM
Hi Jibz,

GetCommandLine removes those leading spaces, so there is no problem.
Title: Tiny C run-time startup module for console applications
Post by: Jibz on September 22, 2004, 10:11:43 PM
What I meant was that if the filename of the executable itself contains spaces, then GetCommandLine will return something like:
Code: [Select]
"C:\Foo\With Space.exe" arg1 arg2
where the filename with path is quoted because it contains a space.

Try in your example to show the contents of lpCmdLine in a messagebox, and then rename the executable to something with a space.
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 23, 2004, 02:54:01 PM
Hi Jibz,

Thanks for pointing me the right direction.

Here is the code:
Code: [Select]

[cpu 486]
[global _WinMainCRTStartup]
[section .text]

[function _WinMainCRTStartup]

_WinMainCRTStartup:
push dword (0)
call dword [(__imp__GetModuleHandleA@4)]
mov dword [(_hInstance)],eax
call dword [(__imp__GetCommandLineA@0)]
cmp byte [eax],34 ;check for leading quote
jne @102
@100: ;look for the second quote
inc eax
mov cl,byte [eax]
or cl,cl
jz @104
cmp cl,34
jne @100
jmp @103 ;look for space chars
@101:
inc eax
@102: ;skip file name
mov cl,byte [eax]
or cl,cl
jz @104
cmp cl,32
jne @101
dec eax
@103: ;skip space chars
inc eax
mov cl,byte [eax]
cmp cl,32
je @103
@104:
push dword 10
push dword eax
push dword (0)
push dword [(_hInstance)]
call _WinMain@16
push dword eax
call dword [(__imp__ExitProcess@4)]

..?X_WinMainCRTStartup:

[section .bss]
[global _hInstance]
[common _hInstance 4]
[extern _WinMain@16]
[extern __imp__GetCommandLineA@0]
[extern __imp__GetModuleHandleA@4]
[extern __imp__ExitProcess@4]
Title: Project file for WCRT0
Post by: TimoVJL on September 24, 2004, 07:37:27 AM
Project file for WCRT0:
Code: [Select]

#
# PROJECT FILE generated by "Pelles C for Windows, version 2.80".
# NOTE! Manual changes of this file is done at your own risk.
#

POC_PROJECT_VERSION = 1.00#
POC_PROJECT_TYPE = 2#
POC_PROJECT_PATH = .#
POC_PROJECT_ARGUMENTS = #
POC_PROJECT_WORKPATH = #
POC_PROJECT_EXECUTOR = #
CC = pocc.exe#
AS = pocc.exe#
AR = polib.exe#
CCFLAGS = #
ASFLAGS = #
ARFLAGS = #

.SILENT:  

#
# Build WCRT0.LIB.
#
"$(POC_PROJECT_PATH)\WCRT0.LIB": \
  "$(POC_PROJECT_PATH)\output\wcrt0.OBJ"
  $(AR) $(ARFLAGS) -out:"$@" $**

#
# Build wcrt0.OBJ.
#
"$(POC_PROJECT_PATH)\output\wcrt0.OBJ": \
  "$(POC_PROJECT_PATH)\wcrt0.asm"  
  $(AS) $(ASFLAGS) -Fo"$@" "$!"


Then you can use it in source file with

#pragma nodefaultlib
#pragma comment(lib, "wcrt0.lib")
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 24, 2004, 08:47:14 AM
Hi timovjl,

That's nice, I will try it.  :)
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 25, 2004, 03:05:13 PM
Here is another example using Pelle's C run-time DLL pocrt.dll
Code: [Select]

#define WIN32_LEAN_AND_MEAN
#define IDC_EDIT 4001

#include <stdio.h>
#include <windows.h>

HINSTANCE hInstance;
FILE *file;
char buffer[75];
char k;
char i=0;

BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch(msg)
    {
        case WM_CLOSE:
EndDialog(hwnd,0);
        break;
        case WM_INITDIALOG:
file=fopen("Text.txt","r");

while ( k=fgetc(file)) {
if (k==EOF) {
buffer[i]=0;
break;
}

if (k==10) {
buffer[i]=13;
++i;
}

buffer[i]=k;
++i;
}
fclose(file);
SetDlgItemText(hwnd,(int)IDC_EDIT,buffer);
       break;
default:
            return FALSE;
    }
    return TRUE;

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
LPCTSTR DlgName="MyDialog";
hInstance=GetModuleHandle(0);
return(DialogBoxParam(hInstance,DlgName,0,DlgProc,0));
}
[/code]
Title: Tiny C run-time startup module for console applications
Post by: Vortex on December 30, 2004, 09:20:49 PM
Hi friends,

Here is the latest release of my C startup code very easy to use, now this time the sample projects both GUI and console are supported with ppj files. The startup codes are assembler with Masm.
Title: Tiny C run-time startup module for console applications
Post by: Gerome on December 30, 2004, 11:54:15 PM
Hi Vortex,

Very nice additions :)
This can be eventually added to the PellesC distro ?
It can be interesting to have several ways of making Executables :)

BTW, do you have the equivalent tiny CRTs for a DLL and a Static LIB please ?

Thanks again for this wonderful job !

Quote from: "Vortex"
Hi friends,

Here is the latest release of my C startup code very easy to use, now this time the sample projects both GUI and console are supported with ppj files. The startup codes are assembler with Masm.
Title: Tiny C run-time startup module for console applications
Post by: Vortex on December 31, 2004, 12:02:43 PM
Hi Gerome,

Thanks for your kind words. The linker extracts and links only the necessary member functions from static libraries, these ones doesn't  require any startup code.

I will post an example for DLLs.
Title: Tiny C run-time startup module for console applications
Post by: Vortex on January 02, 2005, 05:19:27 PM
Hi Gerome,

The tricks to create small DLLs are again avoiding using static C run-time libraries, plus setting the entry point of the DLL to:
Code: [Select]

DllMain@12


The project I posted is an example of an autotyper. The application launches notepad.exe and characters of a message starts to appear one by one on the notepad! :)
The autotyping function is called from a DLL sized only 3072 bytes.
Title: Tiny C run-time startup module for console applications
Post by: Vortex on September 11, 2005, 01:12:13 PM
Hi friends,

Here is another C run-time startup module coded with GoAsm
Title: Tiny C run-time startup module for console applications
Post by: Vortex on February 10, 2006, 08:44:06 PM
Here is a new version of the library coded with POASM
Title: Tiny C run-time startup module for console applications
Post by: lvckyluke on May 16, 2006, 11:45:44 PM
vortex, the console startup code didn't check for 'tab'..  it failed to read correct argv[] when running the program with batch file that exist tab as commandline separator.

i make fixup like this:

Code: [Select]

; POASM
.586
.model flat,c
option casemap:none

WINBASEAPI_GetCommandLineA typedef proto stdcall
externdef stdcall _imp__GetCommandLineA@0: ptr WINBASEAPI_GetCommandLineA
GetCommandLine equ <_imp__GetCommandLineA@0>

WINBASEAPI_ExitProcess typedef proto stdcall :DWORD
externdef stdcall _imp__ExitProcess@4: ptr WINBASEAPI_ExitProcess
ExitProcess equ <_imp__ExitProcess@4>

main proto c :DWORD,:VARARG

.data?
_p__args db 144 dup(?) ; 32 for argv[x8], 128 for buffer

.code

_setargv proc uses esi edi
invoke GetCommandLine
mov esi,eax
mov edx,offset _p__args
push edx
lea edi,[edx+32]
xor ecx,ecx
mov ah,32
@@:
lodsb
test al,al
jz @5
cmp al,9
jz @b
cmp al,ah
jz @b
@0:
mov [edx],edi
add edx,4
inc ecx
jmp @2
@1:
lodsb
cmp al,ah
jz @3
cmp al,9
jz @3
@2:
cmp al,34
jnz @4
xor ah,32
jmp @1
@3:
mov al,0
@4:
stosb
test al,al
jnz @1
dec esi
jmp @b
@5:
mov eax,ecx ; argc
pop ecx        ; argv[1]
ret
_setargv endp

public mainCRTStartup
mainCRTStartup proc
push ebp
mov ebp,esp
invoke _setargv
invoke main,eax,ecx ; argc,argv
invoke ExitProcess,eax
mainCRTStartup endp
end

Title: Re: Tiny C run-time startup module for console applications
Post by: Vortex on April 19, 2009, 11:04:05 AM
This version checks the TAB character.
Title: Re: Tiny C run-time startup module for console applications
Post by: Vortex on October 09, 2011, 08:58:41 PM
New version of the tiny C run-time startup library ( Wcrt0_7.zip ) :

The NULL terminator character of the last command-line argument was not copied to the destination buffer by the module crt0cons. This bug is fixed now.

ParseCmdLineParam.zip : Command-line parser for Jwasm \ Masm \ Poasm console applications
Title: Re: Tiny C run-time startup module for console applications
Post by: TimoVJL on October 12, 2011, 06:49:08 PM
Thanks Vortex.

Here is similar code converted to C :
Code: [Select]
//#define WIN32_LEAN_AND_MEAN
//#include <windows.h>

#ifndef _WINDOWS_H
void _stdcall ExitProcess(unsigned int);
char __stdcall *GetCommandLineA(void);
#define GetCommandLine GetCommandLineA
int __stdcall lstrlenA(char *);
#define lstrlen lstrlenA
int __cdecl wsprintfA(char *, char *, ...);
#define wsprintf wsprintfA
#define DWORD unsigned long
int __stdcall WriteFile(void *, char *, DWORD, DWORD*, void*);
void * __stdcall GetStdHandle(DWORD);
#define STD_OUTPUT_HANDLE -11
#endif

#pragma comment(lib, "kernel32")
#pragma comment(lib, "user32")

char szCmdLine[1024];

int ParseCmdLine(char *pCmdLine)
{
char *pPos, *pP2, cSp, cTab;
int iArgs;

pPos = GetCommandLine();
pP2 = pCmdLine;
cSp = 32;
cTab = 9;
iArgs = 0;
do { // scan commandline
if (*pPos == ' ' || *pPos == '\t') // strip whitespaces off
continue;
iArgs++;
do { // loop cmdline
if (!*pPos) {
*pP2 = *pPos; // store 0 too
break;
}
if (*pPos == cSp || *pPos == cTab) { // if not quoted it is separator
break; // end of parameter
}
if (*pPos == '"') { // quote ?
cSp ^= 32;
cTab ^= 9;
continue;
}
*pP2++ = *pPos; // store char
} while (*pPos++);
*pP2++ = 0;
} while (*pPos++);
return iArgs;
}

int __cdecl mainCRTStartup(void)
{
int nLen, nIdx, nCnt;
DWORD dwWrite;
char *pPos, szTmp[1024];

nCnt = ParseCmdLine(szCmdLine);
pPos = szCmdLine;
nIdx = 0;
do {
nLen = wsprintf(szTmp, "par %d = %s\n", nIdx++, pPos);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), szTmp, nLen, &dwWrite, 0);
pPos += lstrlen(pPos) + 1;
} while(--nCnt);

ExitProcess(0);
return 0;
}