How to create an executable file to run on a specific processor architecture (instead of a specific OS)?

Therefore, I take my C ++ program in Visual Studio, compile, and it spits out a nice little EXE file. But EXEs will only work on windows, and I've heard a lot about how C / C ++ compiles into assembly language that runs directly on the processor. The exe is launched using windows, or I may have a program that makes an executable that runs on a Mac. But am I not compiling C ++ code into assembly language that is processor specific?

My impressions:

  • I guess probably not. I know that there is an Intel C ++ compiler, so that it would make build code for a specific processor? EXEs work on windows, so they use many things that are already configured, from graphic packages to the massive .NET framework. An executable file with a processor will literally start from scratch, only with a set of processor instructions.

  • Will this executable be file? We can launch windows and open them, but then it will only control switching to the processor? I assume that this executable will be something like an operating system, since it must be run before something else is loaded, and will only have a processor instruction to “use”.

+6
c ++ c compilation executable processor
source share
10 answers

Think about what run means ...

Something must load binary codes into memory. This is an OS..EXE function or binary executable file or package or something else, formatted in a very OS-specific way so that the OS can load it into memory.

Something has to turn control over these binary codes. There OS again.

I / O routines (in C ++, but this is true in most places) is just a library that encapsulates the OS API. Drat that OS is everywhere.

Recollection .

In the old days (yes, I'm so old) I worked on machines that did not have an OS. We also did not have C.

We wrote machine codes using tools such as “assemblers” and “linkers” to create large binary images that we could load into the machine. We had to download these binary images through a painful boot process.

We will use the keys on the front panel to load enough code into the memory to read a convenient device, such as a paper tape with paper tape. This would download a small portion of the fairly standard bootloader software. (We used mylar tape so that it does not wear out.)

Then, when we had this link loader in memory, we could copy the tape that we prepared earlier using assembler.

We wrote our own device drivers. Or we used library procedures that were in their original form, punched on paper tapes.

The patch was actually patched with pieces of paper tape. Plus, since there were minor errors, we would have to adjust the memory image based on handwritten instructions - patches that were not placed on the tape.

Later we had a simple OS with simple APIs, simple device drivers, and several utilities, such as the “file system”, “editor”, and “compiler”. It was a language called Jovial, but we also sometimes used Fortran.

We had to solder the serial interface cards so that we could connect the device. We had to write device drivers.

Bottom line .

You can easily write C ++ programs that do not require an OS.

  • Learn about the hardware BIOS (or similar BIOS) that are part of your chipset. Most modern hardware has a simple OS connected to ROM that performs a self-test (POST), loads a few simple drivers, and finds boot blocks.

  • Learn how to write your own boot block. This is the first correct “software” that loads after POST. This is not so difficult. You can use various partitioning tools to force your boot block program to disk, and you will have full control over the hardware. No OS.

  • Find out how GRUB, LILO, or BootCamp launch the OS. It's not hard. Once they load, they can load your program, and you are turned off and running. This is a little easier because you are creating the type of partition that the bootloader wants to load. Based on the Linux kernel, you will be happier. Do not try to understand how Windows boots - it is too complicated.

  • Read the ELF. http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

  • Find out how device drivers are recorded. If you are not using the OS, you will need to write device drivers.

+16
source share

The problem is that the OS really does a lot to run your programs. The EXE file itself contains the header information that Windows recognizes, identifying itself as an EXE file. Your application does everything from file system access to memory allocation, through the OS.

But yes, you can run applications compiled for Windows / intel on other platforms without emulation. If you want to run EXE on Mac or UNIX, you will need to install some more software to do the work that Windows will do to run your program - see the project "Wine".

+6
source share

What you are talking about is what is known in the embedded world as a bare metal application. They are very common for things like ARM Cortex-M3, which is included (say) in a debit card authentication unit or an interactive toy and does not have enough memory or the ability to run a full operating system. Thus, instead of the "ARM / Linux" compiler, which would compile the Linux application on the ARM processor, you get the "ARM bare-metal" compiler, which compiles everything that needs to be run on the ARM processor without an operating system. (As an example, I use ARM, not x86, because currently, pure x86 metal applications are really very rare.)

As stated in your question and other answers, your application will need to do some things that would otherwise take care of the operating system.

First, it needs to initialize the memory system, interrupt vectors, and various other bits of the board. This is usually what the bare metal compiler does for you, although if you have a weird board, you may need to tell her how to do it. This gets things from where the board turns on at the point where your main () function starts.

Then you need to interact with things outside the CPU and RAM. The operating system includes all kinds of functions for this: disk I / O, screen output, keyboard and mouse input, networking, etc. Etc. Etc. Without an operating system, you should get it from somewhere else. You can get some of these libraries from your equipment manufacturer; for example, the board I recently played with has a 40x200-pixel LED screen, and it includes a library with code to enable this and set individual pixel values ​​on it. And there are several companies that sell libraries to implement the TCP / IP stack and the like, to create networks or something else.

Consider, for example, that this makes even basic printf difficult to execute. When you have an operating system, printf simply sends a message to the operating system that says “put this line on the console”, and the operating system finds the current cursor position on the console and does whatever it takes to figure out which pixels to change on the screen and which processor instructions to use to change these pixels to do this.

Oh, and we mentioned that you first need to figure out how to get the program into the CPU? A typical computer has a bit of programmable ROM that will load instructions from the moment it starts. On x86, this is the BIOS, and it usually already contains a handy program that starts the processor, sets up the display, looks for disks and loads the program from the disk that it finds. In an embedded system, which usually runs your program, which means that you need to somehow place your program. Often this means that you have a device called a "debugger" physically attached to the built-in board that loads the program, and can also do things that let you pause the processor and determine what its state is, so you can step through your a program as if you were running it in a software debugger on your computer. But I'm distracted.

In any case, in order to answer your second question, this executable file that you create will be stored in this ROM on the built-in board - or maybe you just saved it in the ROM (which is pretty small after that) and save the rest part on the flash drive, and a bit in the ROM will contain instructions to get the rest of it from the flash drive. It will probably be stored as a file on your main computer (that is, on a computer running Linux or Windows, where you create it), but it's just for storage, it won’t work there.

You will notice that when you have many of these libraries together, they do an honest part of what the operating system does, and there is such a space between a bunch of libraries and the real operating system. In this space what is called RTOS - the "real operating system time. " The smaller ones are actually just collections of libraries that work together to run all operating systems, and sometimes also include material so that you can run multiple threads at the same time (and then you can use different threads as different programs) - - although all this is all compiled into the same compiled “program”, and RTOS is nothing but the library that you included. Larger ones begin to store parts of the code in different places, and I think some of them can even load code snippets from disks - just like Windows and Linux when the program starts. This is a kind of continuum, not either / or.

The FreeRTOS system is an open source RTOS that targets the smaller end of the RTOS space; they can be a good place to take a look at some of them if you are more interested. They have some examples of x86 applications that will give you an idea of ​​which x86 systems will run the program based on a simple or RTOS application and how you will compile something to run on one; link here: http://www.freertos.org/a00090.html#186 .

+5
source share

The computer is not a CPU. To do anything useful, the processor must be connected to memory and I / O controllers and other devices. The OS takes care of abstracting all this from running programs. So, if you want to write a program that works without an OS, your program will have to replicate at least some of the OS's functions: intercepting from the BIOS during the boot process, initializing devices, communicating with the disk controller to download the code, and data communicating with the display controller, to show information to the user, communicating with the keyboard controller and mouse controller, to read user input, etc. etc. etc.

If you do not create an embedded system with specialized equipment, this makes no sense. In addition, the launch of your program will mean that the user will have to refuse to start other programs. Although this may be acceptable for ATM today or WordStar in 1984, these days people are unhappy that they cannot check their emails while listening to music.

+3
source share

Of course they exist. They are called cross-compilers . For example, how can I program the iPhone platform using Xcode.

A related type of compiler is one that compiles for a virtual platform. The way Java works .

+1
source share

Any given compiler / toolkit creates code for a specific combination of processors and OS. Thus, your Visual Studio compilation example creates code for x86 / Windows. This .EXE will only work on x86 / Windows, not (for example) ARM / Windows (as used by some cell phones).

To create code for a combination of processors and operating systems other than the one on which the compiler is running, what is commonly called a cross-compiler is required. If you have a full professional Visual Studio subscription, you can get an ARM cross-compiler that will allow you to create ARM / Windows.EXE files that will not work on your desktop computer, but will work on an ARM / Windows or palmtop mobile phone .

+1
source share

Yes, you can make an executable file that runs on the bare metal of the processor. Obviously, the kernel of the operating system. The main thing you need to do is create an executable file that does not use any libraries. However, the “no library” restriction includes the standard C library! Thus, this means the absence of malloc, printf, etc. You should basically be your own OS and manage the memory and I / O yourself. This will inevitably require fair work directly in the assembly at a certain stage.

You also lose several other luxuries, such as main (), which cannot be the starting point for your program, since main () is what the OS and the C runtime invoke.

0
source share

Absolutely! This is what embedded programming is. As many probably have already said that the operating system is quite a bit for you. And even in an embedded world without an operating system, a number of development tools will provide a startup code for the processor to work enough to get to your program. Some / many provide full-featured C / C ++ libraries so that you can call functions like memcpy (), and sometimes malloc () and printf ().

You can provide each line of code and each instruction, and not use the development tool package, but, nevertheless, use a compiler, for example, gcc. Some binary formats are common to those that run on operating systems such as elf. You can execute elf files on Linux, but also have firmware in the binary elf system. The processor cannot execute the elf in this format, but any programs in which the bootable release or ram in some cases will extract the binary program from the elf file, unlike the operating system that extracts the program to run from the elf file. EXE is not one of these file formats. Your favorite Windows application compiler is probably not a built-in compiler, although sometimes you can use it to work with a high-level language, and then use an alternative assembler and linker. More work than usual. For example, you write a function in C (which does NOT make any library or system calls), compile this for an object. Write your own or find a utility to extract the compiled binary from this object, convert it to another object format or to assembler (disassemble). Add a startup code and another assembly to it. Assemble and connect everything together as a firmware. I did this once with Microsoft's built-in visual C to see how it is measured before other compilers, it was terrible, but, of course, it was not worth the hacking effort to get a way out.

Each processor from your computer to your mobile phone or microwave oven also has a download code. This code does not work on the operating system. This code uses the same or similar compilers as the operating system applications. For some devices, this code places the processor and memory, as well as peripheral devices with a microcircuit, and turns them off in a state in which the operating system can be started. From there, the operating system begins to operate. On your computer, it will be the BIOS, followed by the bootloader, and then, ultimately, the operating system, dos, windows, linux, etc.

0
source share

The main problem is the file format. PE is very different from ELF (used on Unix-like systems). A valid PE program cannot be a valid ELF. Thus, you either load the binary file dynamically with different starts, or you need to refuse.

In addition, with knowledge of the OS services, the values ​​of the registers at startup, etc., your code can probably easily and reliably detect which OS you are running and operating accordingly (some malicious programs do just that). Another problem is reusing code in place of two or more different programs in the same binary. Basically, you will need to write an emulator, at least for the services you need.

0
source share

Do not forget about Windows libraries as well. Look at QT and GTK +

0
source share

All Articles