A bare-metal x86-cross-compiler on Mountain Lion

I wanted to create a bare-metal program for an Intel-x86 processor. The program is used in a chapter called The Bare Metal in the book Into Embedded.

On an Ubuntu Linux host I could use gcc, together with a linker script, to accomplish the task. I could then run the program using Bochs.

On a Mac Mountain Lion host, the above method did not work out of the box, due to ld not being the GNU linker.

In addition, gcc was not GNU gcc either.

I searched the net and found this interesting page by M3 Operating System Development where it was described how to build an i386 cross-compiler. I thought that this could be a way to create a compiler for bare-metal programs with no OS-dependencies – which was desirable since the bare-metal program was to be evolved into an OS by itself.

Problem arose, however, since the pre-installed gcc on my Mac could not build the i386-cross-gcc.

I searched again, and found this eminent page by Solarian Programmer where it is described how to build a GNU gcc compiler.

I downloaded the gcc 4.7.2 sources from the GNU ftp repository.

Then, following the instructions, however leaving out the choice of building a compiler for Fortran and also changing the gcc version from 4.7.1 to gcc 4.7.2, I was able to build a native GNU gcc compiler.

The newly built native gcc could then be set to the default gcc by issuing the command

export PATH=/usr/gcc-4.7.2/bin:$PATH

Then, returning to the instructions for building an i386-cross-gcc, I started with downloading


from the GNU binutils repository.

I created a destination directory for the cross compiler, by doing

sudo mkdir /usr/local/i386elfgcc/

The binutils could then be unpacked, configured, and built, using the commands

tar zxvf binutils-2.23.tar.gz
mkdir build-binutils
cd build-binutils/
../binutils-2.23/configure --target=i386-elf --prefix=/usr/local/i386elfgcc
sudo make install

I then built gcc, using inspiration also from this OS development wiki, by issuing the commands

tar xvjf gcc-4.7.2.tar.bz2
mkdir build-gcc
cd build-gcc
../gcc-4.7.2/configure --target=i386-elf --prefix=/usr/local/i386elfgcc --with-gnu-as --with-gnu-ld --disable-libssp --enable-languages=c --without-headers
make all-gcc
sudo make install-gcc

After having added /usr/local/i386elfgcc/bin to the PATH environment variable I was able to compile and link a bare metal program.

The program consists of three C-files, which I could compile using the commands

i386-elf-gcc -Wall -c screen_output.c
i386-elf-gcc -c -Wall -DBUILD_X86_FD_TARGET src/bare_metal.c -o obj/bare_metal_x86_fd_target.o
i386-elf-gcc -c -Wall -DBUILD_X86_FD_TARGET src/console.c -o obj/console_x86_fd_target.o

The program could then be linked, using a command where also startup code, written in assembly and assembled using NASM resulting in the object file start_code.o, as

i386-elf-ld -T arch/x86_fd_target/link.ld --oformat=elf32-i386 -melf_i386 arch/x86_fd_target/start_code.o arch/x86_fd_target/screen_output.o -o prog_x86_fd_target.elf obj/console_x86_fd_target.o obj/bare_metal_x86_fd_target.o

Finally, the file prog_x86_fd_target.elf needs to be converted from ELF format to raw binary format. This can be done using the command

i386-elf-objcopy -O binary prog_x86_fd_target.elf prog_x86_fd_target.bin

As a last step, a binary bootable image for a floppy-disc drive can be created, by concatenating a FAT12 boot sector, a defined number of empty FAT12-sectors, and the binary file created by the i386-elf-objcopy command.

The concatenation is done as

cat arch/x86_fd_target/boot.bin arch/x86_fd_target/b_32_512.bin prog_x86_fd_target.bin > arch/x86_fd_target/a.img

The program can now be run, using Bochs, by giving the command

bochs -f arch/x86_fd_target/bochsrc.txt -q

Installing an ARM cross-compiler on Mac Mountain Lion

Here I will describe my installation of an ARM cross compiler, on a MacBook Air with Mac OS Mountain Lion.

After some searching on the net I decided to try the YAGARTO toolchain.

Navigating to the download place for Mac, I downloaded the file


Using this file however led to an error, saying

selected processor does not support requested special purpose register -- `mrs r0,cpsr'

I reverted to an older version, found at YAGARTO’s Sourceforge page. This led to download of the file


Double-clicking on this downloaded file, I was able to install the toolchain.

I then added the following changes

export ARM_GCC_LOCATION=/Users/oladahl/yagarto/yagarto-4.6.2/bin

to my setup script, where I also set up other environment variables.

Now I can start programming for ARM!

As an example, I can compile, link, and run the example described in Chapter The Bare Metal in the book Into Embedded.

Installing an ARM cross compiler on Ubuntu

Here I will describe my installation of an ARM cross compiler, on an x86 machine with Ubuntu Linux.

Updates to this post

  • July 12, 2013 – changed to a later version of the Sourcery ARM compiler – now using version 2013.05-23
  • March 1, 2013 – changed to a later version of the Sourcery ARM compiler – now using version 2012.09-63

I had decided to use the Sourcery ARM compiler, formerly from CodeSourcery and now from Mentor.

I go to the page


at which I decide to use the EABI release for ARM processors.

Then, I continue to the installation page for the ARM EABI version.

After having created an account (this was my first time here) and then logging in, I get an e-mail with a download link from which I can proceed to a page where I can download the IA32 GNU/Linux Installer. Doing this results in download of a file named arm-2013.05-23-arm-none-eabi.bin.

I make the file executable by doing

chmod +x arm-2013.05-23-arm-none-eabi.bin

and then I run the file, using the command


This command results in an error message, and I am instructed to issue the command

sudo dpkg-reconfigure -plow dash

and then answer the question that comes up as instructed by the error message.

Now, again running the command


results in the installation being started. After having gone through steps involving reading and accepting license agreements, followed by a decision to not create any symbolic links, and to not send anonymous information about usage of the ARM compiler, the installation is complete.

As a last step, I modify the PATH environment variable using the commands (where /home/ola is my home directory)

export ARM_GCC_LOCATION=/home/ola/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin

I put the above two lines in a setup file, called setup.sh, that I run every time I want to use the ARM toolchain.

Now I can start programming for ARM!

As an example, I can compile, link, and run the example described in Chapter The Bare Metal in the book Into Embedded.