卓一笔记---局部描述符表(LDT寻址表)的使用
生活随笔
收集整理的這篇文章主要介紹了
卓一笔记---局部描述符表(LDT寻址表)的使用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? 知識是浩瀚的海洋,一人窮其一生也不可能學完.但是每個人都可以像令狐沖/喬峰一樣學一門獨門絕技,馳騁江湖.匯編就是這樣一門武學,靜靜修之,可使內功與日俱增.今天要講的是LDT尋址表.
? ? ? GDT,LDT表都是32位系統用來尋址用的.GDT是全局的,LDT是局部的.當有局部任務時,GDT中應該包含LDT表存放的位置,這樣當處理器在段描述符表中找到LDT描述表后發現是局部任務,這樣就可以通過其記錄的LDT表的位置,找到LDT表,然后在LDT表中找到相應的段描述符,如下圖所示:
段描述符表=全局任務(GDT+LDT)GDTR寄存器中用于存放全局描述符表GDT的32位線性基地址和16位的表的長度值。LDTR寄存器中用于存放局部描述符表LDT的32位線性基地址和16位的表的長度值。通過系統指令,lgdt將GDT的線性基址和長度值加載到GDTR寄存器中,lldt將LDT的線性基址和長度值加載到LDTR寄存器中。
? ? ?下面是一段實踐代碼:
1,構建pm.inc文件
DA_LDT EQU 82h;局部描述符表段類型值 DA_32 EQU 4000h ;32位段 DA_DRW EQU 92h ; 存在的可讀寫數據段屬性值 DA_DRWA EQU 93h ; 存在的已訪問可讀寫數據段類型值 DA_C EQU 98h ;存在的只執行代碼段屬性DA_DPL1 EQU 20h ; DPL = 1SA_TIG EQU 0 ; ┓TI SA_TIL EQU 4 ; ┛;描述符定義,傳進來的參數會自動裝到對應的字節中 ;usage:Descriptor Base,Limit,Attr %macro Descriptor 3dw %2&0FFFFh ;段界限1dw %1&0FFFFh ;段基址1db (%1>>16)&0FFh ;段基址2dw ((%2>>8)&0F00h)|(%3&0F0FFh) ;屬性1 + 段界限2 + 屬性2db (%1>>24)&0FFh ;段基址3 %endmacro ;共8個字節2.構建pmldt.asm文件
; ========================================== ; pmldt.asm ; 編譯方法:make -f MakeFileLDT ; ==========================================%include "pm.inc" ;常量,宏,以及一些說明 org 0100h jmp LABEL_BEGIN ;跳到開始處執行,此時不會修改cs,cs仍然為0,偏移地址會加上7c00 [SECTION .gdt] ;定義GDT全局描述符號(為(段地址,段界限,屬性)三元組,占8字節空間) LABEL_GDT: Descriptor 0,0,0 ;空描述符 LABEL_DESC_NORMAL:Descriptor 0, 0ffffh,DA_DRW ;Normal描述符 LABEL_DESC_CODE32:Descriptor 0,SegCode32Len-1,DA_C+DA_32 ;指向32位保護模式非一致代碼段 LABEL_DESC_CODE16:Descriptor 0, 0ffffh,DA_C ;指向16位,非一致代碼 LABEL_DESC_DATA:Descriptor 0, DataLen-1, DA_DRW+DA_DPL1 ;Data 用來驗證保護模式修改了這個值 LABEL_DESC_STACK:Descriptor 0,TopOfStack, DA_DRWA+DA_32 ;stack,32位,用來存儲函數調用時暫時存入的參數 LABEL_DESC_LDT:Descriptor 0, LDTLen - 1, DA_LDT ;LDT基地址描述符 LABEL_DESC_VIDEO:Descriptor 0B8000h,0ffffh,DA_DRW ;顯存(顯卡)首地址描述符 ;GDT結束 GdtLen equ $-LABEL_GDT ;GDT長度 GdtPtr dw GdtLen-1 ;GDT界限dd 0 ;GDT基地址 ;GDT選擇子 SelectorNormal equ LABEL_DESC_NORMAL-LABEL_GDT SelectorCode32 equ LABEL_DESC_CODE32-LABEL_GDT SelectorCode16 equ LABEL_DESC_CODE16-LABEL_GDT SelectorData equ LABEL_DESC_DATA-LABEL_GDT SelectorStack equ LABEL_DESC_STACK-LABEL_GDT SelectorVideo equ LABEL_DESC_VIDEO-LABEL_GDT SelectorLDT equ LABEL_DESC_LDT - LABEL_GDT ;選擇子指向LDT基址 ;這里比較特殊,各個描述符號的最右側3位都為0,因此相減后,就是描述符在GDT表中的索引 ;END of [SECTION .gdt][SECTION .data1] ALIGN 32 [BITS 32] LABEL_DATA: SPValueInRealMode dw 0 ;從保護模式跳入實模式時,用來當做棧偏移地址 PMMessage: db "In Protect Mode now, ^_^",0 ;在保護模式中顯示 OffsetPMMessage equ PMMessage-$$ ;保護模式下相對于選擇子基址的偏移量 DataLen equ $-LABEL_DATA ;END of [SECTION .data1];全局堆棧段 [SECTION .gs] ALIGN 32 [BITS 32] LABEL_STACK:times 512 db 0TopOfStack equ $-LABEL_STACK-1 ;相對于堆棧選擇子基址的字節偏移,指向512字節末尾字節 ;END of [SECTION .gs][SECTION .s16] [BITS 16] LABEL_BEGIN:mov ax,csmov ds,axmov es,axmov ss,axmov sp,0100hmov [LABEL_GO_BACK_TO_REAL+3],ax ;由保護模式跳回來,跳到這個基地址mov [SPValueInRealMode],sp; 初始化數據段描述符xor eax, eaxmov ax, dsshl eax, 4add eax, LABEL_DATAmov word [LABEL_DESC_DATA + 2], axshr eax, 16mov byte [LABEL_DESC_DATA + 4], almov byte [LABEL_DESC_DATA + 7], ah;初始化LDT在GDT中的描述符,對準LDT表的基址xor eax,eaxmov ax, dsshl eax, 4 ;注意偏移地址時這里一定時eax,要不然20位地址就溢出了add eax,LABEL_LDTmov word [LABEL_DESC_LDT+2],axshr eax,16mov byte [LABEL_DESC_LDT+4],almov byte [LABEL_DESC_LDT+7],ah; 初始化堆棧段描述符xor eax, eaxmov ax, dsshl eax, 4add eax, LABEL_STACKmov word [LABEL_DESC_STACK + 2], axshr eax, 16mov byte [LABEL_DESC_STACK + 4], almov byte [LABEL_DESC_STACK + 7], ah;初始化32位代碼段全局描述符的段基址xor eax,eaxmov ax,csshl eax,4add eax,LABEL_SEG_CODE32mov word [LABEL_DESC_CODE32+2],axshr eax,16mov byte [LABEL_DESC_CODE32+4],almov byte [LABEL_DESC_CODE32+7],ah;初始化LDT中的描述符xor eax,eaxmov ax,dsshl eax,4add eax,LABEL_CODE_Amov word [LABEL_LDT_DESC_CODEA+2],axshr eax,16mov byte [LABEL_LDT_DESC_CODEA+4],almov byte [LABEL_LDT_DESC_CODEA+7],ah;初始化16位代碼段全局描述符的段基址xor eax,eaxmov ax,csshl eax,4add eax,LABEL_SEG_CODE16mov word [LABEL_DESC_CODE16+2],axshr eax,16mov byte [LABEL_DESC_CODE16+4],almov byte [LABEL_DESC_CODE16+7],ah;為加載GDT表做準備,先將GDT表的界限和起始地址找到存到Gdtptr中xor eax,eaxmov ax,dsshl eax,4add eax,LABEL_GDTmov dword [GdtPtr + 2],eax ;將GDT的基地址放好lgdt [GdtPtr] ;將GDT表加載進來,后面可以訪問GDT表中的值;關中斷cli;打開地址線A20in al,92hor al,00000010bout 92h,al;準備切換到保護模式mov eax,cr0or eax,1mov cr0,eax;真正進入保護模式jmp dword SelectorCode32:0 ;執行這句話,為了將SelectorCode32;指向的32為保護模式代碼載入cs中;并跳轉到SelectorCode32:0處LABEL_REAL_ENTRY: ;從保護模式跳回到實模式會走到這里mov ax,csmov ds,axmov es,axmov ss,axmov sp,[SPValueInRealMode] in al,92h ;關閉A20地址線and al,11111101b out 92h, al sti ;打中斷mov ax,4c00h ;啟動21號中斷,回到dos窗口 int 21h ;;END of [SECTION .s16][SECTION .s32] [BITS 32] LABEL_SEG_CODE32:mov ax,SelectorDatamov ds,ax ;數據段選擇子mov ax,SelectorVideomov gs,ax ;視屏段選擇子mov ax,SelectorStackmov ss,ax ;堆棧選擇子 mov esp,TopOfStack ;把棧頂初始化,ss:esp指向棧頂;下面顯示一個字符mov ah,0ch ;0代表黑底,c代表紅字xor esi,esixor edi,edimov esi,OffsetPMMessage ;ds:esi指向Data數據區mov edi,(80*10+0)*2 ;目的數據偏移.屏幕第10行,第0列cld.1:lodsb ;ds:esi指向的數據會自動加載到al中test al,al ;al為0時代表沒有數據了需要結束顯示jz .2mov [gs:edi],axadd edi,2 ;顯示一個字符占兩個字節(顏色和字)jmp .1 .2: ;顯示完畢call DispReturn ;在下一行開頭處寫數據;Load LDT表mov ax,SelectorLDTlldt ax;跳入LDT表中局部描述符指向的任務jmp SelectorLDTCodeA:0DispReturn:push eaxpush ebxmov eax,edimov bl,160div bl ;計算出當前行號,一行占用160字節(80個字符)and eax,0ffh;上一步得到的商在eax存著,取出行數inc eax ;讓行數加1mov bl,160mul bl ;重新計算出行首的字節處mov edi,eax;上一步計算出的值在eax中,讓顯示屏定位到下一行行首pop ebxpop eaxret ;DispReturn結束------SegCode32Len equ $-LABEL_SEG_CODE32 ;END of [SECTION .s32] ;LDT[SECTION .ldt] ALIGN 32 LABEL_LDT: ;段基址 段界限 屬性 LABEL_LDT_DESC_CODEA:Descriptor 0,CodeALen-1,DA_C+DA_32 ;Code,32位代碼 LDTLen equ $-LABEL_LDT;LDT選擇子 SelectorLDTCodeA equ LABEL_LDT_DESC_CODEA - LABEL_LDT + SA_TIL ;LDT描述符指向要調用的地址, ;SA_TIL為表明描述符為LDT描述符,會將TIL位置位1,代表是LDT選擇子 ;END of [SECTION .ldt];CODEA(LDT,32位描述符) [SECTION .la] ALIGN 32 [BITS 32] LABEL_CODE_A:mov ax, SelectorVideomov gs, ax ;視頻段選擇子,指向顯示屏,輸出信息mov edi,(80*12+0)*2 ;屏幕第12行,第0列輸出信息mov ah,0ch ;0是黑底,c是紅色字mov al,'L' ;顯示屏上輸出Lmov [gs:edi],ax ;顯示屏上輸出;LDT表指示的任務完成后,跳回實模式jmp SelectorCode16:0 CodeALen equ $-LABEL_CODE_A ;END of [SECTION .la][SECTION .s16code] ALIGN 32 [BITS 16] LABEL_SEG_CODE16: ;跳回實模式mov ax,SelectorNormal ;回到正常16位模式段mov ds,axmov es,axmov fs,axmov ss,axmov eax,cr0mov al,11111110bmov cr0,eaxLABEL_GO_BACK_TO_REAL:jmp 0:LABEL_REAL_ENTRY ;段地址在前面會重新被置為正確的值 Code16Len equ $-LABEL_SEG_CODE16 ;END of [SECTION .s16code]3.構建MakeFileLDT文件,用來構建項目
################################################## # Makefile of pmtestx.asm (x=[1,2,3...]) ##################################################SRC:=pmldt.asm BIN:=$(subst .asm,.com,$(SRC)) #${SRC}中的.asm會替換成.com #此句等價于pmprotect2real.com.PHONY : everythingeverything : $(BIN)sudo mount -o loop pm.img /mnt/floppy/sudo cp $(BIN) /mnt/floppy/ -fvsudo umount /mnt/floppy/$(BIN) : $(SRC)nasm $< -o $@ #等價與nasm pmldt.asm -o pmldt.com4.運行結果如下,圖上顯示的L正是LDT表中的地址描述符指向的任務顯示出來的.
?
源碼:https://github.com/Foolegend/aos/tree/master/chapter03/LDT
總結
以上是生活随笔為你收集整理的卓一笔记---局部描述符表(LDT寻址表)的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于几种常用的脱壳方法总结
- 下一篇: web工程无法访问本地图片解决方案