Remove END
This commit is contained in:
@@ -25,5 +25,3 @@ mov $0x5307, %ax
|
||||
mov $0x0001, %bx
|
||||
mov $0x0003, %cx
|
||||
int $0x15
|
||||
|
||||
END
|
||||
|
||||
@@ -66,5 +66,3 @@ jc APM_error #if the carry flag is set there was an error
|
||||
|
||||
APM_error:
|
||||
hlt
|
||||
|
||||
END
|
||||
|
||||
@@ -70,3 +70,7 @@ For when we decide to port this tutorial:
|
||||
ARM:
|
||||
|
||||
- <https://github.com/bravegnu/gnu-eprog>
|
||||
|
||||
Raspberry PI:
|
||||
|
||||
- <https://github.com/dwelch67/raspberrypi>
|
||||
|
||||
@@ -8,4 +8,3 @@ int $0x10
|
||||
PUTC($0x61)
|
||||
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -13,6 +13,5 @@ Carriage returns are needed just like in old days.
|
||||
BEGIN
|
||||
PRINT($msg)
|
||||
hlt
|
||||
END
|
||||
msg:
|
||||
.asciz "hello\n\rworld"
|
||||
|
||||
@@ -33,4 +33,3 @@ CURSOR_POSITION(0, 0)
|
||||
PUTC($0x62)
|
||||
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -29,4 +29,3 @@ PUTC($0x62)
|
||||
PUTC($0x63)
|
||||
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -18,4 +18,3 @@ int $0x10
|
||||
PUTC($0x63)
|
||||
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -15,15 +15,12 @@ Bibliography:
|
||||
|
||||
- http://wiki.osdev.org/ATA_in_x86_RealMode_%28BIOS%29
|
||||
- https://en.wikipedia.org/wiki/INT_13H
|
||||
- https://thiscouldbebetter.wordpress.com/2011/03/15/creating-a-bootable-program-in-assembly-language/
|
||||
|
||||
TODO answer:
|
||||
|
||||
- https://thiscouldbebetter.wordpress.com/2011/03/15/creating-a-bootable-program-in-assembly-language/
|
||||
- http://stackoverflow.com/questions/7716427/loading-2nd-stage-of-bootloader-and-starting-it
|
||||
- http://stackoverflow.com/questions/2065370/how-to-load-second-stage-boot-loader-from-first-stage
|
||||
- http://stackoverflow.com/questions/19381434/cannot-read-disk-sectors-in-assembly-language
|
||||
- http://stackoverflow.com/questions/15497842/read-a-sector-from-hard-drive-with-int-13h
|
||||
- http://stackoverflow.com/questions/9899577/example-for-int-13-ah-03h-interupt-assembly
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
@@ -44,7 +41,13 @@ BEGIN
|
||||
mov $2, %ah
|
||||
/* Number of sectors to read. */
|
||||
mov $1, %al
|
||||
/* Drive number. Starts at 0x80, second one is 0x81. TODO why not from 0? */
|
||||
/*
|
||||
Drive number. Starts at 0x80, second one is 0x81. TODO why not from 0?
|
||||
|
||||
The BIOS stores the right number on dl as an initial state,
|
||||
but we may be destroying it before, and are lazy to properly store it somewhere.
|
||||
http://stackoverflow.com/a/19387093/895245
|
||||
*/
|
||||
mov $0x80, %dl
|
||||
/* cylinder number */
|
||||
mov $0, %ch
|
||||
@@ -73,5 +76,4 @@ stage2:
|
||||
but let's just put it here to keep our other images smaller.
|
||||
*/
|
||||
.org 512
|
||||
END
|
||||
|
||||
|
||||
@@ -12,4 +12,3 @@ halt:
|
||||
hlt
|
||||
msg:
|
||||
.asciz "hello world"
|
||||
END
|
||||
|
||||
@@ -8,4 +8,3 @@ mov $0x00, %ah
|
||||
int $0x16
|
||||
PUTC(%al)
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -11,4 +11,3 @@ start:
|
||||
int $0x16
|
||||
PUTC(%al)
|
||||
jmp start
|
||||
END
|
||||
|
||||
@@ -13,6 +13,5 @@ Carriage returns are needed just like in old days.
|
||||
BEGIN
|
||||
PRINT($msg)
|
||||
hlt
|
||||
END
|
||||
msg:
|
||||
.asciz "hello\nworld"
|
||||
|
||||
@@ -13,4 +13,3 @@ BEGIN
|
||||
mov $0x0E40, %ax
|
||||
int $0x10
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -49,4 +49,3 @@ start:
|
||||
jmp start
|
||||
end:
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -19,4 +19,3 @@ start:
|
||||
jmp start
|
||||
end:
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -62,6 +62,5 @@ mov $0x0202, %dx
|
||||
int $0x10
|
||||
|
||||
hlt
|
||||
END
|
||||
stair:
|
||||
.asciz "a\nb\nc\nd"
|
||||
|
||||
2
common.h
2
common.h
@@ -19,8 +19,6 @@ The big ones do bloat the executable.
|
||||
/* We should set SP because BIOS calls may depend on that. TODO confirm. */ \
|
||||
mov %bp, %sp
|
||||
|
||||
#define END
|
||||
|
||||
#define CURSOR_POSITION(x, y) \
|
||||
mov $0x02, %ah;\
|
||||
mov $0x00, %bh;\
|
||||
|
||||
@@ -45,4 +45,3 @@ start:
|
||||
out %al, $0x61
|
||||
|
||||
jmp start
|
||||
END
|
||||
|
||||
@@ -33,4 +33,3 @@ loop:
|
||||
PRINT_HEX(%al)
|
||||
PRINT_NEWLINE
|
||||
jmp loop
|
||||
END
|
||||
|
||||
@@ -12,4 +12,3 @@ I am so going to make a pixel drawing program with this.
|
||||
#include "common.h"
|
||||
BEGIN
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -8,4 +8,3 @@ It likely wastes more energy? But is less prone to being interrupted than `hlt`.
|
||||
BEGIN
|
||||
loop:
|
||||
jmp loop
|
||||
END
|
||||
|
||||
40
initial_state.S
Normal file
40
initial_state.S
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Check the initial state the firmware leaves us in.
|
||||
|
||||
Could be done with GDB on the emulator, but this will also work on real hardware.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define INITIAL_STORE(x) mov % ## x, x
|
||||
|
||||
#define INITIAL_DATA(x) \
|
||||
x: .word 0;\
|
||||
x ## s: .ascii #x " = \0"
|
||||
|
||||
#define INITIAL_PRINT(x) \
|
||||
PRINT($x ## s);\
|
||||
PRINT_HEX(x);\
|
||||
PRINT_NEWLINE
|
||||
|
||||
BEGIN
|
||||
|
||||
INITIAL_STORE(ax)
|
||||
INITIAL_STORE(bx)
|
||||
INITIAL_STORE(cx)
|
||||
INITIAL_STORE(dx)
|
||||
INITIAL_STORE(cs)
|
||||
|
||||
INITIAL_PRINT(ax)
|
||||
INITIAL_PRINT(bx)
|
||||
INITIAL_PRINT(cx)
|
||||
INITIAL_PRINT(dx)
|
||||
INITIAL_PRINT(cs)
|
||||
|
||||
hlt
|
||||
|
||||
INITIAL_DATA(ax)
|
||||
INITIAL_DATA(bx)
|
||||
INITIAL_DATA(cx)
|
||||
INITIAL_DATA(dx)
|
||||
INITIAL_DATA(cs)
|
||||
@@ -39,4 +39,3 @@ handler:
|
||||
iret
|
||||
end:
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -18,4 +18,3 @@ handler:
|
||||
PUTC($0x61)
|
||||
iret
|
||||
jmp loop
|
||||
END
|
||||
|
||||
@@ -10,4 +10,3 @@ BEGIN
|
||||
handler:
|
||||
PUTC($0x61)
|
||||
int $0
|
||||
END
|
||||
|
||||
@@ -14,4 +14,3 @@ handler:
|
||||
PUTC($0x61)
|
||||
fail:
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
.POSIX:
|
||||
|
||||
BASENAME ?= bios_hello_world
|
||||
RUN ?= bios_hello_world
|
||||
IN_EXT ?= .asm
|
||||
OUT_EXT ?= .img
|
||||
|
||||
OUT := $(BASENAME)$(OUT_EXT)
|
||||
OUTS := $(patsubst %$(IN_EXT),%$(OUT_EXT),$(wildcard *$(IN_EXT)))
|
||||
RUN_FILE := $(RUN)$(OUT_EXT)
|
||||
|
||||
.PHONY: clean run
|
||||
|
||||
$(OUT): $(BASENAME)$(IN_EXT)
|
||||
all: $(OUTS)
|
||||
|
||||
%$(OUT_EXT): %$(IN_EXT)
|
||||
nasm -f bin -o '$@' '$<'
|
||||
|
||||
clean:
|
||||
rm -f '$(OUT)'
|
||||
rm -f *'$(OUT_EXT)'
|
||||
|
||||
run: $(OUT)
|
||||
qemu-system-i386 '$(OUT)'
|
||||
run: all
|
||||
qemu-system-i386 '$(RUN_FILE)'
|
||||
|
||||
bochs: all
|
||||
CYLINDERS="$$(($$(stat -c '%s' '$(RUN_FILE)') / 512))" && \
|
||||
bochs -qf /dev/null \
|
||||
'ata0-master: type=disk, path="$(RUN_FILE)", mode=flat, cylinders='"$$CYLINDERS"', heads=1, spt=1' \
|
||||
'boot: disk' \
|
||||
'display_library: sdl' \
|
||||
'megs: 128'
|
||||
|
||||
36
nasm/bios_disk_load.asm
Normal file
36
nasm/bios_disk_load.asm
Normal file
@@ -0,0 +1,36 @@
|
||||
use16
|
||||
org 0x7C00
|
||||
|
||||
; Load stage 2 to memory.
|
||||
mov ah, 0x02
|
||||
mov al, 1
|
||||
mov dl, 0x80
|
||||
mov ch, 0
|
||||
mov dh, 0
|
||||
mov cl, 2
|
||||
mov bx, stage2
|
||||
int 0x13
|
||||
|
||||
jmp stage2
|
||||
|
||||
times ((0x200 - 2) - ($ - $$)) db 0x00
|
||||
dw 0xAA55
|
||||
|
||||
stage2:
|
||||
|
||||
mov si, msg
|
||||
mov ah, 0x0E
|
||||
for_each_char:
|
||||
lodsb
|
||||
cmp al, 0x00
|
||||
je end_for_each_char
|
||||
int 0x10
|
||||
jmp for_each_char
|
||||
end_for_each_char:
|
||||
|
||||
cli
|
||||
hlt
|
||||
|
||||
msg: db 'second stage', 0
|
||||
|
||||
times ((0x400) - ($ - $$)) db 0x00
|
||||
@@ -1,6 +1,8 @@
|
||||
; Adapted from: http://blog.ackx.net/asm-hello-world-bootloader.html
|
||||
org 0x7c00
|
||||
bits 16
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
start:
|
||||
cli
|
||||
mov si, msg
|
||||
|
||||
138
nasm/protected_mode.asm
Normal file
138
nasm/protected_mode.asm
Normal file
@@ -0,0 +1,138 @@
|
||||
; 2-stage protected mode entry.
|
||||
;
|
||||
; Initially taken from:
|
||||
; https://thiscouldbebetter.wordpress.com/2011/03/17/entering-protected-mode-from-assembly/
|
||||
|
||||
use16
|
||||
org 0x7C00 ; boot sector address
|
||||
|
||||
Boot:
|
||||
;
|
||||
mov ah,0x00 ; reset disk
|
||||
mov dl,0 ; drive number
|
||||
int 0x13
|
||||
;
|
||||
mov ah,0x02 ; read sectors into memory
|
||||
mov al,0x10 ; number of sectors to read (16)
|
||||
mov dl,0x80 ; drive number
|
||||
mov ch,0 ; cylinder number
|
||||
mov dh,0 ; head number
|
||||
mov cl,2 ; starting sector number
|
||||
mov bx,Main ; address to load to
|
||||
int 0x13 ; call the interrupt routine
|
||||
;
|
||||
jmp Main
|
||||
;
|
||||
|
||||
PreviousLabel:
|
||||
|
||||
PadOutWithZeroesSectorOne:
|
||||
times ((0x200 - 2) - ($ - $$)) db 0x00
|
||||
|
||||
BootSectorSignature:
|
||||
dw 0xAA55
|
||||
|
||||
;===========================================
|
||||
|
||||
Main:
|
||||
;
|
||||
; set the display to VGA text mode now
|
||||
; because interrupts must be disabled
|
||||
;
|
||||
mov ax,3
|
||||
int 0x10 ; set VGA text mode 3
|
||||
;
|
||||
; set up data for entering protected mode
|
||||
;
|
||||
xor edx,edx ; edx = 0
|
||||
mov dx,ds ; get the data segment
|
||||
shl edx,4 ; shift it left a nibble
|
||||
add [GlobalDescriptorTable+2],edx ; GDT's base addr = edx
|
||||
;
|
||||
lgdt [GlobalDescriptorTable] ; load the GDT
|
||||
mov eax,cr0 ; eax = machine status word (MSW)
|
||||
or al,1 ; set the protection enable bit of the MSW to 1
|
||||
;
|
||||
cli ; disable interrupts
|
||||
mov cr0,eax ; start protected mode
|
||||
;
|
||||
mov bx,0x08 ; the size of a GDT descriptor is 8 bytes
|
||||
mov fs,bx ; fs = the 2nd GDT descriptor, a 4 GB data seg
|
||||
;
|
||||
; write a status message
|
||||
;
|
||||
mov ebx,0xB8000 ; address of first char for VGA mode 3
|
||||
;
|
||||
mov si,TextProtectedMode ; si = message text
|
||||
;
|
||||
ForEachChar:
|
||||
;
|
||||
lodsb ; get next char
|
||||
cmp al,0x00 ; if it's null, break
|
||||
je EndForEachChar
|
||||
;
|
||||
mov [fs:ebx],al ; write char to display memory
|
||||
;
|
||||
inc ebx ; 2 bytes per char
|
||||
inc ebx ; so increment twice
|
||||
;
|
||||
jmp ForEachChar
|
||||
EndForEachChar:
|
||||
;
|
||||
LoopForever: jmp LoopForever
|
||||
;
|
||||
ret
|
||||
;
|
||||
TextProtectedMode: db 'The processor is in protected mode.',0
|
||||
|
||||
GlobalDescriptorTable:
|
||||
|
||||
; the global descriptor table is the heart of protected mode
|
||||
; entries are used to map virtual to physical memory
|
||||
; among other things
|
||||
;
|
||||
; each descriptor contains 8 bytes, "organized" as follows:
|
||||
;
|
||||
; |----------------------2 bytes--------------------|
|
||||
;
|
||||
; +-------------------------------------------------+
|
||||
; | segment address 24-31 | flags #2 | len 16-19 | +6
|
||||
; +-------------------------------------------------+
|
||||
; | flags #1 | segment address 16-23 | +4
|
||||
; +-------------------------------------------------+
|
||||
; | segment address bits 0-15 | +2
|
||||
; +-------------------------------------------------+
|
||||
; | segment length bits 0-15 | +0
|
||||
; +-------------------------------------------------+
|
||||
|
||||
; the high-order bit of flags #2 controls "granularity"
|
||||
; setting it to 1 multiplies the segment length by 4096
|
||||
|
||||
;======================================================
|
||||
|
||||
; create two descriptors:
|
||||
; one for the GDT itself, plus a 4 gibabyte data segment
|
||||
|
||||
dw GlobalDescriptorTableEnd - GlobalDescriptorTable - 1
|
||||
; segment address bits 0-15, 16-23
|
||||
dw GlobalDescriptorTable
|
||||
db 0
|
||||
; flags 1, segment length 16-19 + flags 2
|
||||
db 0, 0
|
||||
; segment address bits 24-31
|
||||
db 0
|
||||
|
||||
; a data segment based at address 0, 4 gibabytes long
|
||||
;
|
||||
dw 0xFFFF ; segment length 0-15
|
||||
db 0, 0, 0 ; segment address 0-15, 16-23
|
||||
db 0x91 ; flags 1
|
||||
db 0xCF ; flags 2, segment length 16-19
|
||||
db 0 ; segment address 24-31
|
||||
;
|
||||
GlobalDescriptorTableEnd:
|
||||
|
||||
;===========================================
|
||||
|
||||
PadOutWithZeroesSectorsAll:
|
||||
times (0x2000 - ($ - $$)) db 0x00
|
||||
@@ -5,9 +5,9 @@ TODO get working.
|
||||
|
||||
- http://wiki.osdev.org/Journey_To_The_Protected_Land
|
||||
- http://wiki.osdev.org/Protected_Mode
|
||||
- http://stackoverflow.com/questions/28645439/how-do-i-enter-32-bit-protected-mode-in-nasm-assembly
|
||||
- https://github.com/chrisdew/xv6/blob/master/bootasm.S
|
||||
- https://thiscouldbebetter.wordpress.com/2011/03/17/entering-protected-mode-from-assembly/ FASM based. Did not word on first try, but looks real clean.
|
||||
- http://stackoverflow.com/questions/28645439/how-do-i-enter-32-bit-protected-mode-in-nasm-assembly
|
||||
|
||||
## GDT
|
||||
|
||||
@@ -61,4 +61,3 @@ cli
|
||||
gdt:
|
||||
.word 0x1234
|
||||
.long 0x12345678
|
||||
END
|
||||
|
||||
1
reboot.S
1
reboot.S
@@ -9,4 +9,3 @@ TODO why does it work?
|
||||
#include "common.h"
|
||||
BEGIN
|
||||
ljmpw $0xF000, $0XFFF0
|
||||
END
|
||||
|
||||
@@ -110,4 +110,3 @@ msg:
|
||||
/* We push the correct A forward 16 bytes in memory to compensate for the segments. */
|
||||
.fill 0x10
|
||||
.byte 'A'
|
||||
END
|
||||
|
||||
1
ss.S
1
ss.S
@@ -8,4 +8,3 @@ SS register. I think the major effect of it is that anything that uses
|
||||
#include "common.h"
|
||||
BEGIN
|
||||
hlt
|
||||
END
|
||||
|
||||
@@ -5,4 +5,3 @@
|
||||
#include "common.h"
|
||||
BEGIN
|
||||
hlt
|
||||
END
|
||||
|
||||
Reference in New Issue
Block a user