; Author: Spencer Shimko ; Program: Boot dump ; Date: 4/21/04 ; Compiled using nasm -f bin boot.asm ; Written to floppy with dd if=boot of=/dev/fd0 ORG 0x7C00 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; begin "main" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; print header, read sector, print sectors CALL printh CALL read CALL prints ;; provided by Prof. Squire ; wait for 'any key': done: LEA SI, [reboot] CALL pstring CALL wait4me ; store magic value at 0040h:0072h to reboot: ; 0000h - cold boot. ; 1234h - warm boot. MOV AX,0040h MOV DS,AX MOV word[0072h],0000h ; cold boot. JMP 0FFFFh:0000h ; reboot! ;; end provided by squire ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; end "main" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; begin functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; function print header ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printh: LEA SI, [head] CALL pstring RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; function reads sectors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; read: ; INT 13,2 - Read Disk Sectors MOV AH, 2 ; AL = number of sectors to read (1-128 dec.) MOV AL, 2 ; CH = track/cylinder number (0-1023 dec., see below) MOV CH, 0 ; CL = sector number (1-17 dec.) MOV CL, 1 ; DH = head number (0-15 dec.) MOV DH, 0 ; DL = drive number (0=A:, 1=2nd floppy, 80h=drive 0, 81h=drive 1) MOV DL, 0x0080 ; ES:BX = pointer to buffer MOV BX, 0x0000 MOV ES, BX MOV BX, 0xA000 INT 0x13 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; function print a screen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; prints: MOV cx, 0 printl: CALL printline ; basically a modulus operator to keep output on screen and readable MOV dx, 0 MOV ax, cx MOV di, 256 ; stop every 256 bytes DIV di CMP dx, 0 ; if remainder is zero... JNE printl CMP cx, 1024 JE printd CALL wait4me JMP printl printd: RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; function print line ; prints address, hex dump, ascii values ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printline: LEA bx, [0xA000] ADD bx, cx ; print addy MOV dx, bx SUB dx, 0xA000 MOV di, 0xE000 PUSH dx CALL printbyte ;addy is 2 bytes CALL printbyte POP dx CALL printspace CALL printspace ; perform hex conversion and print PUSH bx ; save some values PUSH cx MOV cx, 16 ; we're printing 16 characters printlp1: MOV dh, byte[bx] ; get next byte LEA di, [0xE000] ; create buffer for chars CALL printbyte ; print the hex CALL printspace ; print a space INC bx ; get to the next char LOOP printlp1 ; loop (duh) CALL printspace ; print a space POP cx ; restore stack frame POP bx ; print right side (non-control ascii characters) PUSH cx LEA di, [0xE000] ; buffer for converted chars MOV cx, 16 ; we're printing 16 characters printascii: ; once again stolen from Squire MOV al, byte[bx] CMP al, 32 JGE pok MOV al, '.' pok: CMP al, 126 JLE uok MOV al, '.' uok: ; end stolen code ; all characters are now printable MOV byte[di], al ; put converted(?) char into buffer INC di ; setup input and ouput for next iteration INC bx LOOP printascii POP cx MOV byte[di], 0 ; need null terminated string.... LEA si, [0xE000] CALL pstring ; actually print the converted string ; print newline... had it as a function but only made 1 call so inefficient? LEA si, [nl] CALL pstring ; increment the sector count (we deal with 2 bytes each time) ADD cx, 16 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; prints hex dump of 1-byte (2 hex characters) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printbyte: PUSH bx ; save some registers PUSH cx MOV cx, 2 ; 1 byte = 2*4bit hex digits so loop nybble: MOV ax, 0 SHLD ax, dx, 4 ; snag next 4 bits SHL dx, 4 ; advance since last instr didn't do it ADD al, 48 ; convert to hex digit CMP al, 57 JLE ovr ADD al, 7 ovr: MOV byte[di], al ; store char INC di LOOP nybble ; get next nybble MOV byte[di], 0 ; null terminated string SUB di, 2 ; decrement to begining of string for printing LEA si, [di] CALL pstring ; print byte POP cx POP bx RET ; print string code from Prof. Squires posted bootreg.asm pstring: ; 'si' comes in with string address PUSH bx PUSH ax MOV bx,0 ; write to display MOV ah,0Eh ; screen function prs: MOV al,[si] ; get next character CMP al,0 ; look for terminator JE finpr ; zero byte at end of string INT 10h ; write character to screen. INC si ; move to next character JMP prs ; loop finpr: POP ax POP bx RET ; finished this line ; end stolen code ;-) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; a "pause" function to wait for a key press ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; stop and wait for any key wait4me: MOV AH, 0 INT 0x16 RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; a print function to print a space ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; printspace: LEA si, [spaces] CALL pstring RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; end functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; data section ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .data nl: db 13,10,0 head: db "ADDR 0 1 2 3 4 5 6 7 8 9 A B C D E F " db " ascii",13,10,0 spaces: db " ",0 reboot: db "Press any key to reboot...",13,10,0