HiveBrain v1.2.0
Get Started
← Back to all entries
patternMajor

The loaderless bootloader

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
loaderlessthebootloader

Problem

I began this month with trying to discover how shellcode is made. My search led me to wanting to learn assembly, so I wrote a simple bootloader with NASM:

```
bits 16 ; 16 bit real mode
org 0x7C00 ; loader start in memory

start: jmp main ; goto main

bgetkey: mov ax, 0 ; clear register a
mov ah, 0x10 ;
int 16h ; interrupt bios keyboard
ret ; return
.buf dw 0 ; buffer size one word

prints: pusha ;
.loop: mov ah, 0x0e ;
mov al, [si] ;
cmp al, 0 ; check for null terminator
jz print_end ; stop printing
mov bh, 0x00 ;
mov bl, 0x07 ;
int 0x10 ; interrupt bios tty
inc si ; next character
jmp .loop ; jump beginning
print_end: popa ;
ret ; return

main: mov ax, 0x0000 ; clear register a
mov ds, ax ;
mov si, welcome ; copy welcome string pointer
call prints ; print string
newinput: mov bx, mem ; set register b to memory start
add bx, word 2 ; increment by size of memory ptr
mov word [mem], bx ; set pointer at first memory byte
type: mov si, qbuf ; set byte buffer ptr for printing
call bgetkey ; capture keyboard input
mov [qbuf], al ; copy key byte to buffer

Solution

Lots of review of the raw mechanics of your code. Not much review of the design. So here are just a few design tips.

Use BPBs, because other people will.

start: jmp main ; goto main

There are two reasons that Volume Boot Record programs do this. The first and foremost is in order to skip over an embedded BIOS Parameter Block. You may not think that you need a BPB in your volume. You almost certainly will. Others have thought that over the years, and later been bitten when they do things like not have a BPB and use tools from operating systems that require that various types of partition have a BPB in the VBR. It bit IBM in the OS/2 Boot Manager. It will bite you.

The second is that there are even tools (broken ones, that are fortunately not in wide use any more) that key off the first instruction in a VBR, expecting it to be a jmp.

Will your code ever be run on an original 8088 manufactured in 1979?


Note that the cli and the sti are super important.

But not for the reason stated. They stop interrupts from occurring in the window where you have loaded only half of ss:sp, and the stack pointer is thus invalid. This piece of 808x wisdom has been unnecessarily and erroneously extended to the other segment registers in that answer, even though there are no accompanying offsets being loaded with those other segments. In truth, those other registers are not expected to have any particular values by interrupt handlers, and you don't need to temporarily disable interrupts in order to manipulate them. 8086 "far" memory model DOS programs manipulate ds and es all of the time without masking interrupts, just fine.

And the importance is overstated. Since the 8088, a mov ss has implicitly caused interrupts (even some that cli cannot mask) to be deferred for one instruction, so that one can slip in a mov sp immediately after it and the two instructions will be implicitly interrupt-safe without an explicit cli/sti pair. (Early 8088s had a bug, but the 8088 reference manual documented this as the behaviour. It's still in the Intel reference manuals today.) Since the 80386, we've had the lss esp instruction that loads the register pair in one instruction.

Interesting historical perspective

In PC Magazine in 1987 Robert L. Hummel called the 8088 bug "a serious bug that should be attended to" and explained the (by then already folkloric) workaround of a cli and sti pairing. In fact Intel had fixed the bug in 1981. The 80386 had arrived in 1985. Thirty years later people are still handing around folk rules for coding this stuff, which have even become distorted.

Exit properly.

hlt ; halt the cpu
welcome db "boot", 0x0A, 0x0D, 0x00

Congratulations! You just executed a prompt string as code.

The IBM PC Compatible firmware provides two software interrupts for properly "exiting" a bootstrap program back to the firmware. The BIOS Boot Specification explains their use. Use them.

Further reading

  • Jonathan de Boyne Pollard (2006) The PC/AT boot process. Frequently Given Answers.



  • Jonathan de Boyne Pollard (2011). A PC/AT-style MBR bootstrap program for EFI partitioned discs. Softwares.



  • Jonathan de Boyne Pollard (2006). All about BIOS parameter blocks. Frequently Given Answers.



  • Jonathan de Boyne Pollard (2006) The meaning and use of the OEM Name field in volume boot blocks. Frequently Given Answers.



  • Will Fastie (September/October 1983). "Tracing a Bug in the 8088". PC Tech Notebook 4. p. 106



  • Sergei Kiselev (2011) "Stack change race condition". Historical Notes.



  • Robert L. Hummel (1987-12-08). "PC Tutor: Defective 8088 chips". PC Magazine. Volume 6 Issue 21. ISSN 0888-8507. Ziff-Davis. p.492.



  • Compaq Computer Corporation; Phoenix Technologies Ltd; Intel Corporation. BIOS Boot Specification 1996-01-11.

Context

StackExchange Code Review Q#94220, answer score: 27

Revisions (0)

No revisions yet.