EXE files, just like any other binary file, contain a header with information in it specific to the file. Here's the
EXE file header on Windows[
^]
When a high-level compiler is used, rather than assembler, it sets the starting point to additional initialization logic, like dependencies and standard libraries' initialization. Read
this[
^] to understand it better.
Some languages, however, like C++, allow overriding that initialization, or at least in part. In VC++, for instance, there are many
pragma
and
__declspec
modifiers that allow custom compiler and/or linker behavior, plus many project configuration switches.
We absolutely can, and people do write the whole thing in assembler. In fact, back in 1993 I personally wrote a whole mini OS for 286 just in TASM, as an academical exercise. It was booting off a floppy drive, initialized DPMI, with basic memory management and UI.
However, today this cannot be a recommended approach. Only specific parts these days are written in assembler, while most of OS is written in ANSI C, though considering the progress, one can already find OS kernels written in C++, which is perhaps acceptable in some cases. But hey, who am I to judge them - look at guys writing OS in .NET:
Develop Your Own Operating System in C# or VB.NET[
^]. I personally think that's just crazy, but that's me.
There are some good tutorials out there on how to get started with your own OS in C, even on this forum:
Building your own operating system[
^] ;)