x86彙編--保護模式下的氣泡排序
阿新 • • 發佈:2019-01-22
其實這個程式碼本身(氣泡排序)沒有什麼意思,而有用的是怎麼從真實模式下進入保護模式,以及怎麼 使用段選擇子和段描述符。
;保護模式下的冒泡測試 ;設定堆疊 mov eax , cs mov ss , eax mov esp , 0x7c00 ;設定下es為0x7c00 mov eax , 0x7c00 mov es , eax ;設定ds為段描述符表起始地址 mov eax , [es:program_gdt+0x2] xor edx , edx mov ebx , 16 div ebx mov ds , eax mov ebx , edx ;設定全域性描述符表 ;0號插槽 mov dword[ebx+0x00],0x00 mov dword[ebx+0x04],0x00 ;1號描述符:程式碼段 mov dword[ebx+0x08],0x7c0001ff ;主引導扇區起始地址:0x7c00;段界限長度為:512位元組(段界限=長度-1) mov dword[ebx+0x0c],0x00409800 ;G=0 D=1:該段內指令偏移地址和運算元為32位(用eip);p=1:一般虛擬記憶體中使用; ;DPL=00 最高特權:表示該程式碼段可以訪問任何許可權段內的資料; ;s=1:表示程式碼段/資料段(堆疊段也是資料段)(若為0,則表示系統段) ;x=1:表示該段只執行,不可讀和寫(程式碼段要能執行的,但預設是一定不能寫入的) ;【x:執行c特權程式碼間呼叫r讀a已訪問位】 ;2號描述符;程式碼段的別名 mov dword[ebx+0x10],0x7c0001ff mov dword[ebx+0x14],0x00409a00 ;因為程式碼段預設是要能執行的,上面的程式碼段是不能讀取的,這裡設定個可以讀取的程式碼段別名 ;3號描述符:資料段;因為程式碼段不能寫入,所以用資料段來寫入資料 mov dword[ebx+0x18],0x0000ffff ;資料段起始地址:0x0000;段界限長度為4G:fffff+1 = 100000 = 2^20=1MB, ;因為G=0,則(2^20)*(4kb)=4G mov dword[ebx+0x1c],0x00cf9200 ;G=0,4kb為偏移量單位;w=1:表示該資料段能寫 ;(資料段不能執行,預設是可以讀的)【xewa】 ;4號描述符:堆疊段 mov dword[ebx+0x20],0x00007a00 ;ss=0x00000 esp=0x7a00 mov dword[ebx+0x24],0x00409600 ;ew=11:表示向下擴充套件,可寫 ;5號描述符:視訊記憶體段 mov dword[ebx+0x28],0x8000ffff ;視訊記憶體起始地址:0xb8000;0xb8000~0xbffff mov dword[ebx+0x2c],0x0040920b mov eax , (6*8-1) mov [es:program_gdt],eax lgdt [es:program_gdt] ;開啟快速A20 mov dx , 0x92 in al , dx or al , 0x2 out dx , al ;設定進入保護模式 cli mov eax , cr0 or eax , 0x1 mov cr0 , eax ;清除流水線,進入保護模式 jmp dword 0x0008:flush [bits 32] flush: ;設定堆疊 mov eax , 0x0020 mov ss , eax mov esp , 0x7c00 ;段暫存器檢查規則:ss:可讀可寫;cs:可執行;其他的段暫存器一定要可讀(否則檢查不通過); ;程式碼段不能讀取,所以用程式碼段的別名段讀取要排序對的資料 mov eax , 0x0010 ;可讀的程式碼段(即:可以用作程式碼段也可以用作其他段暫存器) mov fs , eax ;用視訊記憶體段來顯示資料 mov eax , 0x0028 mov es , eax ;開始顯示未排序的array mov esi , array mov edi , 0x00 mov ecx , (separate - array) call print_string ;列印下分割線 mov esi , separate mov ecx , (program_gdt - separate) call print_string ;開始氣泡排序 mov eax , 0x0018 mov ds , eax mov ebx , array mov ecx , (separate - array -1) call Bubble_sort ;列印排序號的array mov esi , array mov ecx , (separate - array) call print_string halt: hlt ;=============Bubble sort==================== ;輸入引數:ds:ebx ecx Bubble_sort: push esi @1: xor esi , esi push ecx @2: mov ax , [0x7c00 + ebx+esi] cmp al , ah jg @3 xchg al , ah mov [0x7c00 + ebx+esi],ax @3: inc esi loop @2 pop ecx loop @1 pop esi ret ;Bubble_sort end ;============print_string===================== ;輸入引數 fs:esi es:edi ecx ;輸出 esi指向字元末尾,edi 指向下個要顯示的地址 print_string: push ecx push fs push es show_array: mov al , [fs:esi] mov [es:edi] , al add edi , 2 inc esi loop show_array pop es pop fs pop ecx ret ;print_string ;=============data===================== array db '9102837564pzlaoskdmrnebq' separate db ' ==== ' program_gdt dw 0x00 dd 0x00007e00 times 510-($-$$) db 0x00 dw 0xaa55
結果如下圖: