日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

操作系统真相还原

發布時間:2024/3/26 windows 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 操作系统真相还原 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

操作系統真相還原

1、部署工作環境

1.2 Bochs下載安裝

下載

下載地址:https://sourceforge.net/projects/bochs/files/bochs/2.7/

解壓:

crescentp@crescentp:~/bochs$ tar zxvf bochs-2.7.tar.gz

編譯

./configure --prefix=/os/bochs --enable-debugger --enable-disasm --enable-iodebug --enable-x86-debugger --with-x --with-x11 make make install

配置bochs

可以在安裝目錄下查看配置文件的樣本文件

cat share/doc/bochs/bochsrc-sample.txt

在 bin目錄下編寫bochsrc.disk代碼

############################################# # Configuration file for Bochs # By CP ############################################# # 第一步,首先設置Bochs在運行中過程中能夠使用的內存,本列為32MB # 關鍵字為:megs megs: 32# 第二步:設置對應真實機器的BIOS和VGA BIOS # 對應的兩個關鍵字為: romimage 和 vgaromimage romimage: file=/os/bochs/share/bochs/BIOS-bochs-latest vgaromimage: file=/os/bochs/share/bochs/VGABIOS-lgpl-latest# 第三步,設置Bochs所使用的的磁盤,軟盤的關鍵字為floppy # 若只有一個軟盤,則使用的floppya即可,若有多個,則為floppya,floppyb # floppya: 1_44=a.img, status=inserted# 第四步,選擇啟動盤符 #boot: floppy #默認從軟盤啟動 boot: disk #改為從硬盤啟動,我們的任何代碼都將直接寫在硬盤上,所以不會再有讀寫軟盤的操作了# 第五步,設置日志文件的輸出 log: bochs.out# 第六步,開啟或關閉某些功能 # 下面是關閉鼠標,并且打開鍵盤 mouse: enabled=0 # keyboard_mapping: enabled=1, keyboard:keymap=/os/bochs/share/bochs/keymaps/x11-pc-us.map# 硬盤設置 ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 # ata0-master: type=disk,path="hd60M.img",mode=flat# 下面的是增加的bochs對gdb的支持,這樣gdb便可以遠程連接到此機器的1234端口調試了 gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0

運行

bochs

配置啟動盤

沒有啟動盤,那我們就配置啟動盤唄

/bin/bximage 是創建啟動盤的工具

bin/bximage -hd=60M -q hd60M.img

2、編寫MBR

mbr.S

;主引導程序 ;--------------------------------------------------------------------- SECTION MBR vstart=0x7c00 ; 表示在本程序編譯時,告訴編譯器,把我的其實地址編譯0x7c00mov ax,cs ; 這一塊是用cs寄存器的值,去初始化其它的寄存器mov ds,ax ; 由于BIOS是通過 jmp 0:0x7c00 跳轉到MBR的,故此時cs為0mov es,axmov ss,axmov fs,axmov sp,0x7c00 ;初始化棧指針,0x7c00以下是安全的區域,可以用來當棧使用;清屏利用0x6號功能,上卷全部行,即可清屏 ;--------------------------------------------------------------------- ;INT 0x10 功能號:0x06 功能描述:上卷屏幕 ;--------------------------------------------------------------------- ;輸入; ;AH 功能號 = 0x06 ;AL = 上卷的行數(如果為0,表示全部) ;BH = 上卷行的屬性 ;(CL,CH) = 窗口左上角的(X,Y)位置 ;(DL,DH) = 窗口右下角的(X,Y)位置 ;無返回值mov ax,0x600mov bx,0x700mov cx,0 ;左上角:(0,0)mov dx,0x184f ;右下角:(80,25);VGA文本模式中,一行只能容納80個字符,共25行;下標從0開始,所以0x18=24,0x4f=79int 0x10 ;int 0x10;;;;;;;; 下面這三行代碼獲取光標位置 ;;;;;;;;;;;;; ; .get_cursor 獲取當前光標位置,在光標位置處打印字符mov ah,3 ;輸入:3號子功能是獲取光標位置,需要存入ah寄存器mov bh,0 ;bh寄存器存儲的是待獲取光標的頁號int 0x10 ;輸出,ch=光標開始行,cl=光標結束行;dh=光標所在行號,dl=光標所在列號;;;;;;;; 獲取光標結束位置 ;;;;;;;;;;;;;;;;;;; 打印字符串 ;;;;;;;;;;;;;還是用10h中斷,不過這次調用13號子功能打印字符串mov ax,messagemov bp,ax ;es:bp為串首地址,es此時和cs一致;開頭已經為sreg初始化;光標位置要用到dx寄存器中的內容,cx中光標位置可忽略mov cx,5 ;cx為串長度,不包括結束符0的字符個數mov ax,0x1301 ;子功能號13顯示字符及屬性,要出入ah寄存器;al設置寫字符方式 ah = 01;顯示字符串,光標跟隨移動mov bx,0x2 ;bh存儲的是要顯示的頁號,此處是第0頁;bl是字符屬性,屬性為黑底綠字(bl = 02h)int 0x10 ;執行BIOS 0x10中斷 ;;;;;;;; 打印字符串結束 ;;;;;;;;;;;;;;jmp $ ;是程序懸停在此處message db "1 MBR"times 510-($-$$) db 0 ; $$ 是本section的地址,$是本行的地址,$-$$是本行到本section的偏移量,最后兩個字節是確定的,這就把本扇區的剩余量補0db 0x55,0xaa

編譯

nasm -o mbr.bin mbr.S

將mbr.bin轉載進入磁盤的第一個扇區

dd if=/os/bochs/mbr.bin of=/os/bochs/hd60M.img bs=512 count=1 conv=notrunc

運行

bin/bochs -f bin/bochsrc.disk

3、完善MBR

我們不適用int10中斷來顯示MBR,而是通過操控顯存的方式

;主引導程序 ; ;LOADER_BASE_ADDR equ 0xA00 ;LOADER_START_SECTOR equ 0x2 ;--------------------------------------------------------------------- SECTION MBR vstart=0x7c00 ; 表示在本程序編譯時,告訴編譯器,把我的其實地址編譯0x7c00mov ax,cs ; 這一塊是用cs寄存器的值,去初始化其它的寄存器mov ds,ax ; 由于BIOS是通過 jmp 0:0x7c00 跳轉到MBR的,故此時cs為0mov es,axmov ss,axmov fs,axmov sp,0x7c00 ;初始化棧指針,0x7c00以下是安全的區域,可以用來當棧使用mov ax,0xb800 ;顯存文本模式中,其內存地址是0xb8000mov gs,ax ;清屏 ;利用0x6號功能,上卷全部行,即可清屏 ;--------------------------------------------------------------------- ;INT 0x10 功能號:0x06 功能描述:上卷屏幕 ;--------------------------------------------------------------------- ;輸入; ;AH 功能號 = 0x06 ;AL = 上卷的行數(如果為0,表示全部) ;BH = 上卷行的屬性 ;(CL,CH) = 窗口左上角的(X,Y)位置 ;(DL,DH) = 窗口右下角的(X,Y)位置 ;無返回值mov ax,0x600mov bx,0x700mov cx,0 ;左上角:(0,0)mov dx,0x184f ;右下角:(80,25);VGA文本模式中,一行只能容納80個字符,共25行;下標從0開始,所以0x18=24,0x4f=79int 0x10 ;int 0x10;輸出背景色綠色,前景色紅色,并且跳動的字符串“1 MBR”mov byte [gs:0x00],'1'mov byte [gs:0x01],0xA4 ;A表示綠色背景閃爍,4表示前景位紅色mov byte [gs:0x02],' 'mov byte [gs:0x03],0xA4mov byte [gs:0x04],'M'mov byte [gs:0x05],0xA4mov byte [gs:0x06],'B'mov byte [gs:0x07],0xA4mov byte [gs:0x08],'R'mov byte [gs:0x09],0xA4jmp $ ;是程序懸停在此處message db "1 MBR"times 510-($-$$) db 0 ; $$ 是本section的地址,$是本行的地址,$-$$是本行到本section的偏移量,最后兩個字節是確定的,這就把本扇區的剩余量補0db 0x55,0xaa

編譯

nasm -o mbr.bin mbr.S

將mbr.bin裝載進入磁盤的第一個扇區

dd if=/os/bochs/mbr.bin of=/os/bochs/hd60M.img bs=512 count=1 conv=notrunc

運行

bin/bochs -f bin/bochsrc.disk

可見這是跳動的

接下來我們通過從硬盤中讀取加載信息,將內核加載器讀入到內存,

mbr.S

;主引導程序 ;------------------------------------------------------------------------------ %include "boot.inc" ;讓編譯器在編譯之前,把boot.inc文件包含進來 SECTION MBR vstart=0x7c00mov ax,csmov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00mov ax,0xb800mov gs,ax;清屏 ;利用0x06功能,上卷所有行,則可清屏 ;------------------------------------------------------------------------------- ;INT 0x10 功能號:0x06 功能描述:上卷窗口 ;------------------------------------------------------------------------------- ;輸入; ;AH 功能號:0x06 ;AL = 上卷的行數(如果為0,表示全部) ;BH = 上卷行屬性 ;(CL,CH) = 窗口左上角(X,Y)位置 ;(DL,DH) = 窗口右下角的(X,Y)位置 ;無返回值mov ax,0600hmov bx,0700hmov cx,0 ;左上角:(0,0)mov dx,184fh ;右下角:(80,25) ;因為VGA文本模式中,一行只能容納80個字符,共25行; 下標從0開始,所有0x18=24,0x4f=79int 10h ;int 10h;輸出字符串MBRmov byte [gs:0x00],'1'mov byte [gs:0x01],0xA4mov byte [gs:0x02],' 'mov byte [gs:0x03],0xA4mov byte [gs:0x04],'M'mov byte [gs:0x05],0xA4 ;A表示綠色背景閃爍,4表示前景顏色為紅色mov byte [gs:0x06],'B'mov byte [gs:0x07],0xA4mov byte [gs:0x08],'R'mov byte [gs:0x09],0xA4mov eax,LOADER_START_SECTOR ;起始扇區lba地址,0x2mov bx,LOADER_BASE_ADDR ;寫入的地址,0x900mov cx,1 ;待寫入的扇區數call rd_disk_m_16 ;以下讀取程序的起始部分(一個扇區)jmp LOADER_BASE_ADDR;------------------------------------------------------------------------------------- ;功能:讀取硬盤n個扇區 rd_disk_m_16: ;-------------------------------------------------------------------------------------;eax=LBA扇區號;bx=將數據寫入的內存地址;cx=讀入的扇區數mov esi,eax ;備份eax,因為al在out命令中會使用,會影響到eax的低8位mov di,cx ;備份cx,cx在讀數據的時候會使用到 ;讀寫硬盤 ;第一步:設置要讀取的扇區數mov dx,0x1f2 ;虛擬硬盤屬于ata0,是Primary通道,所以sector count 是由0x1f2訪問mov al,cl ;cl是cx的低8位,就讀一個扇區,這樣就能傳過去了out dx,al ;讀取的扇區數,sector count 記錄要讀取的扇盤數量mov eax,esi ;恢復eax,現在eax存的是其實扇區lba的地址,0x2,第二個扇區;第二步:將LBA地址存入 0x1f3 ~ 0x1f6;LBA地址 7~0 位寫入端口 0x1f3mov dx,0x1f3 ;LBA lowout dx,al ;eax的第8位,就是al;LBA地址 15~8 位寫入端口 0x1f4mov cl,8shr eax,cl ;eax右移8位,讓al的數,變為eax中8位mov dx,0x1f4 ;LBA midout dx,al;LBA地址 23~16 位寫入端口 0x1f5shr eax,cl ;再右移8位mov dx,0x1f5 ;LBA highout dx,alshr eax,cl ;這樣al為0000and al,0x0f ;lba第24~27位or al,0xe0 ;設置7~4位為1110,表示lba模式mov dx,0x1f6 ;就是拼湊出device寄存器的值out dx,al;第3步:向0x1f7端口寫入讀命令,0x20mov dx,0x1f7mov al,0x20out dx,al ;command:0x1f7,寫入命令,寫入的命令是讀命令;第四步:檢測硬盤狀態.not_ready:;同一端口,寫時表示寫入命令字,讀時表示寫入硬盤的狀態,所以不需要更換dx的值nop ;減少打擾硬盤的工作in al,dx ;將Status的寄存器的值讀入到al中and al,0x88 ;第四位為1表示硬盤控制器已準備好數據傳輸,第七位為1表示硬盤忙,保存第4位和第7位cmp al,0x08 ;若第4位為1,表示數據已經準備好了,若第7位為1,表示硬盤處于忙jnz .not_ready ;若未準備好,繼續等,判斷結果是否為0;第5步,從0x1f0端口讀數據mov ax,di ;這個時候di存的是上面備份的cx,及時要讀取的扇區的數量mov dx,256 ;每次in操作只讀取兩個字節,根據讀入的數據總量(扇區數*512字節)mul dx ;dx*ax就是總數量/2,然后將值送到cx中,cx就是要in的次數mov cx,ax ;di為要讀取的扇區數,一個扇區有512個字節,每次讀入一個字,共需要di*512/2次,所以di*256mov dx,0x1f0.go_on_read:in ax,dx ;讀入到ax中mov [bx],ax ;讀入到bx指向的內存add bx,2 ;每次讀入2個字節loop .go_on_read ;cx是循環的次數rettimes 510-($-$$) db 0db 0x55,0xaa

boot.inc

;---------- loader 和 kernel----------------- LOADER_BASE_ADDR equ 0x900 LOADER_START_SECTOR equ 0x2

編譯:將boot.inc一起編譯

nasm -I include/ -o mbr.bin mbr.S

loader.S

%include "boot.inc" section loader vstart=LOADER_BASE_ADDR;輸出背景色綠色,前景色紅色,并且跳動的字符串"1 MBR" mov byte [gs:0x00],'2' mov byte [gs:0x01],0xA4mov byte [gs:0x02],' ' mov byte [gs:0x04],0xA4mov byte [gs:0x04],'L' mov byte [gs:0x05],0xA4mov byte [gs:0x06],'O' mov byte [gs:0x07],0xA4mov byte [gs:0x08],'A' mov byte [gs:0x09],0xA4mov byte [gs:0x0a],'D' mov byte [gs:0x0b],0xA4mov byte [gs:0x0c],'E' mov byte [gs:0x0d],0xA4mov byte [gs:0x0e],'R' mov byte [gs:0x0f],0xA4jmp $ ;通過死循環使查詢懸停在此 nasm -I include/ -o loader.bin loader.S dd if=/os/bochs/mbr.bin of=/os/bochs/hd60M.img bs=512 count=1 conv=notrunc

加載到第二個磁盤

dd if=/os/bochs/loader.bin of=/os/bochs/hd60M.img bs=512 count=4 conv=notrunc seek=2

運行

bin/bochs -f bin/bochsrc.disk

4、保護模式入門

mbr.S

;主引導程序 ;------------------------------------------------------------------------------ %include "boot.inc" ;讓編譯器在編譯之前,把boot.inc文件包含進來 SECTION MBR vstart=0x7c00mov ax,csmov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00mov ax,0xb800mov gs,ax;清屏 ;利用0x06功能,上卷所有行,則可清屏 ;------------------------------------------------------------------------------- ;INT 0x10 功能號:0x06 功能描述:上卷窗口 ;------------------------------------------------------------------------------- ;輸入; ;AH 功能號:0x06 ;AL = 上卷的行數(如果為0,表示全部) ;BH = 上卷行屬性 ;(CL,CH) = 窗口左上角(X,Y)位置 ;(DL,DH) = 窗口右下角的(X,Y)位置 ;無返回值mov ax,0600hmov bx,0700hmov cx,0 ;左上角:(0,0)mov dx,184fh ;右下角:(80,25) ;因為VGA文本模式中,一行只能容納80個字符,共25行; 下標從0開始,所有0x18=24,0x4f=79int 10h ;int 10h;輸出字符串MBRmov byte [gs:0x00],'1'mov byte [gs:0x01],0xA4mov byte [gs:0x02],' 'mov byte [gs:0x03],0xA4mov byte [gs:0x04],'M'mov byte [gs:0x05],0xA4 ;A表示綠色背景閃爍,4表示前景顏色為紅色mov byte [gs:0x06],'B'mov byte [gs:0x07],0xA4mov byte [gs:0x08],'R'mov byte [gs:0x09],0xA4mov eax,LOADER_START_SECTOR ;起始扇區lba地址,0x2mov bx,LOADER_BASE_ADDR ;寫入的地址,0x900mov cx,4 ;待寫入的扇區數,由于loader.bin超過了512個字節,可能是多個扇區call rd_disk_m_16 ;以下讀取程序的起始部分(一個扇區)jmp LOADER_BASE_ADDR;------------------------------------------------------------------------------------- ;功能:讀取硬盤n個扇區 rd_disk_m_16: ;-------------------------------------------------------------------------------------;eax=LBA扇區號;bx=將數據寫入的內存地址;cx=讀入的扇區數mov esi,eax ;備份eax,因為al在out命令中會使用,會影響到eax的低8位mov di,cx ;備份cx,cx在讀數據的時候會使用到 ;讀寫硬盤 ;第一步:設置要讀取的扇區數mov dx,0x1f2 ;虛擬硬盤屬于ata0,是Primary通道,所以sector count 是由0x1f2訪問mov al,cl ;cl是cx的低8位,就讀一個扇區,這樣就能傳過去了out dx,al ;讀取的扇區數,sector count 記錄要讀取的扇盤數量mov eax,esi ;恢復eax,現在eax存的是其實扇區lba的地址,0x2,第二個扇區;第二步:將LBA地址存入 0x1f3 ~ 0x1f6;LBA地址 7~0 位寫入端口 0x1f3mov dx,0x1f3 ;LBA lowout dx,al ;eax的第8位,就是al;LBA地址 15~8 位寫入端口 0x1f4mov cl,8shr eax,cl ;eax右移8位,讓al的數,變為eax中8位mov dx,0x1f4 ;LBA midout dx,al;LBA地址 23~16 位寫入端口 0x1f5shr eax,cl ;再右移8位mov dx,0x1f5 ;LBA highout dx,alshr eax,cl ;這樣al為0000and al,0x0f ;lba第24~27位or al,0xe0 ;設置7~4位為1110,表示lba模式mov dx,0x1f6 ;就是拼湊出device寄存器的值out dx,al;第3步:向0x1f7端口寫入讀命令,0x20mov dx,0x1f7mov al,0x20out dx,al ;command:0x1f7,寫入命令,寫入的命令是讀命令;第四步:檢測硬盤狀態.not_ready:;同一端口,寫時表示寫入命令字,讀時表示寫入硬盤的狀態,所以不需要更換dx的值nop ;減少打擾硬盤的工作in al,dx ;將Status的寄存器的值讀入到al中and al,0x88 ;第四位為1表示硬盤控制器已準備好數據傳輸,第七位為1表示硬盤忙,保存第4位和第7位cmp al,0x08 ;若第4位為1,表示數據已經準備好了,若第7位為1,表示硬盤處于忙jnz .not_ready ;若未準備好,繼續等,判斷結果是否為0;第5步,從0x1f0端口讀數據mov ax,di ;這個時候di存的是上面備份的cx,及時要讀取的扇區的數量mov dx,256 ;每次in操作只讀取兩個字節,根據讀入的數據總量(扇區數*512字節)mul dx ;dx*ax就是總數量/2,然后將值送到cx中,cx就是要in的次數mov cx,ax ;di為要讀取的扇區數,一個扇區有512個字節,每次讀入一個字,共需要di*512/2次,所以di*256mov dx,0x1f0.go_on_read:in ax,dx ;讀入到ax中mov [bx],ax ;讀入到bx指向的內存add bx,2 ;每次讀入2個字節loop .go_on_read ;cx是循環的次數rettimes 510-($-$$) db 0db 0x55,0xaa

boot.inc

;---------------loader和kernel ----------LOADER_BASE_ADDR equ 0x900 LOADER_START_SECTOR equ 0x2;-------------- gdt描述符屬性 ------------- DESC_G_4K equ 1_00000000000000000000000b ;G在段描述符第23位,將這里設為1,就是使用4K的密度 DESC_D_32 equ 1_0000000000000000000000b ;D在段描述符第22位,將這里設為1,表示操作數使用32位 DESC_L equ 0_000000000000000000000b ;L:段是否64位模式 64位代碼標記,此處標記為0便可。 DESC_AVL equ 0_00000000000000000000b ; cpu不用此位,暫置為0 DESC_LIMIT_CODE2 equ 1111_0000000000000000b ;段界限,段的長度 DESC_LIMIT_DATA2 equ DESC_LIMIT_CODE2 ; DESC_LIMIT_VIDEO2 equ 0000_000000000000000b ;段界限,設為0 DESC_P equ 1_000000000000000b ;p:是否在內存中 DESC_DPL_0 equ 00_0000000000000b ;DPL,為0的權限 DESC_DPL_1 equ 01_0000000000000b DESC_DPL_2 equ 10_0000000000000b DESC_DPL_3 equ 11_0000000000000b DESC_S_CODE equ 1_000000000000b ;代碼段 DESC_S_DATA equ DESC_S_CODE ;數據段,都是1,表示非系統段 DESC_S_sys equ 0_000000000000b DESC_TYPE_CODE equ 1000_00000000b ;x=1,c=0,r=0,a=0 代碼段是可執行的,非依從的,不可讀的,已訪問位a清0. DESC_TYPE_DATA equ 0010_00000000b ;x=0,e=0,w=1,a=0 數據段是不可執行的,向上擴展的,可寫的,已訪問位a清0.DESC_CODE_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_CODE2 + DESC_P + DESC_DPL_0 + DESC_S_CODE + DESC_TYPE_CODE + 0x00 ;代碼段的平坦模型 DESC_DATA_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_DATA2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x00 DESC_VIDEO_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_VIDEO2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x0b;-------------- 選擇子屬性 --------------- RPL0 equ 00b ;訪問權限 RPL1 equ 01b RPL2 equ 10b RPL3 equ 11b TI_GDT equ 000b ;訪問GDT TI_LDT equ 100b ;訪問LDT

loader.S

%include "boot.inc"section loader vstart=LOADER_BASE_ADDRLOADER_STACK_TOP equ LOADER_BASE_ADDR ;保護模式下的棧jmp loader_start;構建 gdt 及其內部的描述符GDT_BASE: dd 0x00000000 ;GDT的第0個段不可用dd 0x00000000; 定義了三個有用的段描述符CODE_DESC: dd 0x0000FFFF ;段描述符的低4字節,其中的低2字節是段長度 FFFF,高2字節是段基址 0000,dd DESC_CODE_HIGH4 ;代碼段的高四節,已經定義好了DATA_STACK_DESC: dd 0x0000FFFF ;數據段和棧段的段描述符dd DESC_DATA_HIGH4 ;顯存段描述符,0xb8000~0xbffff是用于文本模式的顯示內存,段基址:0x8000 長度 0007 VIDEO_DESC: dd 0x80000007 ;limit=(0xbffff-0xb8000)/4k = 0x7 4k是段粒度dd DESC_VIDEO_HIGH4 ;此時dpl為0GDT_SIZE equ $ - GDT_BASE ;19~20 獲取GDT的大小,為加載GDT做準備GDT_LIMIT equ GDT_SIZE - 1times 60 dq 0 ;此處預留60個描述符的空位,為了將來往GDT中添加其它描述符,提前保留空間SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0 ;相當于(CODE_DESC - GDT_BASE)/8 + TI_GDT + RPL0,構建代碼段的段選擇子,段描述符+TI+PRLSELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0 ;同上SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0 ;同上;以下是gdt的指針,前2字節是gdt界限,后四字節是gdt起始地址gdt_ptr dw GDT_LIMIT ;定義GDT的指針.前16位,是GDT以字節為單位的長度,也就是GDT大小減1dd GDT_BASE ;GDT的起始位置loadermsg db '2 loader in real.'loader_start:;-------------------------------------------------- ;INT 0x10 功能號:0x13 功能描述:打印字符串 ;-------------------------------------------------- ;輸入 ;AH 子功能號=13H ;BH = 頁碼 ;BL = 屬性(若AL=00H或01H) ;CX = 字符串的長度 ;(DH,DL) = 坐標(行,列) ;ES:BP=字符串的地址 ;AL=顯示輸出方式 ; 0--字符串中只含顯示字符,其顯示屬性在BL中,顯示后,光標位置不變 ; 1--字符串中只含顯示字符,其顯示屬性在BL中,顯示后,光標位置改變 ; 2--字符串中含顯示字符和顯示屬性.顯示后,光標位置不變 ; 3--字符串中含顯示字符和顯示休息,顯示后,光標位置改變 ;無返回值mov sp,LOADER_BASE_ADDRmov bp,loadermsg ;ES:BP = 字符串地址mov cx,17 ;字符串長度mov ax,0x1301 ;AH = 13,AL=01hmov bx,0x001f ;頁號為0(BH = 0) 藍底粉紅字(BL = 1fh)mov dx,0x1800 ;dh=18h=24行,dl=0,最后一行的行首int 0x10 ;10h 號中斷;------------------------ 準備進入保護模式 -------------------------- ;1 打開A20 ;2 加載gdt ;3 將cr0的pe位置1;---------------- 打開A20 ----------------------------------in al,0x92or al,0000_0010Bout 0x92,al;---------------- 加載GDT ----------------------------------lgdt [gdt_ptr];---------------- cr0 第0位置1 -------------------------------mov eax,cr0or eax,0x00000001mov cr0,eaxjmp dword SELECTOR_CODE:p_mode_start ;刷新流水線[bits 32] p_mode_start:mov ax,SELECTOR_DATA ;83~89 用選擇子初始化成各段寄存器mov ds,axmov es,axmov ss,axmov esp,LOADER_STACK_TOPmov ax,SELECTOR_VIDEOmov gs,axmov byte [gs:160], 'P'jmp $

編譯:

nasm -I include/ -o mbr.bin mbr.S nasm -I include/ -o loader.bin loader.S

裝載至磁盤

dd if=/os/bochs/mbr.bin of=/os/bochs/hd60M.img bs=512 count=1 conv=notrunc dd if=/os/bochs/loader.bin of=/os/bochs/hd60M.img bs=512 count=4 conv=notrunc seek=2

運行

bin/bochs -f bin/bochsrc.disk

5、保護模式進階、向內核邁進

mbr.S

;主引導程序 ;------------------------------------------------------------------------------ %include "boot.inc" ;讓編譯器在編譯之前,把boot.inc文件包含進來 SECTION MBR vstart=0x7c00mov ax,csmov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00mov ax,0xb800mov gs,ax;清屏 ;利用0x06功能,上卷所有行,則可清屏 ;------------------------------------------------------------------------------- ;INT 0x10 功能號:0x06 功能描述:上卷窗口 ;------------------------------------------------------------------------------- ;輸入; ;AH 功能號:0x06 ;AL = 上卷的行數(如果為0,表示全部) ;BH = 上卷行屬性 ;(CL,CH) = 窗口左上角(X,Y)位置 ;(DL,DH) = 窗口右下角的(X,Y)位置 ;無返回值mov ax,0600hmov bx,0700hmov cx,0 ;左上角:(0,0)mov dx,184fh ;右下角:(80,25) ;因為VGA文本模式中,一行只能容納80個字符,共25行; 下標從0開始,所有0x18=24,0x4f=79int 10h ;int 10h;輸出字符串MBRmov byte [gs:0x00],'1'mov byte [gs:0x01],0xA4mov byte [gs:0x02],' 'mov byte [gs:0x03],0xA4mov byte [gs:0x04],'M'mov byte [gs:0x05],0xA4 ;A表示綠色背景閃爍,4表示前景顏色為紅色mov byte [gs:0x06],'B'mov byte [gs:0x07],0xA4mov byte [gs:0x08],'R'mov byte [gs:0x09],0xA4mov eax,LOADER_START_SECTOR ;起始扇區lba地址,0x2mov bx,LOADER_BASE_ADDR ;寫入的地址,0x900mov cx,4 ;待寫入的扇區數,由于loader.bin超過了512個字節,可能是多個扇區call rd_disk_m_16 ;以下讀取程序的起始部分(一個扇區)jmp LOADER_BASE_ADDR;------------------------------------------------------------------------------------- ;功能:讀取硬盤n個扇區 rd_disk_m_16: ;-------------------------------------------------------------------------------------;eax=LBA扇區號;bx=將數據寫入的內存地址;cx=讀入的扇區數mov esi,eax ;備份eax,因為al在out命令中會使用,會影響到eax的低8位mov di,cx ;備份cx,cx在讀數據的時候會使用到 ;讀寫硬盤 ;第一步:設置要讀取的扇區數mov dx,0x1f2 ;虛擬硬盤屬于ata0,是Primary通道,所以sector count 是由0x1f2訪問mov al,cl ;cl是cx的低8位,就讀一個扇區,這樣就能傳過去了out dx,al ;讀取的扇區數,sector count 記錄要讀取的扇盤數量mov eax,esi ;恢復eax,現在eax存的是其實扇區lba的地址,0x2,第二個扇區;第二步:將LBA地址存入 0x1f3 ~ 0x1f6;LBA地址 7~0 位寫入端口 0x1f3mov dx,0x1f3 ;LBA lowout dx,al ;eax的第8位,就是al;LBA地址 15~8 位寫入端口 0x1f4mov cl,8shr eax,cl ;eax右移8位,讓al的數,變為eax中8位mov dx,0x1f4 ;LBA midout dx,al;LBA地址 23~16 位寫入端口 0x1f5shr eax,cl ;再右移8位mov dx,0x1f5 ;LBA highout dx,alshr eax,cl ;這樣al為0000and al,0x0f ;lba第24~27位or al,0xe0 ;設置7~4位為1110,表示lba模式mov dx,0x1f6 ;就是拼湊出device寄存器的值out dx,al;第3步:向0x1f7端口寫入讀命令,0x20mov dx,0x1f7mov al,0x20out dx,al ;command:0x1f7,寫入命令,寫入的命令是讀命令;第四步:檢測硬盤狀態.not_ready:;同一端口,寫時表示寫入命令字,讀時表示寫入硬盤的狀態,所以不需要更換dx的值nop ;減少打擾硬盤的工作in al,dx ;將Status的寄存器的值讀入到al中and al,0x88 ;第四位為1表示硬盤控制器已準備好數據傳輸,第七位為1表示硬盤忙,保存第4位和第7位cmp al,0x08 ;若第4位為1,表示數據已經準備好了,若第7位為1,表示硬盤處于忙jnz .not_ready ;若未準備好,繼續等,判斷結果是否為0;第5步,從0x1f0端口讀數據mov ax,di ;這個時候di存的是上面備份的cx,及時要讀取的扇區的數量mov dx,256 ;每次in操作只讀取兩個字節,根據讀入的數據總量(扇區數*512字節)mul dx ;dx*ax就是總數量/2,然后將值送到cx中,cx就是要in的次數mov cx,ax ;di為要讀取的扇區數,一個扇區有512個字節,每次讀入一個字,共需要di*512/2次,所以di*256mov dx,0x1f0.go_on_read:in ax,dx ;讀入到ax中mov [bx],ax ;讀入到bx指向的內存add bx,2 ;每次讀入2個字節loop .go_on_read ;cx是循環的次數rettimes 510-($-$$) db 0db 0x55,0xaa

loader.S

%include "boot.inc"section loader vstart=LOADER_BASE_ADDRLOADER_STACK_TOP equ LOADER_BASE_ADDR ;保護模式下的棧;構建 gdt 及其內部的描述符GDT_BASE: dd 0x00000000 ;GDT的第0個段不可用dd 0x00000000; 定義了三個有用的段描述符CODE_DESC: dd 0x0000FFFF ;段描述符的低4字節,其中的低2字節是段長度 FFFF,高2字節是段基址 0000,dd DESC_CODE_HIGH4 ;代碼段的高四節,已經定義好了DATA_STACK_DESC: dd 0x0000FFFF ;數據段和棧段的段描述符dd DESC_DATA_HIGH4 ;顯存段描述符,0xb8000~0xbffff是用于文本模式的顯示內存,段基址:0x8000 長度 0007 VIDEO_DESC: dd 0x80000007 ;limit=(0xbffff-0xb8000)/4k = 0x7 4k是段粒度dd DESC_VIDEO_HIGH4 ;此時dpl為0GDT_SIZE equ $ - GDT_BASE ;19~20 獲取GDT的大小,為加載GDT做準備GDT_LIMIT equ GDT_SIZE - 1times 60 dq 0 ;此處預留60個描述符的空位,為了將來往GDT中添加其它描述符,提前保留空間SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0 ;相當于(CODE_DESC - GDT_BASE)/8 + TI_GDT + RPL0,構建代碼段的段選擇子,段描述符+TI+PRLSELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0 ;同上SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0 ;同上;total_mem_bytes用于保存內存容量,以字節為單位,此位置比較好記;當前偏移 loader.bin 文件頭0x200字節 loader.bin的加載地址是0x900 4個段描述符的定義 32 dq了60個 480 = 512 = 0x200;故total_mem_bytes內存中的地址是0xb00 將來在內核咱們會引用此地址total_mem_bytes dd 0 ;存儲獲取到的內存容量;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;以下是gdt的指針,前2字節是gdt界限,后四字節是gdt起始地址gdt_ptr dw GDT_LIMIT ;定義GDT的指針.前16位,是GDT以字節為單位的長度,也就是GDT大小減1dd GDT_BASE ;GDT的起始位置;人工對齊:total_mem_bytes 4+gdt_ptr 6+ards_buf 244+ards_nr2,共256字節ards_buf times 244 db 0ards_nr dw 0 ;用于記錄ARDS結構體數量,每執行一次中斷就會獲得一個ards結構的數據loader_start:;int 15h eax = 0000E820h,edx = 534D4150h('SMAP')獲取內存布局xor ebx,ebx ;第一次調用ebx要為0mov edx,0x543d4150 ;edx只賦值一次,循環體中不改變mov di,ards_buf ;ards結構緩沖區,es:di,BIOS將獲取到的內存信息寫到此寄存器指向的內存,每次都以ARDS格式返回 .e820_mem_get_loop: ;循環獲取每個ARDS內存范圍描述結構mov eax,0x0000e820 ;子功能號,eax用來指定子功能號,每次執行 int 0x15后,eax值會變為0x534d4150mov ecx,20 ;ARDS結構的字節大小,ARDS地址范圍描述符是20字節int 0x15jc .e820_failed_so_try_e801 ;若cf位為1嘖有錯誤發生,嘗試0xe801子功能add di,cx ;使di增加20字節指向緩沖區中新ARDS結構位置inc word [ards_nr] ;記錄ARDS數量cmp ebx,0 ;ebx存放后續值,下一個ARDS的地址,在cf為0的情況下,若ebx為0,表示這是最后一個ARDS結構jnz .e820_mem_get_loop;在只有ards結構中,找出(base_add_low + length_low)的最大值,即內存大小mov cx,[ards_nr] ;遍歷每一個ARDS結構體,循環次數是ARDS的數量mov ebx,ards_bufxor edx,edx ;edx為最大的內存容量,在此先清0 .find_max_mem_area: ;無需判斷type是否為1,最大內存塊一定是可被使用的mov eax,[ebx] ;base_add_lowadd eax,[ebx+8] ;length_lowadd ebx,20 ;指向緩沖區中下一個ARDS結構cmp edx,eax ;冒泡排序,找出最大,edx寄存器始終是最大的內存容量jge .next_ardsmov edx,eax .next_ards:loop .find_max_mem_areajmp .mem_get_ok;----------- int 15h ax = E801h 獲取內存大小,最大支持4G ------------------- ; 返回后,ax cx 值一樣,以KB為單位,bx dx 值都一樣,以64KB為單位 ; 在ax和cx寄存器中為低16MB,在bx和dx寄存器中為16Mb到4GB .e820_failed_so_try_e801:mov ax,0xe801 ;功能號int 0x15jc .e801_failed_so_try88 ;若當前e801方法失敗,就嘗試0x88方法;1. 先算出低15MB的內存,ax和cx中是以KB為單位的內存數量,將其轉化成以byte為單位mov cx,0x400 ;cx和ax一樣,cx用作乘數mul cxshl edx,16and eax,0x0000FFFFor edx,eaxadd edx,0x100000 ;ax只是15MB,故要加1MBmov esi,edx ;先把低15MB的內存容量存入esi寄存器備份;2. 再將16MB以上的內存轉化為byte為單位,寄存器bx和dx中是以64KB為單位的內存數量xor eax,eaxmov ax,bxmov ecx,0x10000 ;0x10000 十進制為 64KBmul ecx ;32位乘法,默認的被乘數是eax,積為64位,高32位存入edx,低32位存入eaxadd esi,eax ;由于此方法只能測出4GB以內的內存,故32位eax足夠了 edx肯定為0mov edx,esi ;edx為總內存大小jmp .mem_get_ok;----------- int 15h ah = 0x88 獲取內存大小,只能獲取64MB之內 ----------------------- .e801_failed_so_try88:;int 15后,ax存入的是以KB為單位的內存容量mov ah,0x88int 0x15;jc .error_hlrand eax,0x0000FFFF;16位乘法,被乘數是ax,積為32位.積的高16位在dx中,積的低16位在ax中mov cx,0x400 ;0x400等于1024,將ax中的內存容量換為byte為三維mul cxshl edx,16 ;把dx移到高16位or edx,eax ;把積的低16位組合到edx,為32位的積add edx,0x100000 ;0x88子功能只會返回1MB以上的內存,故實際內存要加上1MB.mem_get_ok:mov [total_mem_bytes],edx ;將內存換成byte單位后存入total_mem_bytes處;----------------------進入保護模式-------------------------------- ;1 打開A20 ;2 加載gdt ;3 將cr0的pe位置1;---------------- 打開A20 ----------------------------------in al,0x92or al,0000_0010Bout 0x92,al;---------------- 加載GDT ----------------------------------lgdt [gdt_ptr];---------------- cr0 第0位置1 -------------------------------mov eax,cr0or eax,0x00000001mov cr0,eaxjmp dword SELECTOR_CODE:p_mode_start ;刷新流水線[bits 32] p_mode_start:mov ax,SELECTOR_DATA ;83~89 用選擇子初始化成各段寄存器mov ds,axmov es,axmov ss,axmov esp,LOADER_STACK_TOPmov ax,SELECTOR_VIDEOmov gs,axmov byte [gs:160], 'P'jmp $

boot.inc

;---------------loader和kernel ----------LOADER_BASE_ADDR equ 0x900 LOADER_START_SECTOR equ 0x2;-------------- gdt描述符屬性 ------------- DESC_G_4K equ 1_00000000000000000000000b ;G在段描述符第23位,將這里設為1,就是使用4K的密度 DESC_D_32 equ 1_0000000000000000000000b ;D在段描述符第22位,將這里設為1,表示操作數使用32位 DESC_L equ 0_000000000000000000000b ;L:段是否64位模式 64位代碼標記,此處標記為0便可。 DESC_AVL equ 0_00000000000000000000b ; cpu不用此位,暫置為0 DESC_LIMIT_CODE2 equ 1111_0000000000000000b ;段界限,段的長度 DESC_LIMIT_DATA2 equ DESC_LIMIT_CODE2 ; DESC_LIMIT_VIDEO2 equ 0000_000000000000000b ;段界限,設為0 DESC_P equ 1_000000000000000b ;p:是否在內存中 DESC_DPL_0 equ 00_0000000000000b ;DPL,為0的權限 DESC_DPL_1 equ 01_0000000000000b DESC_DPL_2 equ 10_0000000000000b DESC_DPL_3 equ 11_0000000000000b DESC_S_CODE equ 1_000000000000b ;代碼段 DESC_S_DATA equ DESC_S_CODE ;數據段,都是1,表示非系統段 DESC_S_sys equ 0_000000000000b DESC_TYPE_CODE equ 1000_00000000b ;x=1,c=0,r=0,a=0 代碼段是可執行的,非依從的,不可讀的,已訪問位a清0. DESC_TYPE_DATA equ 0010_00000000b ;x=0,e=0,w=1,a=0 數據段是不可執行的,向上擴展的,可寫的,已訪問位a清0.DESC_CODE_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_CODE2 + DESC_P + DESC_DPL_0 + DESC_S_CODE + DESC_TYPE_CODE + 0x00 ;代碼段的平坦模型 DESC_DATA_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_DATA2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x00 DESC_VIDEO_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_VIDEO2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x0b;-------------- 選擇子屬性 --------------- RPL0 equ 00b ;訪問權限 RPL1 equ 01b RPL2 equ 10b RPL3 equ 11b TI_GDT equ 000b ;訪問GDT TI_LDT equ 100b ;訪問LDT

編譯:

nasm -I include/ -o mbr.bin mbr.S nasm -I include/ -o loader.bin loader.S

裝載至磁盤

dd if=/os/bochs/mbr.bin of=/os/bochs/hd60M.img bs=512 count=1 conv=notrunc dd if=/os/bochs/loader.bin of=/os/bochs/hd60M.img bs=512 count=4 conv=notrunc seek=2

運行

bin/bochs -f bin/bochsrc.disk

loader.S

自己寫的,注釋很全,但是可能有點問題

%include "boot.inc"section loader vstart=LOADER_BASE_ADDRLOADER_STACK_TOP equ LOADER_BASE_ADDR ;保護模式下的棧;構建 gdt 及其內部的描述符GDT_BASE: dd 0x00000000 ;GDT的第0個段不可用dd 0x00000000; 定義了三個有用的段描述符CODE_DESC: dd 0x0000FFFF ;段描述符的低4字節,其中的低2字節是段長度 FFFF,高2字節是段基址 0000,dd DESC_CODE_HIGH4 ;代碼段的高四節,已經定義好了DATA_STACK_DESC: dd 0x0000FFFF ;數據段和棧段的段描述符dd DESC_DATA_HIGH4 ;顯存段描述符,0xb8000~0xbffff是用于文本模式的顯示內存,段基址:0x8000 長度 0007 VIDEO_DESC: dd 0x80000007 ;limit=(0xbffff-0xb8000)/4k = 0x7 4k是段粒度dd DESC_VIDEO_HIGH4 ;此時dpl為0GDT_SIZE equ $ - GDT_BASE ;19~20 獲取GDT的大小,為加載GDT做準備GDT_LIMIT equ GDT_SIZE - 1times 60 dq 0 ;此處預留60個描述符的空位,為了將來往GDT中添加其它描述符,提前保留空間SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0 ;相當于(CODE_DESC - GDT_BASE)/8 + TI_GDT + RPL0,構建代碼段的段選擇子,段描述符+TI+PRLSELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0 ;同上SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0 ;同上;total_mem_bytes用于保存內存容量,以字節為單位,此位置比較好記;當前偏移 loader.bin 文件頭0x200字節 loader.bin的加載地址是0x900 4個段描述符的定義 32 dq了60個 480 = 512 = 0x200;故total_mem_bytes內存中的地址是0xb00 將來在內核咱們會引用此地址total_mem_bytes dd 0 ;存儲獲取到的內存容量;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;以下是gdt的指針,前2字節是gdt界限,后四字節是gdt起始地址gdt_ptr dw GDT_LIMIT ;定義GDT的指針.前16位,是GDT以字節為單位的長度,也就是GDT大小減1dd GDT_BASE ;GDT的起始位置;人工對齊:total_mem_bytes 4+gdt_ptr 6+ards_buf 244+ards_nr2,共256字節ards_buf times 244 db 0ards_nr dw 0 ;用于記錄ARDS結構體數量,每執行一次中斷就會獲得一個ards結構的數據loader_start:;int 15h eax = 0000E820h,edx = 534D4150h('SMAP')獲取內存布局xor ebx,ebx ;第一次調用ebx要為0mov edx,0x543d4150 ;edx只賦值一次,循環體中不改變mov di,ards_buf ;ards結構緩沖區,es:di,BIOS將獲取到的內存信息寫到此寄存器指向的內存,每次都以ARDS格式返回 .e820_mem_get_loop: ;循環獲取每個ARDS內存范圍描述結構mov eax,0x0000e820 ;子功能號,eax用來指定子功能號,每次執行 int 0x15后,eax值會變為0x534d4150mov ecx,20 ;ARDS結構的字節大小,ARDS地址范圍描述符是20字節int 0x15jc .e820_failed_so_try_e801 ;若cf位為1嘖有錯誤發生,嘗試0xe801子功能add di,cx ;使di增加20字節指向緩沖區中新ARDS結構位置inc word [ards_nr] ;記錄ARDS數量cmp ebx,0 ;ebx存放后續值,下一個ARDS的地址,在cf為0的情況下,若ebx為0,表示這是最后一個ARDS結構jnz .e820_mem_get_loop;在只有ards結構中,找出(base_add_low + length_low)的最大值,即內存大小mov cx,[ards_nr] ;遍歷每一個ARDS結構體,循環次數是ARDS的數量mov ebx,ards_bufxor edx,edx ;edx為最大的內存容量,在此先清0 .find_max_mem_area: ;無需判斷type是否為1,最大內存塊一定是可被使用的mov eax,[ebx] ;base_add_lowadd eax,[ebx+8] ;length_lowadd ebx,20 ;指向緩沖區中下一個ARDS結構cmp edx,eax ;冒泡排序,找出最大,edx寄存器始終是最大的內存容量jge .next_ardsmov edx,eax .next_ards:loop .find_max_mem_areajmp .mem_get_ok;----------- int 15h ax = E801h 獲取內存大小,最大支持4G ------------------- ; 返回后,ax cx 值一樣,以KB為單位,bx dx 值都一樣,以64KB為單位 ; 在ax和cx寄存器中為低16MB,在bx和dx寄存器中為16Mb到4GB .e820_failed_so_try_e801:mov ax,0xe801 ;功能號int 0x15jc .e801_failed_so_try88 ;若當前e801方法失敗,就嘗試0x88方法;1. 先算出低15MB的內存,ax和cx中是以KB為單位的內存數量,將其轉化成以byte為單位mov cx,0x400 ;cx和ax一樣,cx用作乘數mul cxshl edx,16and eax,0x0000FFFFor edx,eaxadd edx,0x100000 ;ax只是15MB,故要加1MBmov esi,edx ;先把低15MB的內存容量存入esi寄存器備份;2. 再將16MB以上的內存轉化為byte為單位,寄存器bx和dx中是以64KB為單位的內存數量xor eax,eaxmov ax,bxmov ecx,0x10000 ;0x10000 十進制為 64KBmul ecx ;32位乘法,默認的被乘數是eax,積為64位,高32位存入edx,低32位存入eaxadd esi,eax ;由于此方法只能測出4GB以內的內存,故32位eax足夠了 edx肯定為0mov edx,esi ;edx為總內存大小jmp .mem_get_ok;----------- int 15h ah = 0x88 獲取內存大小,只能獲取64MB之內 ----------------------- .e801_failed_so_try88:;int 15后,ax存入的是以KB為單位的內存容量mov ah,0x88int 0x15jc .error_hltand eax,0x0000FFFF;16位乘法,被乘數是ax,積為32位.積的高16位在dx中,積的低16位在ax中mov cx,0x400 ;0x400等于1024,將ax中的內存容量換為byte為三維mul cxshl edx,16 ;把dx移到高16位or edx,eax ;把積的低16位組合到edx,為32位的積add edx,0x100000 ;0x88子功能只會返回1MB以上的內存,故實際內存要加上1MB.mem_get_ok:mov [total_mem_bytes],edx ;將內存換成byte單位后存入total_mem_bytes處;----------------------進入保護模式-------------------------------- ;1 打開A20 ;2 加載gdt ;3 將cr0的pe位置1;---------------- 打開A20 ----------------------------------in al,0x92or al,0000_0010Bout 0x92,al;---------------- 加載GDT ----------------------------------lgdt [gdt_ptr];---------------- cr0 第0位置1 -------------------------------mov eax,cr0or eax,0x00000001mov cr0,eaxjmp dword SELECTOR_CODE:p_mode_start ;刷新流水線,這將導致之前做的預測失效,從而起到了刷新的作用.error_hlt: ;出錯則掛起hlt[bits 32] p_mode_start:mov ax,SELECTOR_DATA ;83~89 用選擇子初始化成各段寄存器mov ds,axmov es,axmov ss,axmov esp,LOADER_STACK_TOPmov ax,SELECTOR_VIDEOmov gs,ax;創建頁目錄表及初始化也內存位圖 call setup_page;要將描述符表位置及偏移量寫入內存 gdt_ptr,一會用新位置重新加載 sgdt [gdt_ptr] ;存儲到原來gdt所有的位置;將gdt描述符中顯存段描述符中的段基址+0xc0000000 使其成為內核所在的高地址,0xc0000000~0xfffffff是內核地址 mov ebx,[gdt_ptr+2] ;前兩字節是偏移量,后面四個字節才是GDT基址 or dword [ebx + 0x18 + 4],0xc0000000 ;顯存段是第3個段描述符,每個段描述符是8字節,故是0x18 ;段描述符的高四節字節的最高位是段基址的31~24位;將gdt的基址加上0xc0000000使其成為內核所在的高地址 add dword [gdt_ptr + 2],0xc0000000add esp,0xc0000000 ;將棧地址同樣映射到內核地址;把頁目錄地址賦給cr3 mov eax,PAGE_DIR_TABLE_POS mov cr3,eax;打開cr0的pg位(第31位) mov eax,cr0 or eax,0x80000000 mov cr0,eax;在開啟分頁后,用gdt新的地址重新加載 lgdt [gdt_ptr] ;重新加載mov byte [gs:160],'V' ;顯存段段基址已經被更新,用字符V表示virtual addrjmp $;---------------------- 創建頁目錄及頁表 ---------------------------------- setup_page: ;先把頁目錄占用的空間逐字節清0mov ecx,4096 ;一個頁目錄項4Byte,一共1024個,所以是4096個mov esi,0 .clear_page_dir:mov byte [PAGE_DIR_TABLE_POS + esi],0inc esiloop .clear_page_dir;開始創建頁目錄項(PDE) .create_pde: ;創建Page Directory Entrymov eax,PAGE_DIR_TABLE_POS ;0x10000000add eax,0x1000 ;此時eax為第一個頁表的位置及屬性,0x10001000mov ebx,eax ;此處為ebx賦值,是為.create_pte做準備,ebx為基址; 下面將頁目錄0和0xc00都存為第一個頁表的地址,每個頁表表示4MB內存 ; 這樣0xc03fffff以下的地址和0x003fffff以下的地址都指向相同的頁表 ; 這是為將地址映射為內核地址做準備or eax,PG_US_U | PG_RW_W | PG_P ;頁目錄項的屬性RW和P為1,US為1,表示用戶屬性,所有特權級都可以訪問mov [PAGE_DIR_TABLE_POS + 0x0],eax ;第一個目錄項,頁目錄表中第1個目錄寫入第一個頁表的位置0x101000及屬性7mov [PAGE_DIR_TABLE_POS + 0xc00],eax ;一個頁表項占4個字節,0xc00表示第768個頁表占用的頁表項,0xc00以上的目錄用于內核空間;也就是頁表的 0xc0000000~0xfffffff 共計1G屬于內核,0x0~0xbfffffff共計3G屬于用戶進程sub eax,0x1000 ;現在是0x100007mov [PAGE_DIR_TABLE_POS + 4092],eax ;使最后一個目錄項指向頁目錄表自己;下面創建頁表項(PTE)mov ecx,256 ;1M低端內存 / 每頁大小 4K = 256mov esi,0mov edx,PG_US_U | PG_RW_W | PG_P ;屬性為7 .create_pte: ;創建Page Table Entrymov [ebx+esi*4],edx ;此時ebx已經在上面通過eax賦值為0x101000,也就是第一個頁表的地址add edx,4096inc esiloop .create_pte;創建內核其它表的PDEmov eax,PAGE_DIR_TABLE_POSadd eax,0x2000 ;此時eax為第二個頁表的位置or eax,PG_US_U | PG_RW_W | PG_P ;頁目錄項的屬性US RW和P位都為1mov ebx,PAGE_DIR_TABLE_POSmov ecx,254 ;范圍為第769~1022所有的目錄項數量mov esi,769 .create_kernel_pde:mov [ebx+esi*4],eaxinc esiadd eax,0x1000loop .create_kernel_pderet

loader.S

%include "boot.inc"section loader vstart=LOADER_BASE_ADDRLOADER_STACK_TOP equ LOADER_BASE_ADDR;構建gdt及其內部的描述符GDT_BASE: dd 0x00000000 dd 0x00000000CODE_DESC: dd 0x0000FFFF dd DESC_CODE_HIGH4DATA_STACK_DESC: dd 0x0000FFFFdd DESC_DATA_HIGH4VIDEO_DESC: dd 0x80000007 ; limit=(0xbffff-0xb8000)/4k=0x7dd DESC_VIDEO_HIGH4 ; 此時dpl為0GDT_SIZE equ $ - GDT_BASEGDT_LIMIT equ GDT_SIZE - 1 times 60 dq 0 ; 此處預留60個描述符的空位(slot)SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0 ; 相當于(CODE_DESC - GDT_BASE)/8 + TI_GDT + RPL0SELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0 ; 同上SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0 ; 同上 ; total_mem_bytes用于保存內存容量,以字節為單位,此位置比較好記。; 當前偏移loader.bin文件頭0x200字節,loader.bin的加載地址是0x900,; 故total_mem_bytes內存中的地址是0xb00.將來在內核中咱們會引用此地址total_mem_bytes dd 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;以下是定義gdt的指針,前2字節是gdt界限,后4字節是gdt起始地址gdt_ptr dw GDT_LIMIT dd GDT_BASE;人工對齊:total_mem_bytes4字節+gdt_ptr6字節+ards_buf244字節+ards_nr2,共256字節ards_buf times 244 db 0ards_nr dw 0 ;用于記錄ards結構體數量loader_start:;------- int 15h eax = 0000E820h ,edx = 534D4150h ('SMAP') 獲取內存布局 -------xor ebx, ebx ;第一次調用時,ebx值要為0mov edx, 0x534d4150 ;edx只賦值一次,循環體中不會改變mov di, ards_buf ;ards結構緩沖區 .e820_mem_get_loop: ;循環獲取每個ARDS內存范圍描述結構mov eax, 0x0000e820 ;執行int 0x15后,eax值變為0x534d4150,所以每次執行int前都要更新為子功能號。mov ecx, 20 ;ARDS地址范圍描述符結構大小是20字節int 0x15jc .e820_failed_so_try_e801 ;若cf位為1則有錯誤發生,嘗試0xe801子功能add di, cx ;使di增加20字節指向緩沖區中新的ARDS結構位置inc word [ards_nr] ;記錄ARDS數量cmp ebx, 0 ;若ebx為0且cf不為1,這說明ards全部返回,當前已是最后一個jnz .e820_mem_get_loop;在所有ards結構中,找出(base_add_low + length_low)的最大值,即內存的容量。mov cx, [ards_nr] ;遍歷每一個ARDS結構體,循環次數是ARDS的數量mov ebx, ards_buf xor edx, edx ;edx為最大的內存容量,在此先清0 .find_max_mem_area: ;無須判斷type是否為1,最大的內存塊一定是可被使用mov eax, [ebx] ;base_add_lowadd eax, [ebx+8] ;length_lowadd ebx, 20 ;指向緩沖區中下一個ARDS結構cmp edx, eax ;冒泡排序,找出最大,edx寄存器始終是最大的內存容量jge .next_ardsmov edx, eax ;edx為總內存大小 .next_ards:loop .find_max_mem_areajmp .mem_get_ok;------ int 15h ax = E801h 獲取內存大小,最大支持4G ------ ; 返回后, ax cx 值一樣,以KB為單位,bx dx值一樣,以64KB為單位 ; 在ax和cx寄存器中為低16M,在bx和dx寄存器中為16MB到4G。 .e820_failed_so_try_e801:mov ax,0xe801int 0x15jc .e801_failed_so_try88 ;若當前e801方法失敗,就嘗試0x88方法;1 先算出低15M的內存,ax和cx中是以KB為單位的內存數量,將其轉換為以byte為單位mov cx,0x400 ;cx和ax值一樣,cx用做乘數mul cx shl edx,16and eax,0x0000FFFFor edx,eaxadd edx, 0x100000 ;ax只是15MB,故要加1MBmov esi,edx ;先把低15MB的內存容量存入esi寄存器備份;2 再將16MB以上的內存轉換為byte為單位,寄存器bx和dx中是以64KB為單位的內存數量xor eax,eaxmov ax,bx mov ecx, 0x10000 ;0x10000十進制為64KBmul ecx ;32位乘法,默認的被乘數是eax,積為64位,高32位存入edx,低32位存入eax.add esi,eax ;由于此方法只能測出4G以內的內存,故32位eax足夠了,edx肯定為0,只加eax便可mov edx,esi ;edx為總內存大小jmp .mem_get_ok;----------------- int 15h ah = 0x88 獲取內存大小,只能獲取64M之內 ---------- .e801_failed_so_try88: ;int 15后,ax存入的是以kb為單位的內存容量mov ah, 0x88int 0x15jc .error_hltand eax,0x0000FFFF;16位乘法,被乘數是ax,積為32位.積的高16位在dx中,積的低16位在ax中mov cx, 0x400 ;0x400等于1024,將ax中的內存容量換為以byte為單位mul cxshl edx, 16 ;把dx移到高16位or edx, eax ;把積的低16位組合到edx,為32位的積add edx,0x100000 ;0x88子功能只會返回1MB以上的內存,故實際內存大小要加上1MB.mem_get_ok:mov [total_mem_bytes], edx ;將內存換為byte單位后存入total_mem_bytes處。;----------------- 準備進入保護模式 ------------------- ;1 打開A20 ;2 加載gdt ;3 將cr0的pe位置1;----------------- 打開A20 ----------------in al,0x92or al,0000_0010Bout 0x92,al;----------------- 加載GDT ----------------lgdt [gdt_ptr];----------------- cr0第0位置1 ----------------mov eax, cr0or eax, 0x00000001mov cr0, eaxjmp dword SELECTOR_CODE:p_mode_start ; 刷新流水線,避免分支預測的影響,這種cpu優化策略,最怕jmp跳轉,; 這將導致之前做的預測失效,從而起到了刷新的作用。 .error_hlt: ;出錯則掛起hlt[bits 32] p_mode_start:mov ax, SELECTOR_DATAmov ds, axmov es, axmov ss, axmov esp,LOADER_STACK_TOPmov ax, SELECTOR_VIDEOmov gs, ax; 創建頁目錄及頁表并初始化頁內存位圖call setup_page;要將描述符表地址及偏移量寫入內存gdt_ptr,一會用新地址重新加載sgdt [gdt_ptr] ; 存儲到原來gdt所有的位置;將gdt描述符中視頻段描述符中的段基址+0xc0000000mov ebx, [gdt_ptr + 2] or dword [ebx + 0x18 + 4], 0xc0000000 ;視頻段是第3個段描述符,每個描述符是8字節,故0x18。;段描述符的高4字節的最高位是段基址的31~24位;將gdt的基址加上0xc0000000使其成為內核所在的高地址add dword [gdt_ptr + 2], 0xc0000000add esp, 0xc0000000 ; 將棧指針同樣映射到內核地址; 把頁目錄地址賦給cr3mov eax, PAGE_DIR_TABLE_POSmov cr3, eax; 打開cr0的pg位(第31位)mov eax, cr0or eax, 0x80000000mov cr0, eax;在開啟分頁后,用gdt新的地址重新加載lgdt [gdt_ptr] ; 重新加載mov byte [gs:160], 'V' ;視頻段段基址已經被更新,用字符v表示virtual addrjmp $;------------- 創建頁目錄及頁表 --------------- setup_page: ;先把頁目錄占用的空間逐字節清0mov ecx, 4096mov esi, 0 .clear_page_dir:mov byte [PAGE_DIR_TABLE_POS + esi], 0inc esiloop .clear_page_dir;開始創建頁目錄項(PDE) .create_pde: ; 創建Page Directory Entrymov eax, PAGE_DIR_TABLE_POSadd eax, 0x1000 ; 此時eax為第一個頁表的位置及屬性mov ebx, eax ; 此處為ebx賦值,是為.create_pte做準備,ebx為基址。; 下面將頁目錄項0和0xc00都存為第一個頁表的地址, ; 一個頁表可表示4MB內存,這樣0xc03fffff以下的地址和0x003fffff以下的地址都指向相同的頁表, ; 這是為將地址映射為內核地址做準備or eax, PG_US_U | PG_RW_W | PG_P ; 頁目錄項的屬性RW和P位為1,US為1,表示用戶屬性,所有特權級別都可以訪問.mov [PAGE_DIR_TABLE_POS + 0x0], eax ; 第1個目錄項,在頁目錄表中的第1個目錄項寫入第一個頁表的位置(0x101000)及屬性(7)mov [PAGE_DIR_TABLE_POS + 0xc00], eax ; 一個頁表項占用4字節,0xc00表示第768個頁表占用的目錄項,0xc00以上的目錄項用于內核空間,; 也就是頁表的0xc0000000~0xffffffff共計1G屬于內核,0x0~0xbfffffff共計3G屬于用戶進程.sub eax, 0x1000mov [PAGE_DIR_TABLE_POS + 4092], eax ; 使最后一個目錄項指向頁目錄表自己的地址;下面創建頁表項(PTE)mov ecx, 256 ; 1M低端內存 / 每頁大小4k = 256mov esi, 0mov edx, PG_US_U | PG_RW_W | PG_P ; 屬性為7,US=1,RW=1,P=1 .create_pte: ; 創建Page Table Entrymov [ebx+esi*4],edx ; 此時的ebx已經在上面通過eax賦值為0x101000,也就是第一個頁表的地址 add edx,4096inc esiloop .create_pte;創建內核其它頁表的PDEmov eax, PAGE_DIR_TABLE_POSadd eax, 0x2000 ; 此時eax為第二個頁表的位置or eax, PG_US_U | PG_RW_W | PG_P ; 頁目錄項的屬性US,RW和P位都為1mov ebx, PAGE_DIR_TABLE_POSmov ecx, 254 ; 范圍為第769~1022的所有目錄項數量mov esi, 769 .create_kernel_pde:mov [ebx+esi*4], eaxinc esiadd eax, 0x1000loop .create_kernel_pderet

總結

以上是生活随笔為你收集整理的操作系统真相还原的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

av免费在线观看1 | 日韩亚洲在线观看 | 久久久久国产视频 | 成人网大片 | 欧美日韩在线视频一区二区 | 国产成人综 | 夜夜嗨av色一区二区不卡 | 国产精品久久久久久久久久不蜜月 | 我爱av激情网 | 丁香六月在线 | 337p西西人体大胆瓣开下部 | 黄视频色网站 | 国产综合小视频 | 99热播精品 | 正在播放日韩 | 91禁在线观看 | 日日弄天天弄美女bbbb | 久草精品视频在线看网站免费 | 日韩一二区在线 | 五月天婷婷免费视频 | 奇米四色影狠狠爱7777 | 久草视频播放 | 久久99爱视频 | 天天操天天摸天天射 | 99中文字幕视频 | 免费看的黄色录像 | 91资源在线 | 日韩,精品电影 | 亚洲精品2区| 亚洲视频 在线观看 | 欧美精品在线视频观看 | 天天操天天色综合 | 久久久久久久久久久国产精品 | 国产高清av免费在线观看 | 亚洲成人欧美 | 国产高清第一页 | 黄色影院在线播放 | 久久高清免费观看 | 国产日韩亚洲 | 伊人午夜 | 国产日韩在线一区 | 日本性生活一级片 | 91国内产香蕉 | 国产精品福利午夜在线观看 | 九九九国产 | 91在线观看视频网站 | 亚洲观看黄色网 | 国产精品免费麻豆入口 | 少妇性bbb搡bbb爽爽爽欧美 | 久久不卡视频 | 国产欧美最新羞羞视频在线观看 | 亚洲国产人午在线一二区 | 国产一级视频免费看 | 在线观看免费av网 | 日韩免费视频一区二区 | 日韩资源在线播放 | 久草精品视频在线播放 | 在线观看 亚洲 | 亚洲精品在线免费观看视频 | 在线日韩亚洲 | a天堂免费 | 精品一区电影 | 日韩视频一区二区三区 | 天天操比| 午夜婷婷网 | 69欧美视频 | 在线播放你懂 | 国产91综合一区在线观看 | a视频免费看 | 久久国产美女 | 亚洲国产成人精品久久 | 婷婷性综合| 香蕉国产91| 在线电影播放 | 亚洲三级在线免费观看 | 99热在线观看| 久久官网 | 福利一区在线视频 | 日韩羞羞| 丁香婷婷综合激情五月色 | 黄色亚洲在线 | 午夜精品一区二区三区免费 | 2019免费中文字幕 | 五月天婷婷丁香花 | 婷香五月 | 日韩在线第一区 | 狠狠狠色丁香婷婷综合久久五月 | 日韩欧美第二页 | 美女视频久久黄 | 久草在线视频精品 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 91在线免费观看国产 | 成人性生交大片免费观看网站 | 日韩中字在线 | 亚洲黄色av网址 | 怡春院av | 韩国一区二区av | 国产精品一区二区在线看 | 黄色三级在线观看 | 国产成人精品久久 | 久草在线免费看视频 | 国产精品免费久久久久 | 欧美另类性 | 国产成人精品久久二区二区 | 又黄又刺激视频 | 激情网综合 | 日韩高清黄色 | 午夜.dj高清免费观看视频 | 91福利试看| 中文字幕国语官网在线视频 | 日韩免费在线网站 | 色偷偷av男人天堂 | av电影一区二区三区 | 中文字幕在线观看网站 | 在线看小早川怜子av | 在线视频 影院 | 91视频 - x99av | 久久免费资源 | 99热这里只有精品国产首页 | 国产成人一区二区三区久久精品 | 亚洲 欧洲av | 国产精品一区二区三区在线免费观看 | 99视频在线精品免费观看2 | 91高清在线看 | 久久精品国产免费观看 | 中文字幕在线观看免费 | 国产精品porn | 色资源二区在线视频 | 91在线看视频免费 | 999精品在线| 91成版人在线观看入口 | 999超碰 | 日韩精品视频在线免费观看 | 国产毛片aaa | 免费看片成人 | 日韩毛片一区 | av免费在线播放 | 国产精品久久久久久久午夜片 | 日韩大片免费在线观看 | 五月情婷婷 | 精品一区二区三区在线播放 | 天天射夜夜爽 | 九九久久免费视频 | 天天看天天操 | 超碰97免费 | 精品久久久久久久久久 | 夜夜躁日日躁狠狠躁 | 久久国产精品久久国产精品 | 国产亚洲精品无 | 久久久久免费观看 | 久热电影 | 中国一级特黄毛片大片久久 | 午夜精品一区二区三区免费 | 狠狠躁日日躁夜夜躁av | 精品一区精品二区 | 五月婷婷丁香激情 | 亚洲播播| 成人午夜电影免费在线观看 | 综合伊人av | 成人午夜电影在线 | 久草影视在线观看 | 亚洲春色综合另类校园电影 | av综合网址 | 精品视频久久久久久 | 99热手机在线 | 婷婷精品视频 | 日韩性网站 | 婷婷激情小说网 | 日韩免费视频在线观看 | 99精品视频播放 | 四虎在线影视 | 婷婷色综| 人人澡人人舔 | 久久久久 | 99精品国产福利在线观看免费 | 91视频高清免费 | 黄av免费 | 中文字幕国内精品 | 欧美日韩一区二区三区不卡 | 伊人超碰在线 | 中文字幕亚洲精品日韩 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 久久精品2 | 亚洲一区久久 | 制服丝袜成人在线 | 日韩中文在线播放 | 国产日韩欧美综合在线 | 韩国av一区二区 | 国产黄色精品在线 | 四虎在线观看视频 | 欧美色图p | 精品久久久久久一区二区里番 | 亚洲视屏 | 天天天综合网 | 国产精品久久久久久久久久免费看 | 亚洲精品在线视频 | 在线成人小视频 | 久久国产精品视频观看 | 在线免费观看国产精品 | 亚洲无吗av| 久久久久亚洲天堂 | 免费久久久 | 日韩一区二区三区不卡 | 国产午夜精品一区二区三区嫩草 | 亚洲视频一区二区三区在线观看 | 99久久精品免费看国产麻豆 | 91丨九色丨首页 | 婷婷色中文字幕 | 久久精品久久久久 | 日韩精品久久一区二区三区 | 中文在线字幕免费观看 | 91免费国产在线观看 | 欧美日韩另类在线观看 | 国产成人高清av | 在线不卡中文字幕播放 | 美女视频黄免费 | 青草草在线| 国产精品精品国产 | 日韩电影在线观看一区二区 | 久久精品国产免费看久久精品 | 日韩电影一区二区在线观看 | 97香蕉视频| 午夜精品久久久久99热app | 99爱在线观看 | 欧洲精品二区 | 精品久久久久久综合日本 | 婷婷六月丁香激情 | 久久视频 | 国产精品一区二区中文字幕 | 久久不卡国产精品一区二区 | 免费十分钟 | 国产理论一区二区三区 | 国产美女永久免费 | 操操操人人 | 成全在线视频免费观看 | 精品国产成人 | 精品国自产在线观看 | 美女又爽又黄 | 奇米网在线观看 | 中文乱码视频在线观看 | www.激情五月.com | 亚洲h在线播放在线观看h | 亚洲一区久久久 | 香蕉视频啪啪 | 91香蕉视频在线下载 | 日日噜噜噜噜夜夜爽亚洲精品 | 国产黄色片免费观看 | 天天做天天干 | 五月天久久久 | 成年人视频在线免费 | 久久久久久久久电影 | 91在线视频播放 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 99久高清在线观看视频99精品热在线观看视频 | 成人免费一区二区三区在线观看 | 91精品啪在线观看国产 | 欧美日韩国产网站 | 24小时日本在线www免费的 | av在线一| 精品国产一区二区三区日日嗨 | 久久久久久久免费 | 精品亚洲男同gayvideo网站 | 国产在线免费 | 国产一及片 | 99精品欧美一区二区蜜桃免费 | 国产成人三级 | 91精品区 | 激情av网址| 98超碰在线 | www国产在线 | 久久久国产电影 | 日日摸日日添日日躁av | ,午夜性刺激免费看视频 | 人人搞人人爽 | 亚洲欧美成人网 | 国产综合久久 | 亚洲.www | 丁香六月天 | 国产大尺度视频 | 欧美巨乳网 | 久久婷婷激情 | 黄色片网站免费 | 国产成人精品久久久久 | 国产成人精品在线播放 | 日韩欧美91 | 国产高清在线视频 | 日日爱视频 | 六月丁香婷婷久久 | 在线视频观看国产 | 久久国产精品一区二区三区 | 97在线视 | 久久a视频 | 视频一区二区视频 | 日韩在线视频播放 | 欧美性黑人 | 日本黄色免费看 | 黄色三级在线看 | 亚洲第一中文字幕 | 中文区中文字幕免费看 | 黄色视屏免费在线观看 | 久久理论影院 | 97电影手机 | 成人午夜精品 | 日韩一区精品 | 91香蕉国产 | 激情欧美一区二区三区 | 欧美日韩国产mv | 天天天天爱天天躁 | 久久国产欧美日韩 | 久草免费资源 | 精品国产伦一区二区三区观看说明 | 色开心| 黄免费在线观看 | 天天综合婷婷 | 人人射人人插 | 久久五月天婷婷 | 国产成人高清在线 | 久草在线看片 | 国产成人精品一区二区三区网站观看 | 91九色视频在线观看 | 国产美女被啪进深处喷白浆视频 | 亚洲区另类春色综合小说校园片 | 五月婷婷,六月丁香 | 99精品视频网站 | 精品美女国产在线 | 国产美女搞久久 | 久久久久9999亚洲精品 | 久久影院一区 | 精品一区在线 | 国产高清在线精品 | 色噜噜色噜噜 | 久久免费观看少妇a级毛片 久久久久成人免费 | 香蕉影院在线播放 | 国产婷婷在线观看 | 亚洲理论片在线观看 | 日本韩国欧美在线观看 | 久久在线观看视频 | 久久综合五月婷婷 | 亚洲国产日韩一区 | 久久这里有精品 | 美女免费视频观看网站 | 久久高清 | 日韩国产精品一区 | 日日操天天爽 | 国内精品久久久久影院日本资源 | 久久精品超碰 | 免费av视屏 | 国产偷国产偷亚洲清高 | 亚洲欧美乱综合图片区小说区 | 日韩免费电影网站 | 成人av中文字幕在线观看 | 伊人婷婷| 九色91在线 | 新版资源中文在线观看 | 91影视成人 | 日韩在线观看你懂的 | 日本一区二区三区免费看 | 麻豆视频在线播放 | 久久久久久久久久久国产精品 | 成人av在线网址 | 日韩av在线看 | 91av视频| 国产精品久久久久999 | 国产在线视频导航 | 97超碰影视 | 婷婷去俺也去六月色 | 亚洲一级黄色大片 | 久久综合九色综合久久久精品综合 | 亚洲电影一级黄 | 在线日韩精品视频 | 久久精品国产免费观看 | 97电院网手机版 | 天天干天天操av | 在线免费视频 你懂得 | 久久精品在线 | 成人久久久久久久久久 | 日批视频| 天天艹天天 | 99免费在线| 97视频在线 | 午夜美女网站 | 区一区二在线 | 亚洲国产精品传媒在线观看 | 久久久久久亚洲精品 | 97香蕉久久国产在线观看 | 99热这里只有精品8 久久综合毛片 | 久久国产精品色av免费看 | 国产精品一区二区果冻传媒 | 国产视频在线免费 | 久精品视频在线观看 | 成人黄色短片 | 成人久久国产 | 国产在线a免费观看 | 国产精品第72页 | 日韩精品在线观看视频 | 国产乱对白刺激视频不卡 | 日韩一区视频在线 | 激情久久一区二区三区 | 精品国产一区二区三区久久久蜜月 | 天天曰| 精产嫩模国品一二三区 | 国产免费视频在线 | 国产免费亚洲高清 | 午夜成人免费电影 | 免费成人在线观看视频 | 视频在线观看亚洲 | 一区二区三区四区在线 | 在线免费色 | 精品久久久成人 | 欧美日韩精品在线观看视频 | 亚洲精品一区二区久 | 综合久久久久久久久 | 日韩精品中文字幕av | 麻豆视频在线免费看 | 久久久免费看片 | 最新国产精品久久精品 | 99久久视频 | 久久久免费 | 欧美日韩精品在线免费观看 | 我爱av激情网 | 国产剧在线观看片 | 欧美一区二区三区特黄 | 天天艹日日干 | 欧美日韩一区二区三区在线观看视频 | 国产精品久久久亚洲 | 国产69精品久久久久99 | 黄色免费大片 | 不卡的av电影在线观看 | 久久久高清一区二区三区 | 国产美女精品人人做人人爽 | 免费的成人av| 国产视频1区2区3区 久久夜视频 | 日韩在线第一区 | 亚洲国产精品第一区二区 | 日韩精品视频免费专区在线播放 | 美女网站视频久久 | 91少妇精拍在线播放 | 欧美三人交 | 亚洲va男人天堂 | 毛片的网址 | 亚洲男男gaygay无套同网址 | 男女免费视频观看 | 久久激情日本aⅴ | 色噜噜日韩精品欧美一区二区 | 色狠狠干 | 亚洲成av | 久久黄色免费观看 | 正在播放 久久 | 91在线播放国产 | a天堂免费| 91在线文字幕 | 久久久精品小视频 | a色视频 | 成人久久 | 丰满少妇一级 | 久久国内免费视频 | 日韩在线激情 | 特级a老妇做爰全过程 | 国产精品亚洲片夜色在线 | 在线观看国产一区 | 丁香花五月 | 亚洲欧美日韩在线一区二区 | 免费观看午夜视频 | 丁香婷婷激情网 | 亚洲黄色软件 | 99久久99| 91麻豆高清视频 | 日韩在线视频网址 | 欧美性生爱 | 欧美日韩国产二区 | 青春草视频在线播放 | 国产精品色在线 | 91高清免费在线观看 | 91高清不卡| 日韩美女高潮 | 美女视频一区 | 欧美淫aaa免费观看 日韩激情免费视频 | 久久天天躁狠狠躁亚洲综合公司 | 激情婷婷色 | 久草在线视频在线 | 国产91粉嫩白浆在线观看 | 99九九99九九九视频精品 | 青青河边草免费直播 | 成人免费视频网站 | 久久久久久久久久影院 | 国产偷v国产偷∨精品视频 在线草 | 97成人资源站 | 天天干天天怕 | 亚洲免费成人av电影 | 在线免费av观看 | 亚洲久草网 | 久草精品视频 | 男女免费视频观看 | 久久精品亚洲综合专区 | 欧美va电影 | 2024av| 国产69久久久 | 欧美黑人性爽 | 久久er99热精品一区二区三区 | 色噜噜在线观看视频 | 欧美一级小视频 | 国产色秀视频 | 2024国产精品视频 | 欧美日韩视频在线一区 | 黄色三级网站在线观看 | 香蕉影视 | 中文字幕在线观看免费高清完整版 | www亚洲视频 | 一区精品在线 | 天天射天天干天天插 | japanesexxxhd奶水 国产一区二区在线免费观看 | 久久久久国产精品午夜一区 | 毛片基地黄久久久久久天堂 | 久草精品视频在线看网站免费 | 东方av免费在线观看 | 天堂av免费在线 | 97在线观看免费观看 | 天天操比| 国产精品一区二区久久精品爱微奶 | 国产精品久久久久久av | 伊人首页 | 欧美另类高潮 | 国产高清福利在线 | www.国产精品 | 午夜精品一区二区三区免费 | 久草在线看片 | 97综合视频 | 午夜狠狠干 | 婷婷丁香色综合狠狠色 | 天天操天天干天天玩 | 2023国产精品自产拍在线观看 | 成人日批视频 | 久久久免费少妇 | 日韩欧美专区 | 黄色网大全 | av在线专区| 久久久久久久久国产 | 免费福利在线视频 | 国内亚洲精品 | 99国产视频在线 | 久久午夜影院 | 三级黄色理论片 | 国产成人久久精品亚洲 | 中文字幕在线视频免费播放 | 国产精品久久久久久久毛片 | 亚洲免费在线观看视频 | 免费人成网 | 99热精品国产一区二区在线观看 | 欧美午夜精品久久久久久浪潮 | 五月激情五月激情 | 91麻豆精品国产91久久久久久久久 | av电影亚洲 | 青草视频在线 | 国产精品久久三 | 久操视频在线观看 | 伊人看片 | 日韩精品1区2区 | 一区二区三区在线看 | 狠狠色丁香婷婷综合 | av女优中文字幕在线观看 | 九九视频热| 午夜久久福利影院 | 美女黄频免费 | 精品久久久久免费极品大片 | 精品在线免费视频 | 国产一区在线观看免费 | 国内精品在线看 | 中文字幕乱码在线播放 | 91亚·色| 国产九九九视频 | 91久久国产露脸精品国产闺蜜 | 国产伦精品一区二区三区照片91 | 久久99久久99精品 | 国产精品美女999 | 小草av在线播放 | 久免费视频| 日韩综合第一页 | 久久99精品国产99久久6尤 | 开心婷婷色| 欧美精品首页 | 日本不卡123区 | 97国产精品免费 | 五月天狠狠操 | www.天天操 | 国产高清免费观看 | 337p日本欧洲亚洲大胆裸体艺术 | 91av电影在线观看 | 午夜免费福利视频 | 香蕉手机在线 | 99在线热播| 久久综合五月婷婷 | 婷婷色伊人 | 伊人天天干| 免费在线一区二区 | 中文字幕一二 | 国产麻豆精品免费视频 | 国产福利精品一区二区 | 精品国产理论 | 亚洲免费av网站 | 日韩在线观看第一页 | 国产成人黄色 | 国产人成看黄久久久久久久久 | 日本中文字幕在线一区 | 久久9精品 | 亚洲最新毛片 | 国产精品久久久久久久久久久久冷 | 日韩狠狠操 | 日本色小说视频 | 色婷婷99 | 91传媒视频在线观看 | 免费看一及片 | 97超碰在线视 | 久久婷婷色 | 91色影院 | 丁香色婷婷| 日韩 在线 | 国产美女在线免费观看 | 久久96国产精品久久99软件 | 午夜精品久久久久久 | av片无限看| 中文字幕视频 | 欧美视频日韩视频 | 在线久久 | 在线观看黄a | 亚洲视频综合在线 | 久久综合狠狠综合 | 狠狠狠色 | 国产精在线 | 日韩在线第一 | 日韩av男人的天堂 | 综合激情伊人 | 91九色网站| 99色精品视频 | 国产一区二区免费在线观看 | 在线观看电影av | 成人在线播放网站 | 97**国产露脸精品国产 | 国产免费亚洲 | 免费开视频| 免费在线观看黄网站 | 久久久久久不卡 | 国产一二区视频 | 国内精品视频在线播放 | 久久艹在线观看 | 久久亚洲欧美 | 欧美激情第十页 | 五月激情姐姐 | 草樱av| 一级电影免费在线观看 | 激情综合六月 | 一区二区三区 中文字幕 | 久久99久久99精品中文字幕 | 午夜精品一二三区 | 日日夜夜天天射 | 国产精品久久久久久99 | 在线亚洲欧美日韩 | 日av免费 | 国产高清视频 | 亚洲精品av在线 | 一级黄色视屏 | 国产欧美久久久精品影院 | 在线国产专区 | 国产一区二区三区在线免费观看 | 欧美日韩不卡在线视频 | 亚洲片在线观看 | 欧美一区二区免费在线观看 | 亚洲精品玖玖玖av在线看 | 一区二区三区高清在线 | 久久黄色免费 | 免费黄色网止 | 欧美精品久久久久久久亚洲调教 | 91视频一8mav| 久久99热这里只有精品国产 | 久久人人艹 | 久久精品国产成人精品 | 色橹橹欧美在线观看视频高清 | 97超碰.com | 在线中文字幕视频 | 在线激情小视频 | 久久精品中文 | 天天综合狠狠精品 | 国产.精品.日韩.另类.中文.在线.播放 | 国产成在线观看免费视频 | 99这里只有久久精品视频 | 国产精品va在线播放 | 欧美伦理一区 | 女女av在线 | 粉嫩av一区二区三区免费 | 狠狠88综合久久久久综合网 | 视频在线观看入口黄最新永久免费国产 | 在线免费观看黄网站 | 午夜精品久久久久久99热明星 | 激情av资源网 | 麻豆成人小视频 | 国产1区2区3区在线 亚洲自拍偷拍色图 | 五月婷婷久久丁香 | 日本久久久久久科技有限公司 | 欧美午夜理伦三级在线观看 | 天天激情在线 | 久久精品久久久久久久 | 国产成人一区二区三区免费看 | 777xxx欧美| 日日夜夜精品视频 | 国产成人精品久久亚洲高清不卡 | 9在线观看免费高清完整版在线观看明 | 精品久久久久久久久久久久久久久久久久 | 亚洲免费在线观看视频 | 国产 日韩 在线 亚洲 字幕 中文 | 黄色一级在线免费观看 | 亚洲午夜电影网 | 美女免费网视频 | 日韩理论视频 | 国产精品一区二区在线播放 | www免费视频com━ | 亚洲精品乱码久久久一二三 | www.色婷婷| 91.精品高清在线观看 | 日韩视频免费在线观看 | 99精品视频观看 | www色网站| 亚洲精品中文在线观看 | 亚洲男男gaygayxxxgv | 99久久这里有精品 | 成人毛片在线观看视频 | 一区二区激情 | 国产精品1000 | 一区二区三区免费在线观看视频 | 国产成人精品一区二区三区免费 | 一区二区三区日韩在线观看 | 亚洲国内精品视频 | 狠狠操天天射 | 一区二区三区四区五区在线 | 欧美日韩一区二区三区在线免费观看 | 超碰夜夜| 亚洲九九 | 国产午夜精品免费一区二区三区视频 | 91麻豆精品国产91久久久久久久久 | 国产麻豆电影在线观看 | 国产玖玖视频 | 亚洲成av人片 | 国产亚洲日 | 成人在线观看免费视频 | 日本精品久久 | 久艹视频在线免费观看 | 久久9999久久免费精品国产 | 亚洲综合精品视频 | 九九热只有这里有精品 | 午夜精品久久 | 热re99久久精品国产66热 | 又黄又网站 | 日韩欧美一区二区三区在线 | 免费成人av在线看 | 人人超在线公开视频 | 成年人国产精品 | 国产精品第二十页 | 亚洲成av片人久久久 | www国产一区 | 永久免费视频国产 | 亚洲精品美女免费 | 精精国产xxxx视频在线播放 | 成人免费大片黄在线播放 | 久久久亚洲国产精品麻豆综合天堂 | 九九热久久久 | 中文在线字幕免费观看 | 婷婷色资源 | 色综合天天爱 | 91av视频网站| 亚洲专区欧美专区 | 丁香5月婷婷久久 | 国产女人免费看a级丨片 | 国产aaa毛片| 成人免费视频在线观看 | 国产主播大尺度精品福利免费 | 在线v| 天天狠狠操 | 欧美少妇xxxxxx | 香蕉视频在线视频 | 最近2019年日本中文免费字幕 | 久久 精品一区 | 夜夜骑天天操 | 91激情 | 亚洲日韩中文字幕 | 国产精品成人免费 | 国产亚洲精品久久久久久 | 成人久久18免费网站图片 | 五月视频 | 日韩大片在线观看 | 久久av观看| 婷色在线 | av在线色 | 97国产电影 | 狠狠地操 | 高清av中文字幕 | 中文在线天堂资源 | www欧美xxxx| 九九亚洲视频 | 五月天久久 | 在线观看日本高清mv视频 | 日韩av成人免费看 | 永久免费观看视频 | 天天曰天天曰 | 91av电影在线 | av在线电影网站 | 久久精品国产亚洲aⅴ | 久久视频在线视频 | 91在线视频在线观看 | 欧美日韩一区二区三区不卡 | 日韩中文字幕网站 | 婷婷草| 色99在线| 久草在线手机视频 | 久香蕉 | 日精品在线观看 | 国产高清免费观看 | 亚洲乱码久久久 | 久久高清精品 | 在线观看网站黄 | 午夜精品视频免费在线观看 | 精品国产伦一区二区三区免费 | 在线国产中文字幕 | 日躁夜躁狠狠躁2001 | 在线免费av观看 | 激情av在线播放 | 久久亚洲欧美日韩精品专区 | 日韩成人免费观看 | www国产一区 | 亚洲精品国产精品国自产观看 | 亚洲欧美日韩中文在线 | 免费观看www视频 | 天天操天天色天天射 | 久久久91精品国产一区二区三区 | 正在播放国产一区二区 | 久操视频在线免费看 | 成人在线观看你懂的 | 日韩高清不卡一区二区三区 | 久久精品韩国 | 久久99久久99精品免视看婷婷 | 一区二区精品视频 | 日本女人的性生活视频 | 伊人婷婷| 色av资源网 | 亚洲色图色 | 超级碰99| 国产97在线观看 | 婷婷av电影 | 日韩中文在线视频 | 日韩精品久久久久久中文字幕8 | 国产二区视频在线 | 亚洲天堂社区 | 免费黄av | 久久综合国产伦精品免费 | 成年人免费电影 | 欧美一区二视频在线免费观看 | 欧美最猛性xxxx | 亚洲 欧美 综合 在线 精品 | 免费亚洲一区二区 | 亚洲经典在线 | 久久综合九色欧美综合狠狠 | 亚洲国产精品99久久久久久久久 | 91精品国产福利在线观看 | 激情影院在线 | 操操操综合 | 久久国产露脸精品国产 | 91麻豆精品国产91 | 黄色a级片在线观看 | 婷婷丁香狠狠爱 | 91九色视频导航 | 高清不卡毛片 | 久久黄色免费视频 | 又湿又紧又大又爽a视频国产 | 国产成人区 | 超碰在线最新网址 | 国产午夜精品一区二区三区欧美 | 久久国产热 | 久久久精品二区 | 亚洲午夜精品一区 | 亚洲精品欧洲精品 | 国产精品黄色av | 丁香六月久久综合狠狠色 | 久久亚洲婷婷 | 91高清免费观看 | 在线观看黄色免费视频 | 精品久久久久久久久久久院品网 | 久久精品99国产精品日本 | 射射射av| 超碰人人草 | 丰满少妇一级 | 国产乱码精品一区二区蜜臀 | 免费网站观看www在线观看 | 深夜男人影院 | 亚州精品在线视频 | 九九色网 | 精品一区av| 国产精品亚洲精品 | 久久一区二区三区日韩 | 亚洲影院天堂 | 91香蕉视频在线下载 | 久草综合在线 | 国产一区二区在线看 | 狠狠干夜夜爽 | 91免费看片黄 | 国产色影院 | 色播五月激情综合网 | 女女av在线 | 成人午夜剧场在线观看 | 国产又粗又猛又色又黄网站 | 人人干在线观看 | 国产精品国产亚洲精品看不卡 | 精品影院一区二区久久久 | 亚洲一级在线观看 | 91网址在线观看 | 亚洲婷久久 | 国产免费小视频 | 中文字幕在线网 | 国产精品精品久久久久久 | 国产成人精品网站 | 一区二区中文字幕在线播放 | 亚洲精品xxxx | 国产黄大片在线观看 | av 一区二区三区 | 日韩一区二区三区不卡 | 99色在线视频 | 久久久久久蜜桃一区二区 | japanese黑人亚洲人4k | 久久免费视频一区 | 国内免费的中文字幕 | 亚洲片在线 | 国产精品免费观看国产网曝瓜 | 手机看片1042| 婷婷国产在线观看 | 亚洲永久精品一区 | 国产成人一区二区在线观看 | 狠狠网亚洲精品 | 久久电影国产免费久久电影 | 亚洲精品字幕在线观看 | 国产精品自产拍在线观看 | av中文资源在线 | 国产综合在线视频 | 日韩视频专区 | 国内精品久久久久久久影视简单 | 欧美性高跟鞋xxxxhd | 五月天综合 | 国产区精品在线 | 中文字幕麻豆 | 久久99国产精品久久 | 久热国产视频 | 国产精品亚洲人在线观看 | 久久爽久久爽久久av东京爽 | 九九免费精品 | 国产伦理一区二区三区 | 免费又黄又爽视频 | 9992tv成人免费看片 | 中文字幕日本特黄aa毛片 | 国产精品成人免费 | 免费黄a| 婷婷五月色综合 | 日韩欧美在线观看 | 国产成人在线观看 | 欧美极品在线播放 | 久久精品亚洲 | 亚洲免费在线观看视频 | 成人动漫一区二区三区 | 视频一区二区精品 | 亚洲免费资源 | 99r国产精品 | 欧美高清成人 | 欧美在线91 | 欧美一级视频在线观看 | 欧美一区二区三区激情视频 | 免费看一及片 | 欧美久草视频 | 国产黄色免费看 | 人人草人人草 | 国产综合在线观看视频 | 国产破处视频在线播放 | 亚洲精品免费在线观看 | 狠狠干电影| 久久精品欧美一区 | 欧美国产不卡 | 在线观看视频一区二区 | 亚洲一级在线观看 | 超碰国产在线观看 | 日日碰狠狠添天天爽超碰97久久 | 午夜精品久久久久久久爽 | av免费网站 | 免费在线观看日韩视频 | 美女一区网站 | 97成人在线 | 日韩精品视频免费专区在线播放 | 日本公妇色中文字幕 | 在线观看91精品国产网站 | 日韩免费av在线 | 亚洲我射av | 欧美精品网站 | 国产精品亚洲片在线播放 | 中文字幕日韩伦理 | 在线看日韩| 国产精品一二三 |