Hello, World! In the bootstrap loader area

Introduction

[Last time] Replaced "Hello, World! In assembly language" in 1 with C language. The sample program is here.

The development environment is the same as Last time.

Bootstrap loader area

When you turn on your PC, software called BIOS starts. When the device initialization is completed, this BIOS loads the MBR (Master Boot Record) of the boot device (FDD, HDD, etc.) into the memory and transfers control to the program in the MBR area. The program in this MBR area is called the bootstrap loader.

ブートローダー.png

Creating a program

code16gcc.h tells GCC that the program is in 16BIT mode.

code16gcc.h


#ifndef _CODE16GCC_H_
#define _CODE16GCC_H_
__asm__(".code16gcc\n");
#endif

Using the inline assembler, create a program that outputs "Hello, World!" In the same way as Last time.

hello.c


#include"code16gcc.h"

__asm__("jmp main");

#define TEXT_COLOR_WHITE 0x07

void print(const char *s)
{
  while(*s) {
    //Call the BIOS function and output one character on the screen
    __asm__ __volatile__ ("int 0x10" : : "a"(0x0E00 | *s), "b"(TEXT_COLOR_WHITE));
    s++;
  }
}

void main(void) {
  print("Hello, World!");

  while(1) {
    //Stop CPU operation
    __asm__ __volatile__("hlt");
  }
}

The BIOS loads the MBR at address 0x7C00 in memory. Therefore, the start position of the program is 0x7C00. The boot signature (0xAA55) is like a signature that the MBR is valid, and without the boot signature the MBR is treated as invalid. The boot signature is located in the MBR 510-511 bytes. The address in memory of the boot signature is address 0x7DFE (0x7C00 + 510 bytes = 0x7DFE).

linker.ld


ENTRY(main);
SECTIONS
{
  /*Program start position*/
  . = 0x7C00;
  .data : { hello.o; }
  /*Boot signature*/
  . = 0x7DFE;
  .sig : { SHORT(0xaa55); }
}

Creating a binary file

Create an object file (hello.o) with the standard library link information (debugging information, etc.) removed.

#compile
gcc -m32 -ffreestanding -fno-common -fno-builtin -fomit-frame-pointer -O2 -c -o hello.o hello.c

Create a binary file (hello.bin) from an object file (hello.o) using a linker.

#Creating a binary file
ld -m elf_i386 -s -static -Tlinker.ld -nostdlib -nmagic --oformat binary -o hello.bin hello.o

Write the binary file to the floppy disk image in the same way as Last time. If you run QEMU and the output "Hello, World!" Is output, it is successful.

kobito.1402210360.448893.png

Execution of sample program

#Launch and connect to Vagrant
host$ vagrant up
host$ vagrant ssh

#Execution of sample program
vagrant$ cd /vagrant/hello-c
vagrant$ rake

Rakefile


OBJECT_FILE = 'hello.o'
BINARY_FILE = 'hello.bin'
IMAGE_FILE  = 'floppy.img'
LINKER_FILE = 'linker.ld'

task :default => :run

task :run => [ BINARY_FILE, IMAGE_FILE ] do
  sh "dd status=noxfer conv=notrunc if=#{BINARY_FILE} of=#{IMAGE_FILE}"
  sh "qemu -boot a -fda #{IMAGE_FILE} -curses -monitor stdio"
end

file BINARY_FILE => [ LINKER_FILE,  OBJECT_FILE ] do
  sh "ld -m elf_i386 -s -static -T#{LINKER_FILE} -nostdlib -nmagic --oformat binary -o #{BINARY_FILE} #{OBJECT_FILE}"
end

file IMAGE_FILE do
  sh "qemu-img create -f raw #{IMAGE_FILE} 1440K"
end

rule '.o' => '.c' do |t|
  sh "gcc -masm=intel -m32 -ffreestanding -fno-common -fno-builtin -fomit-frame-pointer -O2 -c -o #{t.name} #{t.source}"
end

rule '.s' => '.c' do |t|
  sh "gcc -S -masm=intel -m32 -ffreestanding -fno-common -fno-builtin -fomit-frame-pointer -O2 -c -o #{t.name} #{t.source}"
end

require 'rake/clean'
CLEAN.include([ '*.bin', '*.img', '*.o' ])

bonus

Let's convert C language to assembly language and compare it with the program of Last time. The following command creates hello.s from hello.c.

cd /vagrant/hello-c-optimization
rake hello.s

The following program removes unnecessary directives (.xxxx) for readability. The syntax is slightly different between the assembly language output by NASM and GCC.

/vagrant/hello-c-optimization/hello.s


    .file   "hello.c"
    .intel_syntax noprefix
    .code16gcc

    jmp main
print:
    push    ebx
    mov edx, eax                 //Set the start address of the string in the EDX register
    movzx   eax, BYTE PTR [eax]  //Get one character from a string and set it in the EAX register
    test    al, al
    je  .L1
    mov ebx, 7                   //Text color (white)(0x07)
.L4:
    movsx   eax, al
    or  ah, 14                   //Tell the BIOS a single character display(0x0E)
    int 0x10                     //Call a function in the BIOS. Call video interrupt.
    add edx, 1                   //Increment the EDX register
    movzx   eax, BYTE PTR [edx]  //Get one character from a string and set it in the EAX register
    test    al, al
    jne .L4
.L1:
    pop ebx
    ret
.LC0:
    .string "Hello, World!"
main:
    mov eax, OFFSET FLAT:.LC0    //Set the start address of the character string in the EAX register
    call    print
.L8:
    hlt
    jmp .L8

Recommended Posts

Hello, World! In the bootstrap loader area
"Hello World" in Java
Hello world in node.js
Hello World in Java
Display "Hello World" in the browser using Java
Display "Hello World" in the browser using Java
Spring Boot Hello World in Eclipse
Hello World in java in eclipse now
hello, world in Vanilla Java-EHW2018 "MVP"
Hello world in Java and Gradle
[Practice! ] Display Hello World in Spring Boot
"Hello, World!" With Kotlin + CLI in 5 minutes
Programming for the first time in my life Java 1st Hello World
Output Hello World in kotlin's simple main function
Hello World with JavaFX 11 (OpenJFX) in Liberica JDK 11
Read "Hello world"
Java, Hello, world!
Returning to the beginning, Java-Kisama mocked Hello World-
Java Hello World
[Introduction] Display Android Studio Hello World on the emulator
The world of clara-rules (2)
Java Learning (1)-Hello World
Read System.out.println ("hello, world")
Let's write Hello World
The world of clara-rules (4)
The world of clara-rules (1)
The world of clara-rules (3)
Studying Java-Part 1-Hello World
The world of clara-rules (5)
Hello World on WebAssembly
Hello World with Micronaut
[Introduction to MVEL] Aiming to be the best MVELer in the world
Hello World with Ruby extension library for the time being