Engineer999
Engineer999

Reputation: 3945

C startup code is only written in assembly confusion

I understand that the C startup code is for initializing the C runtime environment, initializes static variables, sets up the stack pointer etc. and finally branches to main().

They say that this can only be written in assembly language as it's platform-specific. However, can't this still be written in C and compiled for the specific platform?

Function calls of course would be not possible because we "more than likely" don't have the stack pointer set up at that stage. I still can't see other main reasons. Thanks in advance.

Upvotes: 4

Views: 1427

Answers (3)

Clifford
Clifford

Reputation: 93466

A minimal C runtime environment requires a stack, and a jump to a start address. Setting the stack pointer on most architectures requires assembly code. Once a stack is available it is possible to run code generated from C source.

ARM Cortex-M devices load the stack pointer and start address from the vector table on reset, so can in fact boot directly into code generated from C source.

On other architectures, the minimal assembly requires is to set a stack pointer, and jump to the start address. Thereafter it is possible to write other start-up tasks in C ( or C++ even). Such startup code is responsible for establishing the full C runtime, so must not assume static initialisation or library initialisation (no heap or filesystem for example), which are things that must be done by the startup code.

In that sense you can run code generated from C source, but the environment is not strictly conforming until main() has been called, so there are some constraints.

Even where assembly code is used, it need not be the whole start-up code that is in assembly.

Upvotes: 4

zwol
zwol

Reputation: 140485

Most of the problem with writing early startup code in C is, in fact, the absence of a properly structured stack. It's worse than just not being able to make function calls. All of a C compiler's generated machine code assumes the existence of a stack, pointed to by the ABI-specified register, that can be used for scratch storage at any time. Changing this assumption would be so much work as to amount to a complete second "back end" for the compiler—way more work than continuing to write early startup code by hand in assembly.

Early bootstrap code, bringing up the machine from power-on, also has to do a bunch of special operations that can't usually be accessed from C, like configuring interrupts and virtual memory. And it may have to deal with the code not having been loaded at the address it was linked for, or the relocation table not having been processed, or other similar problems; these also break pervasive assumptions made by the C compiler (e.g. that it can inject a call to memcpy whenever it wants).

Despite all that, most of a user mode C library's startup code will, in fact, be written in C, for exactly the reason you are thinking. Nobody wants to write more code in assembly, over and over for each supported ISA, than absolutely necessary.

Upvotes: 7

0___________
0___________

Reputation: 67476

Startup code can be written in C language only if:

  1. Implementation provides all necessary intrinsic functions to set hardware features that cannot be set using standard C
  2. Provides mechanism of placing fragments of code and data in the specific place and in specific order (gcc support for ld linker scripts for example).

If both conditions are met you can write the startup code in C language.

I use my own startup code written in C (instead of one provided by the chip vendors) for Cortex-M microcontrollers as ARM provides CMSIS header files with all needed inline assembly functions and gcc based toolchain gives me full memory layout control.

Upvotes: 8

Related Questions