pmtest3源码解析:使用LDT

来源:互联网 发布:淘宝网老年棉拖鞋 编辑:程序博客网 时间:2024/06/14 15:44
摘要:在本节中,我们将添加一个LDT段,在段中打印一个字符L,从而学习如何利用程序的LDT段。程序的执行流程随之也会发生变化,我们将分析代码和分析代码结构。


一、概要分析:

在pmtest2的基础上,我们增加一个段LDT和一个LDT中的一个段codeA。需要注意的是,LDT存在的前提是GDT,因为LDT本身是一个段中,需要由GDT中的信息,得到基地址。另外,这个场景,给出了段选择子,我们如何去索引描述符呢?思考以后,我们知道,我们需要判断但选择子属于GDT还是LDT中的段——这个需要通过选择子的第二位来判断。


我们来理一下程序的执行流程:
初始在实模式下,初始化GDT段描述符,做好进入保护模式的准备工作,经过一个长跳转,进入
保护模式32b代码段,加载相关段选择子,打印相关字符串信息,加载ldtr,进入局部任务codeA段
局部任务段codeA:打印字符,跳转到GDT中的code16段;
code16段:初始化相关寄存器,然后重新跳回实模式(通过jmp0)


二、代码解惑

注意,selector部分是不暂用GDT的存储空间的,所以计算GDT的时候,不包括selector部分。另外,汇编与一些高级语言相比,之所以在程序上难以理解,主要是因为它的结构化不是很强,也没有什么模块的概念,完全是计算的最底层,通过顺序,判断,跳转三条基本的指令来完成相应的功能。这就导致,程序之间的耦合性比较大,调用函数输入和输出不是很明显,所以会比较困难。另外,有很多处理器架构和汇编本身的语法问题,也给理解带来了额外的困难。为了理解代码,我们需要有如下的意识:


1)一个段往往是为了完成特定的功能(存储数据或者执行代码):比如说,初始的实模式下的段,就是为了进入保护模式,那么就需要设置GDT、CR0、关中断、打开A20、跳转等。进入保护模式下32b的代码段之后,需要打印字符串信息和跳转到LDT中的段,所以需要设置相应的段寄存器....等等,只有从宏观上理解了程序的执行流程,才能写出代码。代码段是逻辑的主体,数据段主要完成数据结构的定义等。
2)另外,要注意的是,很多东西都是通过寄存器的设置来实现的:访问GDT之前要设置GDTR,同理有ss、ds、cs、sp、ldtr等。
[plain] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. 代码如下:  
  2. ; ==========================================  
  3. ; pmtest3.asm  
  4. ; 编译方法:nasm pmtest3.asm -o pmtest3.com  
  5. ; ==========================================  
  6.   
  7.   
  8. %include    "pm.inc"    ; 常量, 宏, 以及一些说明  
  9.   
  10.   
  11. org 0100h  
  12.     jmp LABEL_BEGIN  
  13.   
  14.   
  15. [SECTION .gdt]  
  16. ; GDT  
  17. ;                                         段基址,       段界限     , 属性  
  18. LABEL_GDT:      Descriptor         0,                 0, 0          ; 空描述符  
  19. LABEL_DESC_NORMAL:  Descriptor         0,            0ffffh, DA_DRW     ; Normal 描述符  
  20. LABEL_DESC_CODE32:  Descriptor         0,  SegCode32Len - 1, DA_C + DA_32   ; 非一致代码段, 32  
  21. LABEL_DESC_CODE16:  Descriptor         0,            0ffffh, DA_C       ; 非一致代码段, 16  
  22. LABEL_DESC_DATA:    Descriptor         0,   DataLen - 1, DA_DRW     ; Data  
  23. LABEL_DESC_STACK:   Descriptor         0,        TopOfStack, DA_DRWA + DA_32    ; Stack, 32 位  
  24. LABEL_DESC_LDT:     Descriptor         0,        LDTLen - 1, DA_LDT     ; LDT  
  25. LABEL_DESC_VIDEO:   Descriptor   0B8000h,            0ffffh, DA_DRW     ; 显存首地址  
  26. ; GDT 结束  
  27.   
  28.   
  29. GdtLen      equ $ - LABEL_GDT   ; GDT长度  
  30. GdtPtr      dw  GdtLen - 1  ; GDT界限  
  31.         dd  0       ; GDT基地址  
  32.   
  33.   
  34. ; GDT 选择子  
  35. SelectorNormal      equ LABEL_DESC_NORMAL   - LABEL_GDT  
  36. SelectorCode32      equ LABEL_DESC_CODE32   - LABEL_GDT  
  37. SelectorCode16      equ LABEL_DESC_CODE16   - LABEL_GDT  
  38. SelectorData        equ LABEL_DESC_DATA     - LABEL_GDT  
  39. SelectorStack       equ LABEL_DESC_STACK    - LABEL_GDT  
  40. SelectorLDT     equ LABEL_DESC_LDT      - LABEL_GDT  
  41. SelectorVideo       equ LABEL_DESC_VIDEO    - LABEL_GDT  
  42. ; END of [SECTION .gdt]  
  43.   
  44.   
  45. [SECTION .data1]     ; 数据段  
  46. ALIGN   32  
  47. [BITS   32]  
  48. LABEL_DATA:  
  49. SPValueInRealMode   dw  0  
  50. ; 字符串  
  51. PMMessage:      db  "In Protect Mode now. ^-^", 0   ; 进入保护模式后显示此字符串  
  52. OffsetPMMessage     equ PMMessage - $$  
  53. StrTest:        db  "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0  
  54. OffsetStrTest       equ StrTest - $$  
  55. DataLen         equ $ - LABEL_DATA  
  56. ; END of [SECTION .data1]  
  57.   
  58.   
  59.   
  60.   
  61. ; 全局堆栈段  
  62. [SECTION .gs]  
  63. ALIGN   32  
  64. [BITS   32]  
  65. LABEL_STACK:  
  66.     times 512 db 0  
  67.   
  68.   
  69. TopOfStack  equ $ - LABEL_STACK - 1  
  70.   
  71.   
  72. ; END of [SECTION .gs]  
  73.   
  74.   
  75.   
  76.   
  77. [SECTION .s16]  
  78. [BITS   16]  
  79. LABEL_BEGIN:  
  80.     mov ax, cs  
  81.     mov ds, ax  
  82.     mov es, ax  
  83.     mov ss, ax  
  84.     mov sp, 0100h  
  85.   
  86.   
  87.     mov [LABEL_GO_BACK_TO_REAL+3], ax  
  88.     mov [SPValueInRealMode], sp  
  89.   
  90.   
  91.     ; 初始化 16 位代码段描述符  
  92.     mov ax, cs  
  93.     movzx   eax, ax  
  94.     shl eax, 4  
  95.     add eax, LABEL_SEG_CODE16  
  96.     mov word [LABEL_DESC_CODE16 + 2], ax  
  97.     shr eax, 16  
  98.     mov byte [LABEL_DESC_CODE16 + 4], al  
  99.     mov byte [LABEL_DESC_CODE16 + 7], ah  
  100.   
  101.   
  102.     ; 初始化 32 位代码段描述符  
  103.     xor eax, eax  
  104.     mov ax, cs  
  105.     shl eax, 4  
  106.     add eax, LABEL_SEG_CODE32  
  107.     mov word [LABEL_DESC_CODE32 + 2], ax  
  108.     shr eax, 16  
  109.     mov byte [LABEL_DESC_CODE32 + 4], al  
  110.     mov byte [LABEL_DESC_CODE32 + 7], ah  
  111.   
  112.   
  113.     ; 初始化数据段描述符  
  114.     xor eax, eax  
  115.     mov ax, ds  
  116.     shl eax, 4  
  117.     add eax, LABEL_DATA  
  118.     mov word [LABEL_DESC_DATA + 2], ax  
  119.     shr eax, 16  
  120.     mov byte [LABEL_DESC_DATA + 4], al  
  121.     mov byte [LABEL_DESC_DATA + 7], ah  
  122.   
  123.   
  124.     ; 初始化堆栈段描述符  
  125.     xor eax, eax  
  126.     mov ax, ds  
  127.     shl eax, 4  
  128.     add eax, LABEL_STACK  
  129.     mov word [LABEL_DESC_STACK + 2], ax  
  130.     shr eax, 16  
  131.     mov byte [LABEL_DESC_STACK + 4], al  
  132.     mov byte [LABEL_DESC_STACK + 7], ah  
  133.   
  134.   
  135.     ; 初始化 LDT 在 GDT 中的描述符  
  136.     xor eax, eax  
  137.     mov ax, ds  
  138.     shl eax, 4  
  139.     add eax, LABEL_LDT  
  140.     mov word [LABEL_DESC_LDT + 2], ax  
  141.     shr eax, 16  
  142.     mov byte [LABEL_DESC_LDT + 4], al  
  143.     mov byte [LABEL_DESC_LDT + 7], ah  
  144.   
  145.   
  146.     ; 初始化 LDT 中的描述符  
  147.     xor eax, eax  
  148.     mov ax, ds  
  149.     shl eax, 4  
  150.     add eax, LABEL_CODE_A  
  151.     mov word [LABEL_LDT_DESC_CODEA + 2], ax  
  152.     shr eax, 16  
  153.     mov byte [LABEL_LDT_DESC_CODEA + 4], al  
  154.     mov byte [LABEL_LDT_DESC_CODEA + 7], ah  
  155.   
  156.   
  157.     ; 为加载 GDTR 作准备  
  158.     xor eax, eax  
  159.     mov ax, ds  
  160.     shl eax, 4  
  161.     add eax, LABEL_GDT      ; eax <- gdt 基地址  
  162.     mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址  
  163.   
  164.   
  165.     ; 加载 GDTR  
  166.     lgdt    [GdtPtr]  
  167.   
  168.   
  169.     ; 关中断  
  170.     cli  
  171.   
  172.   
  173.     ; 打开地址线A20  
  174.     in  al, 92h  
  175.     or  al, 00000010b  
  176.     out 92h, al  
  177.   
  178.   
  179.     ; 准备切换到保护模式  
  180.     mov eax, cr0  
  181.     or  eax, 1  
  182.     mov cr0, eax  
  183.   
  184.   
  185.     ; 真正进入保护模式  
  186.     jmp dword SelectorCode32:0  ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0  处  
  187.   
  188.   
  189. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
  190.   
  191.   
  192. LABEL_REAL_ENTRY:       ; 从保护模式跳回到实模式就到了这里  
  193.     mov ax, cs  
  194.     mov ds, ax  
  195.     mov es, ax  
  196.     mov ss, ax  
  197.   
  198.   
  199.     mov sp, [SPValueInRealMode]  
  200.   
  201.   
  202.     in  al, 92h     ; ┓  
  203.     and al, 11111101b   ; ┣ 关闭 A20 地址线  
  204.     out 92h, al     ; ┛  
  205.   
  206.   
  207.     sti         ; 开中断  
  208.   
  209.   
  210.     mov ax, 4c00h   ; ┓  
  211.     int 21h     ; ┛回到 DOS  
  212. ; END of [SECTION .s16]  
  213.   
  214.   
  215.   
  216.   
  217. [SECTION .s32]; 32 位代码段. 由实模式跳入.  
  218. [BITS   32]  
  219.   
  220.   
  221. LABEL_SEG_CODE32:  
  222.     mov ax, SelectorData  
  223.     mov ds, ax          ; 数据段选择子  
  224.     mov ax, SelectorVideo  
  225.     mov gs, ax          ; 视频段选择子  
  226.   
  227.   
  228.     mov ax, SelectorStack  
  229.     mov ss, ax          ; 堆栈段选择子  
  230.   
  231.   
  232.     mov esp, TopOfStack  
  233.   
  234.   
  235.   
  236.   
  237.     ; 下面显示一个字符串  
  238.     mov ah, 0Ch         ; 0000: 黑底    1100: 红字  
  239.     xor esi, esi  
  240.     xor edi, edi  
  241.     mov esi, OffsetPMMessage    ; 源数据偏移  
  242.     mov edi, (80 * 10 + 0) * 2  ; 目的数据偏移。屏幕第 10 行, 第 0 列。  
  243.     cld  
  244. .1:  
  245.     lodsb  
  246.     test    al, al  
  247.     jz  .2  
  248.     mov [gs:edi], ax  
  249.     add edi, 2  
  250.     jmp .1  
  251. .2: ; 显示完毕  
  252.   
  253.   
  254.     call    DispReturn  
  255.   
  256.   
  257.     ; Load LDT  
  258.     mov ax, SelectorLDT  
  259.     lldt    ax  
  260.   
  261.   
  262.     jmp SelectorLDTCodeA:0  ; 跳入局部任务  
  263.   
  264.   
  265. ; ------------------------------------------------------------------------  
  266. DispReturn:  
  267.     push    eax  
  268.     push    ebx  
  269.     mov eax, edi  
  270.     mov bl, 160  
  271.     div bl  
  272.     and eax, 0FFh  
  273.     inc eax  
  274.     mov bl, 160  
  275.     mul bl  
  276.     mov edi, eax  
  277.     pop ebx  
  278.     pop eax  
  279.   
  280.   
  281.     ret  
  282. ; DispReturn 结束---------------------------------------------------------  
  283.   
  284.   
  285. SegCode32Len    equ $ - LABEL_SEG_CODE32  
  286. ; END of [SECTION .s32]  
  287.   
  288.   
  289.   
  290.   
  291. ; 16 位代码段. 由 32 位代码段跳入, 跳出后到实模式  
  292. [SECTION .s16code]  
  293. ALIGN   32  
  294. [BITS   16]  
  295. LABEL_SEG_CODE16:  
  296.     ; 跳回实模式:  
  297.     mov ax, SelectorNormal  
  298.     mov ds, ax  
  299.     mov es, ax  
  300.     mov fs, ax  
  301.     mov gs, ax  
  302.     mov ss, ax  
  303.   
  304.   
  305.     mov eax, cr0  
  306.     and al, 11111110b  
  307.     mov cr0, eax  
  308.   
  309.   
  310. LABEL_GO_BACK_TO_REAL:  
  311.     jmp 0:LABEL_REAL_ENTRY  ; 段地址会在程序开始处被设置成正确的值  
  312.   
  313.   
  314. Code16Len   equ $ - LABEL_SEG_CODE16  
  315.   
  316.   
  317. ; END of [SECTION .s16code]  
  318.   
  319.   
  320.   
  321.   
  322. ; LDT  
  323. [SECTION .ldt]  
  324. ALIGN   32  
  325. LABEL_LDT:  
  326. ;                                         段基址       段界限     ,   属性  
  327. LABEL_LDT_DESC_CODEA:   Descriptor         0,     CodeALen - 1,   DA_C + DA_32  ; Code, 32 位  
  328.   
  329.   
  330. LDTLen      equ $ - LABEL_LDT  
  331.   
  332.   
  333. ; LDT 选择子  
  334. SelectorLDTCodeA    equ LABEL_LDT_DESC_CODEA    - LABEL_LDT + SA_TIL  
  335. ; END of [SECTION .ldt]  
  336.   
  337.   
  338.   
  339.   
  340. ; CodeA (LDT, 32 位代码段)  
  341. [SECTION .la]  
  342. ALIGN   32  
  343. [BITS   32]  
  344. LABEL_CODE_A:  
  345.     mov ax, SelectorVideo  
  346.     mov gs, ax          ; 视频段选择子(目的)  
  347.   
  348.   
  349.     mov edi, (80 * 12 + 0) * 2  ; 屏幕第 10 行, 第 0 列。  
  350.     mov ah, 0Ch         ; 0000: 黑底    1100: 红字  
  351.     mov al, 'L'  
  352.     mov [gs:edi], ax  
  353.   
  354.   
  355.     ; 准备经由16位代码段跳回实模式  
  356.     jmp SelectorCode16:0  
  357. CodeALen    equ $ - LABEL_CODE_A  
  358. ; END of [SECTION .la] 
0 0
原创粉丝点击