There are 2 types of compilers
- Native
- Cross compiler
Native On a PC when you write a program in high level language and compiles using let us say "Visual studio" it generates code for microprocessor on your computer. ( Most probably Intel ).
Compiler convert the high level language constructs into machine language of microprocessor.
Cross compiler
A cross compiler is compiler which converts the C code into other microprocessor /micro-controller machine language.
Now various tool like Keil uVision, IAR Embedded Workbench , Code Composer Studio which runs on PC but create machine code for micro-controller selected. Every IDE will provide list of processor families and part number which it supports and it compiles C code accordingly.
These IDE provides various features to configure your program output as per the hardware. Start up and INIT.A51 file you have mentioned will do necessary hardware initialization before main() function will start executing your program.
So when you select particular part number from device list compiler checks if compiled output can be run on part mentioned. For example : If your program requires X amount of RAM and controller has less than X amount of memory it will throw compiler error.