Operating System Truth Restoration_Chapter 3: 8086 Assembly Hardware Interaction

register

segment register

CS: Code Segment Register
DS: Data Segment Register
ES: Additional segment register
FS: Additional segment register
GS: Additional segment register
SS: stack segment register

general purpose register

AX: accumulator
BX: base address register
CX: counter
DX: data register
si: source index register
di: destination index register
sp: stack pointer register
bp: base address pointer

flag register

FLAGS

8086-1MB memory distribution

addressing mode

register addressing
immediate addressing
memory addressing
The memory addressing can be divided into:
direct addressing
base addressing
Indexed addressing
base + index addressing

bochs debug commands

Debugger control class

Exit the debug state: q | quit | exit
Set the value of the register: set reg=val
Set whether to disassemble instructions every time you stop execution: set u on | off
Prompt every time you switch modes: show mode
Prompt on every interrupt: show int
Prompt every function call: show call
Print the disassembled code each time an instruction is executed: trace on | off
Code disassembly: u | disasm /num start end

Execution control class

Continue to execute, stop when a breakpoint is encountered: c | cont | continue
Execute n instructions, default 1, do not skip functions: s | step n
Execute 1 instruction, skip function: p|n|next

Breakpoint control class

Set breakpoint by address

Physical address: pb | pbreak | b | break [addr]
Linear address: lb | lbreak [addr]
Virtual address: vb | vbreak [seg : off]

Set a breakpoint by the number of instructions

Interrupt after executing n instructions from the current position: sb n
Interrupt after executing n instructions since the CPU started running: sba n

Set breakpoints with read and write IO

Interrupt when reading [phy_addr]: watch r | read [phy_addr]
Interrupt when writing to [phy_addr]: watch w | write [phy_addr]

Replenish

Show all read and write breakpoints: watch
Clear read-write breakpoint on [phy_addr]: unwatch [phy_addr]
Clear all read and write breakpoints: unwatch
Show all breakpoint information: blist
Disable/enable breakpoint n, n query using blist: bpd | bpe n
Delete breakpoint n, n use blist to query: d | del | delete n

CPU and memory contents class

memory check

View physical address memory: xp /nuf [phy_addr]
View linear address memory: x /nuf [addr]
Stack view: print-stack [num]
n: number of units displayed
u: the size of the display unit, b is 1B, h is 2B, w is 4B, g is 8B
f: display format, x is hexadecimal, d is decimal, u is unsigned decimal, o is octal, t is binary, c is character display, s is ASCIIz display, i is instr display

memory operation

Set the content of consecutive size bytes starting from [phy_addr] to val: setpmem [phy_addr] [size] [val]

Register View

General register view: r | regs | registers
Status register view: info flags | eflags
Segment register view: sreg
Debug register view: dreg
Control register view: creg
View all registers: info CPU

View special data

View breakpoint information, equivalent to blist: info pb | pbreak | b | break
FPU status view: info fpu
View the nth entry in the global descriptor table: info gdt n
View the nth entry in the interrupt vector table: info ivt n
View the interrupt vector table: info idt
View the local descriptor table: info ldt
View the task status section: info tss
View the mapping of linear addresses to physical addresses: page line_addr
View the mapping of linear addresses to physical addresses in the page table: info tab

memory interaction

Basic knowledge of video memory

Memory distribution:

Display Mode:
32KB memory area from start address 0xB8000 to 0xBFFFF for text display
There are many display modes, which are represented by the number of columns and rows, such as 8025, 4025…
The product of the modes is the number of characters that the entire screen can hold, and works in 8025 mode by default
The data structure of 1 character is as follows, the first byte is ASCII code, and the last byte is character attribute
In the working mode of 8025, 1 page screen occupies 280*25 bytes, which can be divided into 32KB/4KB pages in total

Manipulating video memory example

Write the master boot sector code to display Hello, World!!!

Programming mbr.s

;main bootloader 
;------------------------------------------------------------
SECTION MBR vstart=0x7c00         
   mov ax,cs      
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov fs,ax
   mov ax, 0xB800
   mov gs, ax
   mov sp,0x7c00

; Clear screen use 0 x06 Number function, scroll up all the lines, you can clear the screen.
; -----------------------------------------------------------
;INT 0x10   function number:0x06	   Function description:roll up window
;------------------------------------------------------
;enter:
;AH function number= 0x06
;AL = Number of lines rolled up(if 0,show all)
;BH = Rollup row properties
;(CL,CH) = upper left corner of the window(X,Y)Location
;(DL,DH) = bottom right of the window(X,Y)Location
;No return value:
   mov     ax, 0x600
   mov     bx, 0x700
   mov     cx, 0           ; top left: (0, 0)
   mov     dx, 0x184f	   ; bottom right: (80,25),
			   ; VGA in text mode,A line can only hold 80 characters,25 lines in total.
			   ; subscripts start at 0,so 0 x18=24,0x4f=79
   int     0x10            ; int 0x10


;;;;;;;;;     print string    ;;;;;;;;;;;
   mov cx, sx-msg
   mov si, msg
   mov di, 0
show_str:
   mov byte al, [si]
   mov byte ah, [sx]
   mov word [gs:di], ax
   inc si
   add di, 2
   loop show_str
;;;;;;;;;      end of typing string	 ;;;;;;;;;;;;;;;

   jmp $		; Hover program here

   msg db "Hello, World!!!"
   sx db 0xA4
   times 510-($-$$) db 0
   db 0x55,0xaa

Compile and write to disk

Compile: nasm -o mbr.bin mbr.s
Write to hard disk: dd if=OS/boot/mbr.bin of=bochs/hd60M.img bs=512 count=1 conv=notrunc

start bochs execution

./bochs installation directory/bin/bochs -f bochs configuration file

Hard disk interaction

Read the loader program from the hard disk through the master boot sector code, and jump to the loader entry for execution

Hard Disk Controller Main Ports


Note: Read and write operations here refer to read and write ports, not hard drives

hard disk addressing

Hard disk structure

CHS mode addressing

Cylinder: Cylinder
Head: magnetic head
Sector: sector

LBA addressing

Divided into LBA28, LBA48
LBA28 addressing:
Bits 0~7: 0x1F3 | 0x173
8~15 bits: 0x1F4 | 0x174
16~23 bits: 0x1F5 | 0x175
24~27 bits: 0x1F6 lower 4 bits | 0x176 lower 4 bits

port

device port


Note: 0 means master disk, 1 means slave disk

command port

Mainly used commands:
identify: 0xEC, hard drive identification
read sector: 0x20, read sector
write sector: 0x30, write sector

status port

Commands for manipulating ports

in op1, op2
in means to read the port register
op1 is a register
op2 is the port number

out op1, op2
out means writing to the port register
op1 is the port number
op2 is a register

Note: op1, op2 can only be dx, ax or al
dx is used to specify the port, ax, al, ah are used to transmit data

Hard disk read and write operation sequence

1. Select the master/slave channel and write the number of sectors to be operated to the sector count port
2. Write the lower 24 bits of the sector logical address, and write the upper 4 bits of the logical sector address into the device
3. Set the 6th bit of the device port to select the addressing mode, and set the 4th bit to select the hard disk
4. Set the command of the command port (read, write or other)
5. Read the status port to get the status of the hard disk, and judge whether the hard disk has completed the work
6. If the above steps are to read the hard disk, go to the next step, otherwise it is completed
7. Read the hard disk data

Replenish:
Whether writing or reading hard disk data, the CPU interacts with the hard disk controller's buffers
When reading data, the hard disk is ready to indicate that the buffer is ready for the required data
When writing data, it is also writing data to the buffer. The hard disk is ready to indicate that the buffer can receive data.

How to read data

1. Unconditional delivery method
2. Query delivery method
3. Interrupt transmission method
4. Direct memory storage method
5. I/O processor transmission mode

Hard Disk Interaction Example

Use the mbr.s program to load the loader.s program in the hard disk, and jump to the loader program to run
The loader program is arranged in the second sector, LBA address: 0x0000001
%include "configuration file name.inc", %include is the preprocessor of nasm, which means that "configuration file name.inc" is included before compilation

Configuration file boot.inc

;--------- mbr & loader ---------
LBA_START_SECTOR equ 0x1
SECTOR_COUNT equ 0x1
LOADER_BASE_ADDR equ 0x100
LOADER_OFF_ADDR equ 0x0
LOADER_ADDR equ 0x1000

mbr program

;main bootloader
;------------------------------------------------------------
%include "boot.inc"
SECTION MBR vstart=0x7c00         
   mov ax,cs      
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov fs,ax
   mov ax, 0xB800
   mov gs, ax
   mov sp,0x7c00

; Clear screen use 0 x06 Number function, scroll up all the lines, you can clear the screen.
; -----------------------------------------------------------
;INT 0x10   function number:0x06	   Function description:roll up window
;------------------------------------------------------
;enter:
;AH function number= 0x06
;AL = Number of lines rolled up(if 0,show all)
;BH = Rollup row properties
;(CL,CH) = upper left corner of the window(X,Y)Location
;(DL,DH) = bottom right of the window(X,Y)Location
;No return value:
   mov     ax, 0x600
   mov     bx, 0x700
   mov     cx, 0           ; top left: (0, 0)
   mov     dx, 0x184f	   ; bottom right: (80,25),
			   ; VGA in text mode,A line can only hold 80 characters,25 lines in total.
			   ; subscripts start at 0,so 0 x18=24,0x4f=79
   int     0x10            ; int 0x10


;;;;;;;;;     print string    ;;;;;;;;;;;

   mov cx, sx - msg
   mov si, msg
   mov di, 0
show_str:
   mov byte al, [si]
   mov byte ah, [sx]
   mov word [gs:di], ax
   inc si
   add di, 2
   loop show_str
   jmp L0

   msg db "enter mbr"
   sx db 0x24

;;;;;;;;;      end of typing string	 ;;;;;;;;;;;;;;;
L0:
   push ds
   push di
   mov eax, LBA_START_SECTOR
   push eax
   mov ax, SECTOR_COUNT
   push ax
   mov ax, LOADER_BASE_ADDR
   push ax
   mov ax, LOADER_OFF_ADDR
   push ax
   call read_disk
   add sp, 10
   pop di
   pop ds

   jmp LOADER_ADDR

;;;;;;;;;      read disk      ;;;;;;;;;

; LBA: [bp+10]
; sector count: [bp+8]
; destination: sec=[bp+6], off=[bp+4]
read_disk:
   push bp
   mov bp, sp

;sector_count
   mov dx,0x1f2
   mov ax, [bp+8]
   out dx, al

;sector_addr
   mov dx, 0x1f3
   mov ax, [bp+10]
   out dx, al

   mov dx, 0x1f4
   mov al, ah
   out dx, al

   mov dx, 0x1f5
   mov ax, [bp+12]
   out dx, al

   mov dx, 0x1f6
   mov al, ah
   and al, 0x0f
   or al, 0xe0
   out dx, al

;command_write
   mov dx, 0x1f7
   mov al, 0x20
   out dx, al

disk_test:
   nop          ;give disk a moment
   in al, dx
   and al, 0x88 ;7: BUSY, 3: READY
   cmp al, 0x08 ; (BUSY=0 & READY=1) or not?
   jnz disk_test

;data_read:   
   mov ax, [bp+8]
   mov dx, 256
   mul dx
   mov cx, ax

   mov bx, [bp+4]
   mov ax, [bp+6]
   mov ds, ax

   mov dx, 0x1f0
go_on_read:
   in ax, dx
   mov [bx], ax
   add bx,2
   loop go_on_read

   mov sp, bp
   pop bp
   ret
;;;;;;;;;      read disk      ;;;;;;;;;

   times 510-($-$$) db 0
   db 0x55,0xaa

loader program

%include "boot.inc"
section loader vstart=LOADER_ADDR
;;;;;;;;;     print string    ;;;;;;;;;;;

   mov cx, sx-msg
   mov si, msg
   mov di, 160
show_str:
   mov byte al, [si]
   mov byte ah, [sx]
   mov word [gs:di], ax
   inc si
   add di, 2
   loop show_str

   msg db "enter loader"
   sx db 0x24

;;;;;;;;;      end of typing string    ;;;;;;;;;;;;;;;
   jmp $

Compile and write to disk

nasm -I The directory where the configuration file is located -o mbr.bin The directory where mbr.s is located/mbr.s
nasm -I The directory where the configuration file is located -o loader.s.bin The directory where loader.s is located/loader.s
dd if=mbr.s directory/mbr.bin of=hard disk directory/hd60M.img bs=512 count=1 seek=0 conv=notrunc
dd if=loader.s directory/loader.bin of=hard disk directory/hd60M.img bs=512 count=1 seek=1 conv=notrunc

start bochs execution

./bochs installation directory/bochs/bin/bochs -f directory where the bochs configuration file is located/boot.disk

Tags: Operating System

Posted by netrepsa on Sat, 22 Oct 2022 07:47:39 +0530