youngray 标签:
程序代码如下
1: %include "pm.inc"
2:3: org 0100h4: jmp LABEL_BEGIN5:6: [section .gdt]7: GDT_BEGIN: ;空描述符,Intel规定必须要有该描述符8: Descriptor 0, 0, 09: GDT_NORMAL: ;Normal描述符,从保护模式返回实模式时,用到该描述符10: Descriptor 0, 0ffffh, DA_DRW11: GDT_CODE16: ;该描述符指向保护模式下的16位代码段12: Descriptor 0, 0ffffh, DA_C13: GDT_CODE32: ;该描述符指向保护模式下的32位代码段14: Descriptor 0, SegCode32Len - 1, DA_C + DA_3215: GDT_DATA: ;该描述指向保护模式下要用到的数据段16: Descriptor 0, SegDataLen - 1, DA_DRW17: GDT_STACK: ;该描述符指向保护模式下要用到的堆栈段18: Descriptor 0, TopOfStack, DA_DRWA + DA_3219: GDT_TEST: ;该描述符指向测试字符串的物理地址20: Descriptor 0500000h, 0ffffh, DA_DRW21: GDT_VIDEO: ;该描述符指向显存首地址22: Descriptor 0b8000h, 0ffffh, DA_DRW23:24: Gdt_Len equ $ - GDT_BEGIN25: GdtPtr dw Gdt_Len - 126: dd 0 ;这里的0起到保留内存空间的作用,不做为实际值27:28: ; 定义 GDT 选择子29: SelectorNormal equ GDT_NORMAL - GDT_BEGIN30: SelectorCode16 equ GDT_CODE16 - GDT_BEGIN31: SelectorCode32 equ GDT_CODE32 - GDT_BEGIN32: SelectorData equ GDT_DATA - GDT_BEGIN33: SelectorStack equ GDT_STACK - GDT_BEGIN34: SelectorTest equ GDT_TEST - GDT_BEGIN35: SelectorVideo equ GDT_VIDEO - GDT_BEGIN36:37: [section .data1] ;保护模式下要用到的数据段38: align 3239: [bits 32]40: LABEL_DATA:41: SPValueInReal dw 0 ;该变量保存实模式下sp指针的值42: PMMessage db "In Protect Mode now. ^-^", 0 ;在保护模式中显示
43: PMMessageOffset equ PMMessage - $$44: TestStr db "ABCDEFGH", 0 ;测试字符串
45: TestStrOffset equ TestStr - $$46: SegDataLen equ $ - LABEL_DATA47:48: [section .gs] ;保护模式下要用到的全局堆栈段49: align 3250: [bits 32]51: LABEL_STACK:52: times 512 db 053: TopOfStack equ $ - LABEL_STACK - 154:55: [section .s16]56: [bits 16]57: LABEL_BEGIN: ;程序从这里开始执行58: mov ax, cs59: mov ds, ax60: mov es, ax61: mov ss, ax62: mov sp, 0100h63:64: ;保存实模式下cs段寄存器的值到LABEL_GO_BACK_TO_REAL + 3所指向的地址处65: mov [LABEL_GO_BACK_TO_REAL+3], ax66: mov [SPValueInReal], sp ;保存实模式下sp指针的值到SPValueInReal变量67:68: ;初始化16位代码段描述符GDT_CODE16的基址值69: xor eax, eax70: mov ax , cs ;将cs段寄存器的值传送到ax71: shl eax, 4 ;将ax中段地址左移位72: add ax , LABEL_CODE16 ;将LABEL_CODE16的偏移地址加到ax,得到它的物理地址73: mov [GDT_CODE16 + 2], ax ;将该物理地址分三部分分别放入描述符GDT_CODE1674: shr eax, 16 ;中,具体的放置位置已经由Intel规定好了,你只须75: mov [GDT_CODE16 + 4], al ;按照GDT描述符的规定把相应位置的值放进去即可76: mov [GDT_CODE16 + 7], ah ;此时,GDT_CODE16的基址值初始化完毕77:78: ;初始化32位代码段描述符GDT_CODE32的基址值79: xor eax, eax80: mov ax , cs81: shl eax, 482: add ax, LABEL_CODE3283: mov [GDT_CODE32 + 2], ax84: shr eax, 1685: mov [GDT_CODE32 + 4], al86: mov [GDT_CODE32 + 7], ah87:88: ;初始化数据段描述符GDT_DATA的基址值89: xor eax, eax90: mov ax , ds ;ds的值在上面的代码被置为cs的值91: shl eax, 492: add eax, LABEL_DATA93: mov [GDT_DATA + 2], ax94: shr eax, 1695: mov [GDT_DATA + 4], al96: mov [GDT_DATA + 7], ah97:98: ;初始化堆栈段描述符GDT_STACK的基址值99: xor eax, eax100: mov ax , ds101: shl eax, 4102: add eax, LABEL_STACK103: mov [GDT_STACK + 2], ax104: shr eax, 16105: mov [GDT_STACK + 4], al106: mov [GDT_STACK + 7], ah107:108: ;为加载 GDTR 作准备109: xor eax, eax110: mov ax , ds111: shl eax, 4112: add eax, GDT_BEGIN113: mov [GdtPtr + 2], eax114:115: ;加载 GDTR116: lgdt [GdtPtr]117:118: ;关中断119: cli120: ;打开A20地址线121: in al, 92h122: or al, 00000010b123: out 92h, al124: ;打开进入保护模式的开关,该开关位于cr0寄存器的第0位125: mov eax, cr0126: or eax, 1127: mov cr0, eax128:129: ;真正进入保护模式130: jmp dword SelectorCode32:0 ;为了防止发生地址截断,这里的dword必不可少131:132: LABEL_REAL_ENTRY: ;从保护模式跳回实模式就到了这里133: mov ax, cs134: mov ds, ax135: mov es, ax136: mov ss, ax137: mov sp, [SPValueInReal]138:139: ;关闭A20地址线140: in al, 92h141: and al, 11111101b142: out 92h, al143: ;开中断144: sti145:146: ;返回 DOS147: mov ax, 4c00h148: int 21h
1: #include <stdio.h>2: int main()
3: {4: printf("NOT helloWorld~/n");5: return 0
6: }
1: #include <stdio.h>
2: int main()
3: {
4: printf("NOT helloWorld~/n");
5: return 0
6: }
1: #include <stdio.h>2: int main()
3: {4: printf("NOT helloWorld~/n");5: return 0
6: }
转载请注明出处:http://blog.youkuaiyun.com/whyiug1/archive/2011/03/07/6229496.aspx