The MASM Forum

Miscellaneous => The Orphanage => Topic started by: daydreamer on August 22, 2019, 12:15:19 AM

Title: if you are forced to use only C/C++ on a project...
Post by: daydreamer on August 22, 2019, 12:15:19 AM
Hi
what should you do if you are forced to use only C/C++ code on a project and must produce readable code without assembly and other advanced functions
and you need it to perform better
should you choose a different and better compiler?(tested to produce faster code on same source with fastest settings)
and if so why just that?
and use knowledge from assembly to make things faster

I think I want to test clang

Title: Re: if you are forced to use only C/C++ on a project...
Post by: TimoVJL on August 22, 2019, 12:55:01 AM
If you want to have a same source file for 32/64 bit, C is for it.
gcc and clang have inline assembler support for x64.
clang is a free option, but without CRT and without standard include files and libraries, but have support for MS PDB.
gcc don't have support for MS PDB.

FORCED ?, better to use best compiler/tools for the project.

Title: Re: if you are forced to use only C/C++ on a project...
Post by: Vortex on August 22, 2019, 04:16:28 AM
Also, MinGW64 supports inline assembly.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 22, 2019, 11:56:51 AM
My take on this is that when we need to use ASM with C or any other high-level language, it is almost always better to use a separate ASM module. The main reason is that, except for very basic things, such as reversing or rotating bits, inline ASM is cumbersome when compared to full fledged ASM. Sure, it will require a call to the module while inline does not, but does it really weight that much in the final computation? Probably not.

Some people believe that C can replace ASM in every instance. It can not, intrinsics are a panacea. When using vector instructions or looking for extreme performance rotines like memory move, better use real ASM.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: hutch-- on August 22, 2019, 05:14:38 PM
Every tool has its place, a C compiler can produce very good code in skilled hands but it can also produce garbage when not well written. The main bugbear with C/C++ are its runtime libraries, an experienced C programmer knows how to navigate the available range where an amateur will produce bloated garbage.

Now if you write in MASM, who cares.  :rofl:
Title: Re: if you are forced to use only C/C++ on a project...
Post by: TimoVJL on August 22, 2019, 09:47:52 PM
C/C++ users should know, that masm32 have a msvcrt.lib for msvcrt.dll without VC startup routines.
Now we just have to learn to use them, so we can share simple examples without VC CRT, for example that vcruntime140.dll, what isn't part of Windows OS.

For ANSI console program:
Code: [Select]
#pragma comment(lib, "msvcrt.lib")
#if _MSC_VER >= 17
# ifdef _WIN64
#  pragma comment(linker,"/subsystem:console,5.2")
# else
#  pragma comment(linker,"/subsystem:console,5.1")
# endif
#endif
void __cdecl mainCRTStartup(void)
{
__declspec(dllimport) int __cdecl __getmainargs(int*, char***, char***, int, void*);
__declspec(dllimport) void __cdecl exit(int status);
int __cdecl main(int argc, char **argv);

int    argc;
char** argv;
char** env;
int    si = 0;

__getmainargs(&argc,&argv,&env,0,&si);
exit(main(argc,argv));
}
Title: Re: if you are forced to use only C/C++ on a project...
Post by: daydreamer on August 23, 2019, 07:24:18 PM
thanks everyone for your answers,I read clang has both cl and gcc compability mode
its nice to be able to use inline asm also in 64bit mode,also good to use clang because it seems to produce faster code
AW
I want to make a library of this:
working on a 4xsincostanarcsinarccos PROC,which I want to add jumptable and ifs,so you can choose one or several parts of it
also read about C++ argument against inline asm,it can break compilers optimizating on the rest of the code,dont know if its truth in it


Title: Re: if you are forced to use only C/C++ on a project...
Post by: jcfuller on August 23, 2019, 07:46:33 PM
C/C++ users should know, that masm32 have a msvcrt.lib for msvcrt.dll without VC startup routines.
Now we just have to learn to use them, so we can share simple examples without VC CRT, for example that vcruntime140.dll, what isn't part of Windows OS.
Problem is msvcrt.dll is not c99 compliant.
You need to fine a way to access ucrtbase.dll which vc has used since VS2015 I believe.
Not sure how Pelles does it?
This link describes one problem:
https://www.oxygenbasic.org/forum/index.php?topic=1947.0

James
Title: Re: if you are forced to use only C/C++ on a project...
Post by: hutch-- on August 23, 2019, 07:53:13 PM
There is in fact a good reason for the MASM32/64 versions of MSVCRT, the DLL is part of the system so its functions have been available for a very long time. The VC initialisations are no real use in assembler and are easy enough to code in any case so they are not part of those two import libraries. You can go the path of having to add DLLs for C compilers but surely it defeats the purpose of making stand alone executable files unless you want to create your own DLLs which is a design choice, not a runtime DLL.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: TimoVJL on August 23, 2019, 08:16:28 PM
Pelles C don't use ucrtbase.dll

ucrt isn't ready yet, it don't have printf, but VC have inline code for it and an additional library for it.

PellesC test with ucrt (https://forum.pellesc.de/index.php?topic=7052.msg26773#msg26773)
Code: [Select]
int main(int argc, char **argv);

void __cdecl mainCRTStartup(void)
{
//_initialize_narrow_environment();
char* pcml[] = {0,_get_narrow_winmain_command_line()};
stdin  = __acrt_iob_func(0);
stdout = __acrt_iob_func(1);
stderr = __acrt_iob_func(2);

exit(main(0, pcml));
}
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 23, 2019, 08:36:48 PM
C/C++ programmers, always pray for users to have all redistributables. What runs behind the scenes is a real mess, even experts have trouble understanding it.

But most of this discussion is indeed useless for Masm programmers that produce Masm standalone applications. Fortunately, msvcrt.dll provides everything needed. Things sometimes become tricky when mixing C/C++ and ASM, but the general rule is to use the same libraries/DLLs already used in the high-level part (C/C++).

Title: Re: if you are forced to use only C/C++ on a project...
Post by: daydreamer on August 23, 2019, 08:37:04 PM
but there is both cons and pros with DLL's,isnt one problem if you use big arrays,you get an additional memcopy between dll library and main program of those?

Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 23, 2019, 08:46:51 PM
but there is both cons and pros with DLL's,isnt one problem if you use big arrays,you get an additional memcopy between dll library and main program of those?

I don't think I understand what you mean, but the DLL once loaded is in the same memory space as the main program, no additional memcopy is needed.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: jj2007 on August 23, 2019, 09:25:18 PM
Problem is msvcrt.dll is not c99 compliant.

James,

Excuse my ignorance, but what exactly is the problem there?

Quote
I received an email pointing out a problem with the time functions which I verified.
Output using vs2019 on Win 10 and gcc on Linux:
Code:
Code: [Select]
Mon Aug  5 14:52:11 2019
Today is Monday, August 05.
The time is 02:52 PM.
ISO week day is 2019W321.
Output from NUWEN and my bc9/TCLib:
Code:
Code: [Select]
Mon Aug 05 15:18:27 2019
Today is Monday, August 05.
The time is 03:18 PM.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: TimoVJL on August 23, 2019, 10:21:46 PM
Someone has found one way to crash msvcrt.dll printf strftime :rofl:
Code: [Select]
Pelles C
Fri Aug 23 14:57:32 2019
Today is Friday, August 23.
The time is 02:57 PM.
ISO week day is 2019W345.

msvcrt.dll
Fri Aug 23 15:01:31 2019
Today is Friday, August 23.
The time is 03:01 PM.

ucrtbase.dll
Fri Aug 23 15:02:52 2019
Today is Friday, August 23.
The time is 03:02 PM.
ISO week day is 2019W345.
Problem is msvcrt.dll is not c99 compliant.
Of course it isn't, as M$ started to conform C99 somewhere 2012, it just took so long.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: jj2007 on August 23, 2019, 11:22:39 PM
Now I see the problem - using the C source from James' post at the oxygen forum:
Code: [Select]
#include <time.h>
#include <stdio.h>
#define SIZE 256

int main (void)
{
  char buffer[SIZE];
  time_t curtime;
  struct tm *loctime;

  /* Get the current time. */
  curtime = time (NULL);

  /* Convert it to local time representation. */
  loctime = localtime (&curtime);

  /* Print out the date and time in the standard format. */
  fputs (asctime (loctime), stdout);

  /* Print it out in a nice format. */
  strftime (buffer, SIZE, "Today is %A, %B %d.\n", loctime);
  fputs (buffer, stdout);
  strftime (buffer, SIZE, "The time is %I:%M %p.\n", loctime);
  fputs (buffer, stdout);
  strftime (buffer, SIZE, "ISO week day is %GW%V%u.\n", loctime);
  fputs (buffer, stdout);
  return 0;
}

Gcc "forgets" the ISO part, while Pelles C and Visual C print it correctly. Seems more a problem with strftime, though: It returns 0 (success?) for all calls but the last one leaves only a zero byte in the buffer.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: TimoVJL on August 24, 2019, 12:02:52 AM
The OS msvcrt.dll thing is a good thing for clang, as it don't have own CRT.
So, a small examples can be done with msvcrt.lib from masm32 package, if we forget those pesky include files, other that Windows SDK.
If there is interest in this area, we can share our knowledge of making small programs.
A fare thing ?
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 24, 2019, 12:41:07 AM
I think MSVCRT.DLL continues not recognizing the format specifiers %G and %V. However, the C runtimes after VS 2015 do recognize.

This is for Windows 10.

Code: [Select]
.model flat, stdcall

size_t typedef ptr
includelib \masm32\lib\msvcrt.lib
time proto C :ptr
strftime proto C :ptr, :size_t, :ptr, :vararg
localtime proto C :ptr
asctime proto C :ptr
puts proto C :ptr

.data
todayIs db "Today is %A, %B %d",0
timeIs db "The time is %I:%M %p.",0
isoMSG db "ISO week day is %GW%V%u.",0
buffer db 256 dup (0)

.code

main proc
LOCAL curtime : qword
LOCAL loctime : ptr

invoke time, 0
mov dword ptr curtime, eax
mov dword ptr curtime+4, edx
invoke localtime, addr curtime
mov loctime, eax
invoke asctime, eax
invoke puts, eax
invoke strftime, addr buffer, 256, offset todayIs, loctime
invoke puts, addr buffer
invoke strftime, addr buffer, 256, offset timeIs, loctime
invoke puts, addr buffer
invoke strftime, addr buffer, 256, offset isoMSG, loctime
invoke puts, addr buffer
ret
main endp

end


Output:
Fri Aug 23 15:34:45 2019

Today is Friday, August 23
The time is 03:34 PM.

(No sign of the ISO message.)
Title: Re: if you are forced to use only C/C++ on a project...
Post by: jcfuller on August 24, 2019, 12:44:50 AM
I did find a couple of discussions on MinGW gcc development accessing ucrtbase.dll but I got distracted elsewhere and did not follow up.
All the source for ucrtbase is in the ??\kits\10 folder (I forget the full path now) but all ucrtbase.dll functions I believe rely on exception handling??

James
Title: Re: if you are forced to use only C/C++ on a project...
Post by: TimoVJL on August 24, 2019, 12:50:21 AM
I think MSVCRT.DLL continues not recognizing the format specifiers %G and %V. However, the C runtimes after VS 2015 do recognize.
Sure it stays as a M$ Palmer era :rofl: , it don't change.
Of course it isn't, as M$ started to conform C99 somewhere 2012, it just took so long.
My mistake, i didn't specifically told that msvcrt.dll don't follow that.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 24, 2019, 01:17:40 AM
But this works, we need to fish ucrt.lib

Code: [Select]
.model flat, stdcall

size_t typedef ptr
includelib "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86\ucrt.lib"
strftime proto C :ptr, :size_t, :ptr, :vararg
asctime proto C :ptr
puts proto C :ptr
includelib \masm32\lib\msvcrt.lib
localtime proto C :ptr
time proto C :ptr

.data
todayIs db "Today is %A, %B %d",0
timeIs db "The time is %I:%M %p.",0
isoMSG db "ISO week day is %GW%V%u.",0
buffer db 256 dup (0)

.code

main proc
LOCAL curtime : qword
LOCAL loctime : ptr

invoke time, 0
mov dword ptr curtime, eax
mov dword ptr curtime+4, edx
invoke localtime, addr curtime
mov loctime, eax
invoke asctime, eax
invoke puts, eax
invoke strftime, addr buffer, 256, offset todayIs, loctime
invoke puts, addr buffer
invoke strftime, addr buffer, 256, offset timeIs, loctime
invoke puts, addr buffer
invoke strftime, addr buffer, 256, offset isoMSG, loctime
invoke puts, addr buffer
ret
main endp

end

Output:
Fri Aug 23 16:14:41 2019

Today is Friday, August 23
The time is 04:14 PM.
ISO week day is 2019W345.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: TimoVJL on August 24, 2019, 01:36:37 AM
Reply #9 http://masm32.com/board/index.php?topic=8045.msg88168#msg88168 ucrtbase.def
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 24, 2019, 01:55:02 AM
Reply #9 http://masm32.com/board/index.php?topic=8045.msg88168#msg88168 ucrtbase.def

Yes, ucrtbase.dll is not enough.   :sad:
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 24, 2019, 02:35:24 AM
Now ucrtbase.dll is enough.  :thumbsup:

Code: [Select]
.model flat, stdcall

size_t typedef ptr
includelib "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86\ucrt.lib"
;includelib ucrtbase.lib ; works also (supplied by TimoVJL)
strftime proto C :ptr, :size_t, :ptr, :vararg
asctime proto C :ptr
puts proto C :ptr
_localtime32 proto C :ptr
_time64 proto C :ptr

.data
todayIs db "Today is %A, %B %d",0
timeIs db "The time is %I:%M %p.",0
isoMSG db "ISO week day is %GW%V%u.",0
buffer db 256 dup (0)

.code

main proc
LOCAL curtime : qword
LOCAL loctime : ptr

invoke _time64, 0
mov dword ptr curtime, eax
mov dword ptr curtime+4, edx
invoke _localtime32, addr curtime
mov loctime, eax
invoke asctime, eax
invoke puts, eax
invoke strftime, addr buffer, 256, offset todayIs, loctime
invoke puts, addr buffer
invoke strftime, addr buffer, 256, offset timeIs, loctime
invoke puts, addr buffer
invoke strftime, addr buffer, 256, offset isoMSG, loctime
invoke puts, addr buffer
ret
main endp

end
Title: Re: if you are forced to use only C/C++ on a project...
Post by: TimoVJL on August 24, 2019, 03:55:24 AM
OK, i missed to show something
Code: [Select]
typedef void *FILE;
FILE *__acrt_iob_func(int);
...
FILE stdout = __acrt_iob_func(1);
then fputs() works
stdio.h is a real trouble maker, a compiler specific header, better to avoid it, mostly full of junk, as C standard group allows that.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 24, 2019, 05:28:08 AM
Yes, it works, (no need for headers  :badgrin:):

Code: [Select]
.model flat, stdcall

size_t typedef ptr
includelib "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86\ucrt.lib"
;includelib ucrtbase.lib ; supplied by TimoVJL
strftime proto C :ptr, :size_t, :ptr, :vararg
asctime proto C :ptr
fputs proto C :ptr, :ptr
_localtime64 proto C :ptr
_time64 proto C :ptr
__acrt_iob_func proto C :BYTE

.data
todayIs db "Today is %A, %B %d",10,0
timeIs db "The time is %I:%M %p.",10,0
isoMSG db "ISO week day is %GW%V%u.",10,0
buffer db 256 dup (0)


localtime equ _localtime64
time equ _time64

.code

main proc
LOCAL curtime : qword
LOCAL loctime : ptr
LOCAL stdout :ptr

invoke time, 0
mov dword ptr curtime, eax
mov dword ptr curtime+4, edx
invoke __acrt_iob_func, 1
mov stdout, eax

invoke localtime, addr curtime
mov loctime, eax
invoke asctime, eax
invoke fputs, eax, stdout
invoke strftime, addr buffer, 256, offset todayIs, loctime
invoke fputs, addr buffer, stdout
invoke strftime, addr buffer, 256, offset timeIs, loctime
invoke fputs, addr buffer, stdout
invoke strftime, addr buffer, 256, offset isoMSG, loctime
invoke fputs, addr buffer, stdout
ret
main endp

end
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 24, 2019, 07:02:24 AM
Using fputs with msvcrt.dll

Code: [Select]
.model flat, stdcall

FILE struct
_ptr dd ?
_cnt dd ?
_base dd ?
_flag dd ?
_file dd ?
_charbuf dd ?
_bufsiz dd ?
_tmpfname dd ?
FILE ends

includelib \masm32\lib\msvcrt.lib
fputs proto C :ptr, :ptr
externdef C _imp___iob : ptr
stdin equ <_imp___iob>

.data

HelloMsg db "Testing fputs",10,0

.code

main proc
LOCAL stdout : ptr

mov ecx,  stdin
add ecx, sizeof FILE
mov stdout, ecx;

mov eax, offset HelloMsg
invoke fputs, eax, stdout
ret
main endp

end

Output:
Testing fputs
Title: Re: if you are forced to use only C/C++ on a project...
Post by: Vortex on August 24, 2019, 07:07:41 PM
James' code built with Cygwin :

Code: [Select]
$ gcc GetTimeTest.c  -o GetTimeTest.exe

$ ./GetTimeTest.exe
Sat Aug 24 12:06:00 2019
Today is Saturday, August 24.
The time is 12:06 PM.
ISO week day is 2019W346.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: daydreamer on August 24, 2019, 09:42:21 PM
but there is both cons and pros with DLL's,isnt one problem if you use big arrays,you get an additional memcopy between dll library and main program of those?

I don't think I understand what you mean, but the DLL once loaded is in the same memory space as the main program, no additional memcopy is needed.
judge for yourself very old unomptimized kinda raycast dll,made with vc++
Title: Re: if you are forced to use only C/C++ on a project...
Post by: hutch-- on August 24, 2019, 10:51:05 PM
Magnus,

This one is not a debate, a DLL is mapped into the memory space of the app that calls it, all you have to do to get data from a DLL is to get the pointer to it as it is already in memory. If someone has to copy memory from a DLL to a calling app, they have done it the wrong way. Just pass the pointer.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: jcfuller on August 24, 2019, 11:56:25 PM
working example for 64bit??

James
Title: Re: if you are forced to use only C/C++ on a project...
Post by: Vortex on August 25, 2019, 04:38:09 AM
MinGW 64-bit V5.4.0 :

Code: [Select]
C:\mingw64>gcc GetTimeTest.c -o GetTimeTest.exe

C:\mingw64>GetTimeTest.exe
Sat Aug 24 21:35:29 2019
Today is Saturday, August 24.
The time is 09:35 PM.
ISO week day is W.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: AW on August 25, 2019, 04:55:36 AM
Playing with stdio file control structures from msvcrt.dll

Code: [Select]
#include <tchar.h>
#include <stdio.h>

#define SIZE 256

#undef stdin
#undef stdout
#undef stderr
#pragma comment(lib,"msvcrt.lib")
#ifdef _WIN64
extern char* __imp__iob;
#define stdin (FILE*)&__imp__iob[0]
#define stdout (FILE*)&__imp__iob[sizeof(FILE)]
#define stderr (FILE*)&__imp__iob[2*sizeof(FILE)]
#else
extern char* _imp___iob;
#define stdin (FILE*)&_imp___iob[0]
#define stdout (FILE*)&_imp___iob[sizeof(FILE)]
#define stderr (FILE*)&_imp___iob[2*sizeof(FILE)]
#endif


int mainCRTStartup(void)
{
char buffer[SIZE] = { 0 };
fputs("Was Stalin German, Italian, Russian or Chinese ?:\n", stdout);
while (1)
{
fgets(buffer, SIZE - 1, stdin);
buffer[strcspn(buffer, "\n")] = '\0';

if (_stricmp(buffer, "russian"))
fputs("Wrong, please retry\n", stderr);
else
{
fputs("Correct\n", stdout);
break;
}
}
getchar();
return 0;
}
Title: Re: if you are forced to use only C/C++ on a project...
Post by: Vortex on August 25, 2019, 05:28:16 AM
Calling __p__iob to get STDIN :

Code: [Select]
.386
.model flat, stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\msvcrt.inc
includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\msvcrt.lib

_iobuf STRUCT

    _ptr        DWORD ?
    _cnt        DWORD ?
    _base       DWORD ?
    _flag       DWORD ?
    _file       DWORD ?
    _charbuf    DWORD ?
    _bufsiz     DWORD ?
    _tmpfname   DWORD ?

_iobuf ENDS

FILE TYPEDEF _iobuf

.data

msg     db 'Message output to STDOUT',0

.data?

stdout  dd ?
stdin   dd ?
stderr  dd ?

.code

start:

    call    crt___p__iob
    mov     stdin,eax           ; #define stdin  (&__iob_func()[0])

    mov     ecx,SIZEOF(FILE)

    add     eax,ecx
    mov     stdout,eax          ; #define stdout (&__iob_func()[1])

    add     eax,ecx
    mov     stderr,eax          ; #define stderr (&__iob_func()[2])

    invoke  crt_fputs,ADDR msg,stdout
           
    invoke  ExitProcess,0

END start
Title: Re: if you are forced to use only C/C++ on a project...
Post by: xanatose on March 10, 2020, 07:10:25 AM
Usual rules of thumb.
- Measure and don't assume.
- Use the best algorithm for the given problem. And you learn this by trying many algorithms. 
- Compile without any optimization to debug it troughly. It will be very slow. But it will give your debugger for the debugger to catch the errors you made while drunk at 2am in the morning. :)
- Compile it in release with whatever compiler you have and debug it with whatever debugger you have.
Now you have a product. But if you want to go one extra step.
Then, and only then, you look for a better optimizing compiler. In this case, I would go for Intel C++. It takes ages to do an optimized compile. But it does provide good results for intel CPU (Not sure if the best results for AMD).

Normally it will be a compromise between getting the best running time and getting the best development time.
Title: Re: if you are forced to use only C/C++ on a project...
Post by: daydreamer on March 10, 2020, 10:12:44 PM
Usual rules of thumb.
- Measure and don't assume.
- Use the best algorithm for the given problem. And you learn this by trying many algorithms. 
- Compile without any optimization to debug it troughly. It will be very slow. But it will give your debugger for the debugger to catch the errors you made while drunk at 2am in the morning. :)
- Compile it in release with whatever compiler you have and debug it with whatever debugger you have.
Now you have a product. But if you want to go one extra step.
Then, and only then, you look for a better optimizing compiler. In this case, I would go for Intel C++. It takes ages to do an optimized compile. But it does provide good results for intel CPU (Not sure if the best results for AMD).

Normally it will be a compromise between getting the best running time and getting the best development time.
good advices