Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Operating system-- the transfer of control of the master bootstrap

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/02 Report--

one。 The first thing to know about the control transfer of the master bootstrapper is the BootLoader memory layout. In the embedded operating system, BootLoader runs before the operating system kernel runs. The hardware device can be initialized and the memory space mapping map can be established, so as to bring the software and hardware environment of the system to an appropriate state, so as to prepare the correct environment for the final call to the operating system kernel. In embedded systems, there is usually no firmware program like BIOS (note, some embedded CPU will also embed a short startup program), so the loading and starting task of the whole system is completely completed by BootLoader. In an embedded system based on ARM7TDMI core, the system usually starts from the address 0x00000000 when the system is powered on or reset, and the BootLoader program of the system is usually arranged at this address.

The starting address of the 0x7c00 master bootstrapper, which used to be the stack space, mainly function calls. Finally, the main bootstrap program jumps from the boot program to 0x9000loader, and the middle part is the Fat table, which occupies 4 bytes

1. Load file contents through FAT table-flowchart

Experimental procedure

1. Create a large text file (Loader) on a virtual floppy disk

two。 Load the contents of Loader to the BaseOfLoader address

3. Print the text in Loader (determine whether the load is complete)

Org 0x7c00jmp short startnopdefine: BaseOfStack equ 0x7c00 BaseOfLoader equ 0x9000 RootEntryOffset equ 19 RootEntryLength equ 14 EntryItemLength equ 32 FatEntryOffset equ 1 FatEntryLength equ 9header: BS_OEMName db "D.T.Soft" BPB_BytsPerSec dw 512 BPB_SecPerClus db 1 BPB_RsvdSecCnt dw 1 BPB_NumFATs db 2 BPB_RootEntCnt dw 224 BPB_TotSec16 dw 2880 BPB_Media db 0xF0 BPB_FATSz16 dw 9 BPB_SecPerTrk dw 18 BPB_NumHeads Dw 2 BPB_HiddSec dd 0 BPB_TotSec32 dd 0 BS_DrvNum db 0 BS_Reserved1 db 0 BS_BootSig db 0x29 BS_VolID dd 0 BS_VolLab db "D.T.OS-0.01" BS_FileSysType db "FAT12" start: mov ax Cs mov ss, ax mov ds, ax mov es, ax mov sp, BaseOfStack mov ax, RootEntryOffset mov cx, RootEntryLength mov bx, Buf call ReadSector mov si, Target mov cx, TarLen mov dx, 0 call FindEntry cmp dx, 0 jz output mov si, bx mov di, EntryItem mov cx, EntryItemLength call MemCpy mov ax, FatEntryLength mov cx, [BPB_BytsPerSec] mul cx mov bx, BaseOfLoader sub bx, ax mov ax, FatEntryOffset mov cx, FatEntryLength call ReadSector mov cx [EntryItem + 0x1A] mov si, BaseOfLoaderloading: mov ax, dx add ax, 31 mov cx, 1 push dx push bx mov bx, si call ReadSector pop bx pop cx call FatVec cmp dx, 0xFF7 jnb BaseOfLoader add si, 512 jmp loadingoutput: mov bp, MsgStr mov cx, MsgLen call Printlast: hlt jmp last Cx-- > index; bx-- > fat table address;; return:; dx-- > Fat [FatVec] FatVec: mov ax, cx mov cl, 2 div cl push ax mov ah, 0 mov cx, 3 mul cx mov cx, ax pop ax cmp ah, 0 jz even jmp oddeven:; FatVec [j] = (Fat [iInde1] & 0x0F) 4) & 0x0F) Mov dx, cx add dx, 2 add dx, bx mov bp, dx mov dl, byte [bp] mov dh, 0 shl dx, 4 add cx, 1 add cx, bx mov bp, cx mov cl, byte [bp] shr cl, 4 and cl, 0x0F mov ch, 0 or dx, cxreturn: ret; ds:si-- > source; es:di-- > destination Cx-- > lengthMemCpy: push si push di push cx push ax cmp si, di ja btoe add si, cx add di, cx dec si dec di jmp etobbtoe: cmp cx, 0 jz done mov al, [si] mov byte [di], al inc si inc di dec cx jmp btoeetob: cmp cx, 0 jz done mov al, [si] mov byte [di] Al dec si dec di dec cx jmp etobdone: pop ax pop cx pop di pop si ret Es:bx-- > root entry offset address; ds:si-- > target string; cx-- > target length;; return:; (dx! = 0)? Exist:noexist; exist-- > bx is the target entryFindEntry: push di push bp push cx mov dx, [BPB_RootEntCnt] mov bp, spfind: cmp dx, 0 jz noexist mov di, bx mov cx, [bp] call MemCmp cmp cx, 0 jz exist add bx, 32 dec dx jmp findexist:noexist: pop cx pop bp pop di ret; ds:si-- > source; es:di-- > destination; cx-- > length Return:; (cx = = 0)? Equal: noequalMemCmp: push si push di push axcompare: cmp cx, 0 jz equal mov al, [si] cmp al, byte [di] jz goon jmp noequalgoon: inc si inc di dec cx jmp compareequal: noequal: pop ax pop di pop si ret; es:bp-- > string address; cx-- > string lengthPrint: mov dx, 0 mov ax, 0x1301 mov bx, 0x0007 int 0x10 ret No parameterResetFloppy: push ax push dx mov ah, 0x00 mov dl, [BS_DrvNum] int 0x13 pop dx pop ax ret; ax-- > logic sector number; cx-- > number of sector Es:bx-- > target addressReadSector: push bx push cx push dx push ax call ResetFloppy push bx push cx mov bl, [BPB_SecPerTrk] div bl mov cl, ah add cl, 1 mov ch, al shr ch, 1 mov dh, al and dh, 1 mov dl, [BS_DrvNum] pop ax pop bx mov ah, 0x02read: int 0x13 jc read pop ax pop dx pop cx pop bx retMsgStr db "No LOADER..." MsgLen equ ($- MsgStr) Target db "LOADER" TarLen equ ($- Target) EntryItem times EntryItemLength db 0x00Buf: times 510-($- $$) db 0x00 db 0x55, 0xaa

The result of make on this

From this result, we can see that the value of TIME is negative, indicating that the size of the main bootstrapper is greater than 512. we need to reduce it and delete the previously unimportant stack and unstack operations to avoid taking up space, so why did we do this before? In order to comply with the convention of the assembly code, the values of the registers related to the operation should be carried out on and off the stack. Then we don't have enough memory, so there's no need to do this. We delete the following stack-in and out-stack operations, but keep the cx register in and out of the stack in the FindEntry function because the value of the cx register is constantly changing. In the find operation, it is necessary to add the si register in and out of the stack operation before and after the call MemCmp operation.

The corrected make and the result implemented on bochs will print the string content in loader.

b. The first loader program

1. Starting address 0x9000

two。 Print a string on the screen through int0x10

a. Zero mark bit-determines whether the result of the operation is 0, and when the result is 0, the value of the ZF bit is 1

b. At the same time, jxx represents a family of instructions, which can be adjusted according to flag bits.

Jo jumps when OF is 1, jc jumps when CF is 1, jns jumps when SF is not 1, jz jumps when ZF is 1, je comparison results are equal

Loader.asm code implementation

Org 0x9000begin: mov si, msgprint: mov al, [si] add si, 1 cmp al, 0x00 je end mov ah, 0x0E mov bx, 0x0F int 0x10 jmp printend: hlt jmp endmsg: db 0x0a, 0x0a db "Hello, D.T.OS!" Db 0x0a, 0x0a db 0x00

The result of decompiling loader.asm

You can see that the jz here corresponds to the je command in loader.asm

Next, copy the loader to the floppy disk, and then jump from Boot to loader for execution. We mount the virtual floppy disk in linux, then copy it, and finally run it.

As can be seen from the printed results, control has been transferred from boot to the loader program.

Modify the print result to see if the implementation result on bochs has also been modified.

Here we need to modify the makefile file to ensure that it is easy to run later.

.PHNY: all clean rebuildBOOT_SRC: = boot.asmBOOT_OUT: = bootLOADER_SRC: = loader.asmLOADER_OUT: = loaderIMG: = data.imgIMG_PATH: = / mnt/hgfsRM: = rm-frall: $(IMG) $(BOOT_OUT) $(LOADER_OUT) @ echo "Build Success = = > D.T.OS!" $(IMG): bximage $@-Q-fd-size=1.44 $(BOOT_OUT): $(BOOT_SRC) nasm $^-o $ Dd if=$@ of=$ (IMG) bs=512 count=1 conv=notrunc$ (LOADER_OUT): $(LOADER_SRC) nasm $^-o $@ sudo mount-o loop $(IMG) $(IMG_PATH) sudo cp $@ $(IMG_PATH) / $@ sudo umount $(IMG_PATH) clean: $(RM) $(IMG) $(BOOT_OUT) $(LOADER_OUT) rebuild: @ $(MAKE) clean @ $(MAKE) all

Finally, data.img is implemented under window.

Summary

1.Boot needs to perform refactoring to ensure that the function is completed within 512 bytes.

two。 Try to ensure that the state of the general register remains unchanged before and after the function call in the assembler.

3.Boot transfers control after successfully loading Loader

There is no limit on the size of the code for 4.Loader programs.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report