[Letztes Mal] "Hallo Welt! In Assemblersprache" in 1 durch C-Sprache ersetzt. Das Beispielprogramm ist hier.
Die Entwicklungsumgebung ist dieselbe wie Letztes Mal.
Wenn Sie Ihren PC einschalten, wird eine Software namens BIOS gestartet. Wenn die Geräteinitialisierung abgeschlossen ist, lädt dieses BIOS den MBR (Master Boot Record) des Startgeräts (FDD, HDD usw.) in den Speicher und überträgt die Steuerung an das Programm im MBR-Bereich. Das Programm in diesem MBR-Bereich wird als Bootstrap-Loader bezeichnet.
code16gcc.h
teilt GCC mit, dass sich das Programm im 16BIT-Modus befindet.
code16gcc.h
#ifndef _CODE16GCC_H_
#define _CODE16GCC_H_
__asm__(".code16gcc\n");
#endif
Erstellen Sie mit dem Inline-Assembler ein Programm, das "Hallo Welt!" Auf die gleiche Weise wie [Letztes Mal] ausgibt (http://qiita.com/yoshi-naoyuki/items/fb958e3c914c56baef40#2-6).
hello.c
#include"code16gcc.h"
__asm__("jmp main");
#define TEXT_COLOR_WHITE 0x07
void print(const char *s)
{
while(*s) {
//Rufen Sie die BIOS-Funktion auf und geben Sie ein Zeichen auf dem Bildschirm aus
__asm__ __volatile__ ("int 0x10" : : "a"(0x0E00 | *s), "b"(TEXT_COLOR_WHITE));
s++;
}
}
void main(void) {
print("Hello, World!");
while(1) {
//Stoppen Sie den CPU-Betrieb
__asm__ __volatile__("hlt");
}
}
Das BIOS lädt den MBR unter der Adresse 0x7C00 in den Speicher. Daher ist die Startposition des Programms 0x7C00. Die Boot-Signatur (0xAA55) entspricht einer Signatur, dass der MBR gültig ist. Ohne die Boot-Signatur wird der MBR als ungültig behandelt. Die Boot-Signatur befindet sich in MBR 510-511 Byte. Die Speicheradresse der Startsignatur lautet Adresse 0x7DFE (0x7C00 + 510 Byte = 0x7DFE).
linker.ld
ENTRY(main);
SECTIONS
{
/*Startposition des Programms*/
. = 0x7C00;
.data : { hello.o; }
/*Boot-Signatur*/
. = 0x7DFE;
.sig : { SHORT(0xaa55); }
}
Erstellen Sie eine Objektdatei (hello.o), in der die Standardinformationen zur Bibliotheksverknüpfung (z. B. Debuginformationen) entfernt sind.
#kompilieren
gcc -m32 -ffreestanding -fno-common -fno-builtin -fomit-frame-pointer -O2 -c -o hello.o hello.c
Erstellen Sie eine Binärdatei (hello.bin) aus einer Objektdatei (hello.o) mit einem Linker.
#Erstellen einer Binärdatei
ld -m elf_i386 -s -static -Tlinker.ld -nostdlib -nmagic --oformat binary -o hello.bin hello.o
Schreiben Sie die Binärdatei auf die gleiche Weise wie Letztes Mal auf das Disketten-Image. Wenn Sie QEMU ausführen und die Ausgabe "Hello, World!" Ausgegeben wird, ist dies erfolgreich.
#Starten Sie und verbinden Sie sich mit Vagrant
host$ vagrant up
host$ vagrant ssh
#Beispielprogramm ausführen
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' ])
Lassen Sie uns die C-Sprache in die Assemblersprache konvertieren und sie mit dem Programm von Last time vergleichen.
Der folgende Befehl erstellt hello.s
aus hello.c
.
cd /vagrant/hello-c-optimization
rake hello.s
Das folgende Programm entfernt unnötige Anweisungen (.xxxx) zur besseren Lesbarkeit. Die Syntax unterscheidet sich geringfügig zwischen den von NASM und GCC ausgegebenen Assemblersprachen.
/vagrant/hello-c-optimization/hello.s
.file "hello.c"
.intel_syntax noprefix
.code16gcc
jmp main
print:
push ebx
mov edx, eax //Stellen Sie die Startadresse der Zeichenfolge im EDX-Register ein
movzx eax, BYTE PTR [eax] //Holen Sie sich ein Zeichen aus der Zeichenfolge und legen Sie es im EAX-Register fest
test al, al
je .L1
mov ebx, 7 //Textfarbe (weiß)(0x07)
.L4:
movsx eax, al
or ah, 14 //Teilen Sie dem BIOS eine Einzelzeichenanzeige mit(0x0E)
int 0x10 //Rufen Sie eine Funktion im BIOS auf. Video-Interrupt aufrufen.
add edx, 1 //Inkrementieren Sie das EDX-Register
movzx eax, BYTE PTR [edx] //Holen Sie sich ein Zeichen aus der Zeichenfolge und legen Sie es im EAX-Register fest
test al, al
jne .L4
.L1:
pop ebx
ret
.LC0:
.string "Hello, World!"
main:
mov eax, OFFSET FLAT:.LC0 //Stellen Sie die Startadresse der Zeichenfolge im EAX-Register ein
call print
.L8:
hlt
jmp .L8
Recommended Posts