保护模式下的冒泡排序
1 ;16位代码 2 [bits 16] 3 ;初始化实模式下的数据段,代码段,堆栈段 4 mov eax, cs 5 mov ss, eax 6 mov sp, 0x7C00 ;实模式下的栈在引导扇区的下边 7 ;将保护模式下的线性地址转换为实模式下的段地址:偏移地址的形式 8 xor edx, edx ;此处使用64位除法, 高32位清零 9 mov eax, [cs:gdt_base + 0x7C00] ;使用超越段前缀访问数据 10 mov ebx,16 ;线性地址 = 段地址 X 16 + 偏移地址 11 div ebx 12 ;设置指向描述符的数据段 13 mov ebx, edx ;余数为偏移地址 14 mov ds, eax 15 ;安装数据段描述符 16 ;#0空描述符 17 mov dword [ebx + 0x00], 0x0000_0000 18 mov dword [ebx + 0x04], 0x0000_0000 19 ;#1代码段 20 mov dword [ebx + 0x08], 0x7C00_01FF 21 mov dword [ebx + 0x0C], 0x0040_9800 22 ;#2数据段 23 mov dword [ebx + 0x10], 0x0000_FFFF 24 mov dword [ebx + 0x14], 0x00CF_9200 25 ;#3别名代码段 26 mov dword [ebx + 0x18], 0x7C00_01FF 27 mov dword [ebx + 0x1C], 0x0040_9200 28 ;#4堆栈段 29 mov dword [ebx + 0x20], 0x0000_6BFF 30 mov dword [ebx + 0x24], 0x0040_9600 31 ;加载GDT 32 mov word [cs:gdt_size + 0x7C00], 0x27 33 lgdt [cs:gdt_size + 0x7C00] 34 ;打开A20 35 in al, 0x92 36 or al, 0000_0010B 37 out 0x92, al 38 ;关中断 39 cli 40 ;进入保护模式(16位) 41 mov eax, cr0 42 or eax, 0000_0001B 43 mov cr0, eax 44 ;进入保护模式(32位) 45 jmp dword 0x08:flush 46 ;32位代码 47 [bits 32] 48 flush: 49 ;加载别名代码段 50 mov eax, 0x18 51 mov ds, eax 52 53 ;加载数据段 54 mov eax, 0x10 55 mov es, eax 56 57 ;加载堆栈 58 mov eax, 0x20 59 mov ss, eax 60 mov esp, 0x0000_7BFF 61 62 ;在屏幕上启动信息字符 63 mov ecx, gdt_size - welcome 64 xor ebx, ebx 65 wel: 66 mov al, [ebx + welcome] 67 mov ah, 0x0A 68 mov [es:0x000B_8000 + ebx * 2], ax 69 inc ebx 70 loop wel 71 ;冒泡排序 72 mov ecx, welcome - string - 1 73 external: 74 xor ebx, ebx 75 push ecx 76 internal: 77 mov ax, [ebx + string] 78 cmp ah, al 79 jg con 80 xchg ah, al 81 mov word [ebx + string], ax 82 con: 83 inc ebx 84 loop internal 85 pop ecx 86 loop external 87 ;显示排序的结果 88 mov ecx, welcome - string 89 xor ebx, ebx 90 res: 91 mov al, [ebx + string] 92 mov ah, 0x0A 93 mov [es:0x000B_8000 + 160 + ebx * 2], ax 94 inc ebx 95 loop res 96 ;停机 97 hlt 98 ;要进行排序的串 99 string: db '958458456541186545552135789642589103598416552556' 100 welcome: db 'Welcome to Lixiaomao boot.' 101 ;GDT位置和界限 102 gdt_size: dw 0 ;这个字用于存放GDT的界限 103 gdt_base: dd 0x0000_7E00 ;打算将GDT放在引导扇区的后边 104 ;填充剩余扇区 105 times 510 - ($ - $$) db 0 106 db 0x55, 0xAA