天天看點

彙編執行個體解析--分頁機制,多任務,基于中斷的任務切換1.引導程式2.核心任務3.使用者任務4.使用者任務2

1.引導程式

core_base_address equ 0x00040000    
         core_start_sector equ 0x00000001   
SECTION  mbr  vstart=0x00007c00  
         ; 此刻cs内容是0x0000       
         mov ax,cs      
         mov ss,ax
         ; 設定sp
         mov sp,0x7c00
         ; gdt基位址
         mov eax,[cs:pgdt+0x02]           
         xor edx,edx
         mov ebx,16
         div ebx                           

         mov ds,eax                        
         mov ebx,edx                       
         ; 段基位址31~24 G D/B L AVL 段界限19~16 P DPL S TYPE 段基位址23~16 
         ; 段基位址15~0 段界限15~0
         ; 0x00 cf 98 00
         ; 0x00 00 ff ff
         ; 段基位址:0x0000 0000
         ; 段界限:f ffff
         ; 段屬性:4kb計量 32位 段在記憶體 0特權級 非系統段 代碼段
         mov dword [ebx+0x08],0x0000ffff    
         mov dword [ebx+0x0c],0x00cf9800    
         ; 段基位址:0x0000 0000
         ; 段界限:f ffff
         ; 段屬性:4kb計量 32位 段在記憶體 0特權級 非系統段 可讀可寫資料段
         mov dword [ebx+0x10],0x0000ffff    
         mov dword [ebx+0x14],0x00cf9200    

         mov word [cs: pgdt],23     
         ; 通知處理器gdt界限,基位址      
         lgdt [cs: pgdt]
         
         ; 開啟a20位址線
         in al,0x92                         
         or al,0000_0010B
         out 0x92,al    

         ; 禁止中斷                   
         cli                                
         
         ; 進入保護模式
         mov eax,cr0                  
         or eax,1
         mov cr0,eax   

         ; 執行指令跳轉                     
         jmp dword 0x0008:flush            
         [bits 32]               
  flush:   
         ; 統一采用全局資料段                               
         mov eax,0x00010                   
         mov ds,eax
         mov es,eax
         mov fs,eax
         mov gs,eax
         mov ss,eax    
         ; 設定esp                     
         mov esp,0x7000
         ; 核心基礎位址                    
         mov edi,core_base_address
         
         ; 核心任務邏輯扇區
         mov eax,core_start_sector
         ; 核心基礎位址
         mov ebx,edi   
         ; 讀取磁盤扇區到實體記憶體                     
         call read_hard_disk_0   
         ; 讀取核心任務頭4位元組           
         mov eax,[edi]                    
         xor edx,edx
         mov ecx,512                      
         div ecx

         or edx,edx
         jnz @1                             
         dec eax                           
   @1:
         or eax,eax                        
         jz pge                            
         mov ecx,eax                       
         mov eax,core_start_sector
         inc eax                           
   @2:
         call read_hard_disk_0
         inc eax
         loop @2                           
         
         ; 到這裡已經把核心任務完整的讀取到了實體記憶體
   pge:
         ; 這是用作頁目錄表的起始位置
         mov ebx,0x00020000          
         ; 設定頁目錄表最後一項指向頁目錄表自己      
         mov dword [ebx+4092],0x00020003 
         ; 這個是頁表的起始位置
         mov edx,0x00021003   
         ; 設定頁目錄表索引0項和索引512項指向頁表             
         mov [ebx+0x000],edx               
         mov [ebx+0x800],edx   

         ; 設定頁表前256項
         ; 這樣設定後,虛拟空間前1mb内的線性位址的實體位址就是線性位址自身      
         mov ebx,0x00021000                
         xor eax,eax                      
         xor esi,esi
  .b1:       
         mov edx,eax
         or edx,0x00000003                                                      
         mov [ebx+esi*4],edx               
         add eax,0x1000                    
         inc esi
         cmp esi,256                        
         jl .b1
         
         ; 通知處理器頁目錄表位置
         mov eax,0x00020000               
         mov cr3,eax

         ; 從處理器擷取gdt界限,基位址資訊
         sgdt [pgdt]
         mov ebx,[pgdt+2]
         add dword [pgdt+2],0x80000000   
         ; 通知處理器gdt界限,基位址資訊[線性位址改成虛拟位址高區間的] 
         lgdt [pgdt]
         
         ; 開啟分頁機制
         mov eax,cr0
         or eax,0x80000000
         mov cr0,eax   

         ; 令esp指向虛拟位址高區間的                    
         add esp,0x80000000  
         ; 指令跳轉  
         ; cs指向全局代碼段,從記憶體取出4位元組段内偏移
         ; 這個段内偏移是線性位址,按頁目錄表-頁表轉換後得到的實體位址将是
         ; 核心任務過程start起始實體位置             
         jmp [0x80040004]  
       
read_hard_disk_0:                          
         push eax 
         push ecx
         push edx
         push eax
         mov dx,0x1f2
         mov al,1
         out dx,al                          

         inc dx                             
         pop eax
         out dx,al                         
         inc dx                            
         mov cl,8
         shr eax,cl
         out dx,al                         

         inc dx                            
         shr eax,cl
         out dx,al                          

         inc dx                             
         shr eax,cl
         or al,0xe0                        
         out dx,al

         inc dx                            
         mov al,0x20                       
         out dx,al

  .waits:
         in al,dx
         and al,0x88
         cmp al,0x08
         jnz .waits                         

         mov ecx,256                       
         mov dx,0x1f0
  .readw:
         in ax,dx
         mov [ebx],ax
         add ebx,2
         loop .readw

         pop edx
         pop ecx
         pop eax
         ret

         pgdt             dw 0
                          dd 0x00008000    
         times 510-($-$$) db 0
                          db 0x55,0xaa
           

2.核心任務

flat_4gb_code_seg_sel  equ  0x0008      
         flat_4gb_data_seg_sel  equ  0x0018     
         idt_linear_address     equ  0x8001f000  
         %macro alloc_core_linear 0             
               mov ebx,[core_tcb+0x06]
               add dword [core_tcb+0x06],0x1000
               call flat_4gb_code_seg_sel:alloc_inst_a_page
         %endmacro 
         %macro alloc_user_linear 0             
               mov ebx,[esi+0x06]
               add dword [esi+0x06],0x1000
               call flat_4gb_code_seg_sel:alloc_inst_a_page
         %endmacro
         
SECTION  core  vstart=0x80040000
         core_length      dd core_end     
         core_entry       dd start        
         [bits 32]

; ds:ebx指向首個待顯示字元的線性位址
put_string:  
         push ebx
         push ecx
         cli                                

  .getc:
         mov cl,[ebx]
         or cl,cl                           
         jz .exit                         
         call put_char
         inc ebx
         jmp .getc

  .exit:
         sti                              
         pop ecx
         pop ebx
         retf                              

put_char:   
         pushad
         mov dx,0x3d4
         mov al,0x0e
         ; 向0x3d4寫入0x0e
         out dx,al
         inc dx           
         ; 從0x3d5讀取1位元組                  
         in al,dx          
         ; 讀取的是16位光标位置高8位                
         mov ah,al

         dec dx                           
         mov al,0x0f
         ; 向0x3d4寫入0x0f
         out dx,al
         inc dx           
         ; 從0x3d5讀取1位元組               
         in al,dx          
         ; bx就是16位光标位置                
         mov bx,ax                          
         and ebx,0x0000ffff                 
         
         cmp cl,0x0d                       
         jnz .put_0a                         

         ; 字元是0x0d時的處理         
         mov ax,bx                         
         mov bl,80
         div bl
         mul bl
         ; 這是将光标位置設定到行首---回車
         mov bx,ax
         jmp .set_cursor

  .put_0a:
         cmp cl,0x0a                       
         jnz .put_other
         ; 字元是0x0a時的處理,這是換行
         add bx,80                          
         jmp .roll_screen

  .put_other:  
         ; 由光标位置得到顯存位置                             
         shl bx,1
         ; 字元存入顯存
         mov [0x800b8000+ebx],cl             

         shr bx,1
         ; 更新光标位置
         inc bx

  .roll_screen:
         cmp bx,2000                       
         jl .set_cursor
         
         ; 将顯存内每一行的内容拷貝到前面一行
         ; 最後一行全部顯示空格
         ; 光标位置設定為最後一行的行首
         cld
         mov esi,0x800b80a0                  
         mov edi,0x800b8000                 
         mov ecx,1920
         rep movsd
         mov bx,3840                        
         mov ecx,80                        
  .cls:
         mov word [0x800b8000+ebx],0x0720
         add bx,2
         loop .cls

         mov bx,1920

  .set_cursor:
         mov dx,0x3d4
         mov al,0x0e
         out dx,al
         inc dx                            
         mov al,bh
         out dx,al
         dec dx                            
         mov al,0x0f
         out dx,al
         inc dx                             
         mov al,bl
         out dx,al
         popad
         ret                              

; eax:磁盤邏輯扇區
; ds:ebx:實體記憶體起始位置線性位址
read_hard_disk_0:    
         cli
         push eax 
         push ecx
         push edx
         push eax
         
         mov dx,0x1f2
         mov al,1
         ; 向0x1f2寫入1---磁盤要傳輸的扇區數
         out dx,al                          

         inc dx                             
         pop eax
         ; 向0x1f3寫入28位邏輯扇區号的最低8位
         out dx,al                         

         inc dx                            
         mov cl,8
         shr eax,cl
         ; 向0x1f4寫入28位邏輯扇區号的次低8位
         out dx,al                          

         inc dx                             
         shr eax,cl
         ; 向0x1f5寫入28位邏輯扇區号的次次低8位
         out dx,al                         

         inc dx                            
         shr eax,cl
         or al,0xe0   
         ; 向0x1f6寫入28位邏輯扇區号的高4位,同時高4位是1110                     
         out dx,al

         inc dx                             
         mov al,0x20  
         ; 向0x1f7寫入0x20---通知磁盤開始資料傳輸                      
         out dx,al

  .waits:
         ; 從0x1f7讀取1位元組
         in al,dx
         and al,0x88
         ; 如果磁盤不忙且準備就緒
         cmp al,0x08
         ; 否則,繼續等待
         jnz .waits                          

         ; 向實體記憶體寫入512位元組
         mov ecx,256                       
         mov dx,0x1f0
  .readw:
         ; 取出2位元組就緒資料
         in ax,dx
         ; 存儲到ds:ebx
         mov [ebx],ax
         add ebx,2
         loop .readw

         pop edx
         pop ecx
         pop eax
         sti
         retf                               

; edx存儲了32位數值,将此數值按16進制顯示
put_hex_dword:      
         pushad
         mov ebx,bin_hex
         mov ecx,8
  .xlt:    
         rol edx,4
         mov eax,edx
         and eax,0x0000000f
         xlat
      
         push ecx
         mov cl,al                           
         call put_char
         pop ecx
         loop .xlt
         popad
         retf

; 在gdt中安裝8位元組描述符 
set_up_gdt_descriptor:  
         push eax
         push ebx
         push edx
         ; 從處理器獲得gdt的界限,基位址(線性位址)
         sgdt [pgdt]                        

         movzx ebx,word [pgdt]   
         inc bx
         ; ebx此時是區域尾後位置                           
         add ebx,[pgdt+2]                 
         
         ; 8位元組描述符存入區域尾部
         mov [ebx],eax
         mov [ebx+4],edx
         add word [pgdt],8        
         ; 通知處理器gdt區域界限,基位址         
         lgdt [pgdt]                      
         mov ax,[pgdt]                     
         xor dx,dx
         mov bx,8
         div bx                             
         mov cx,ax
         ; 剛剛安裝描述符的選擇子
         shl cx,3                          
         
         pop edx
         pop ebx
         pop eax
         retf

; 段基位址31~24 G D/B L AVL 段界限19~16 P DPL S TYPE 段基位址23~16 
; 段基位址15~0 段界限15~0
; 傳入:eax段基位址,ebx段界限,ecx屬性資訊
; 傳出:edx:eax 8位描述符    
make_seg_descriptor:                        
         mov edx,eax
         shl eax,16
         or ax,bx                           

         and edx,0xffff0000                 
         rol edx,8
         bswap edx                          

         xor bx,bx
         or edx,ebx                         
         or edx,ecx                         
         retf

; 段内偏移31~16 P DPL 0 TYPE(1100) 000 參數個數(5位) 
; 例程所在代碼段選擇子 段内偏移15~0
; eax:32位段偏移
; ebx:16位例程所在代碼段選擇子
; cx:16位屬性位
make_gate_descriptor:                     
         push ebx
         push ecx
      
         mov edx,eax
         and edx,0xffff0000                
         or dx,cx                          
       
         and eax,0x0000ffff                 
         shl ebx,16                          
         or eax,ebx                        
         pop ecx
         pop ebx
         retf                                   

; 實體頁尋找與配置設定
; eax傳回時存儲了實體頁實體位址                            
allocate_a_4k_page:  
         push ebx
         push ecx
         push edx
         xor eax,eax
  .b1:
         ; 将線性位址指向位置指定偏移的比特位從記憶體送入寄存器,然後對應位置設定為1
         bts [page_bit_map],eax
         jnc .b2
         inc eax
         cmp eax,page_map_len*8
         jl .b1
         mov ebx,message_3
         call flat_4gb_code_seg_sel:put_string
         hlt                               
         
  .b2:
         shl eax,12                        
         pop edx
         pop ecx
         pop ebx
         ret
         
alloc_inst_a_page:  
         push eax
         push ebx
         push esi
         
         ; 保留高10位
         mov esi,ebx
         and esi,0xffc00000
         ; 成為低10位
         shr esi,20  
         ; 高20位采用0xfffff                      
         or esi,0xfffff000                 
         
         ; 線性位址ds:esi,esi高20位得到實體頁---頁目錄表自己
         ; 原始ebx的高10位構成索引
         test dword [esi],0x00000001         
         jnz .b1                           
          
         ; 表示索引對應的目錄項指向的頁表不存在
         ; 配置設定4kb實體頁
         call allocate_a_4k_page           
         or eax,0x00000007
         ; 在頁目錄表對應項設定頁表
         mov [esi],eax                     
          
  .b1:
         ; 0b [0000000000] {0000000000} '000000000000'
         mov esi,ebx
         ; 0b 0000000000 [0000000000] {0000000000} '00'
         shr esi,10
         ; 0b 0000000000 [0000000000] 0000000000 00
         and esi,0x003ff000
         ; 0b 1111111111 [0000000000] 0000000000 00
         or esi,0xffc00000                  
         
         ; 0b [0000000000] {0000000000} '000000000000'
         ; -->0b 0000000000 {0000000000} 000000000000
         and ebx,0x003ff000
         ; 0b 0000000000 0000000000 {0000000000} 00
         shr ebx,10      
         ;  0b 1111111111 [0000000000] 0000000000 00
         ;  0b 0000000000 0000000000 {0000000000} 00
         ;->0b 1111111111 [0000000000] {0000000000} 00                 
         or esi,ebx                         
         ; 搜尋并配置設定4kb實體頁
         call allocate_a_4k_page           
         or eax,0x00000007
         ; 用高10位尋找頁目錄表得到頁表(其實是頁目錄表自身)
         ; 用傳入線性位址高10位在頁表定位到實體頁(其實是頁表)
         ; 用 傳入線性位址次高10位+00 在實體頁定位偏移
         ; 通路的其實是頁表索引項--》索引号是傳入線性位址次高10位
         ; 修改索引項讓其指向傳入線性位址對應的實體頁
         mov [esi],eax 
         
         pop esi
         pop ebx
         pop eax
         retf  

; 傳回時eax是新配置設定的4kb實體頁的實體位址
; 這個實體頁拷貝了目前頁目錄表的1024項
create_copy_cur_pdir:  
         push esi
         push edi
         push ebx
         push ecx
         
         ; 配置設定4kb實體頁
         call allocate_a_4k_page            
         mov ebx,eax
         or ebx,0x00000007
         ; 這是設定頁目錄表倒數第2項指向剛剛配置設定的4kb實體頁
         mov [0xfffffff8],ebx
         
         ; 給定線性位址,通知處理器檢查此線性位址是否在tlb(快表中)
         ; 如在,更新塊表中對應的線性位址--實體位址映射
         invlpg [0xfffffff8]
         
         mov esi,0xfffff000                
         mov edi,0xffffe000                 
         mov ecx,1024   
         ; 将頁目錄表1024項,依次拷貝到新配置設定的4kb實體頁              
         cld
         ; 每次拷貝4位元組
         repe movsd 
         
         pop ecx
         pop ebx
         pop edi
         pop esi
         retf

; 通用中斷處理       
general_interrupt_handler:
         push eax
         mov al,0x20 
         ; 向0xa0寫入0x20                       
         out 0xa0,al     
         ; 向0x20寫入0x20                   
         out 0x20,al                       
         pop eax
         iretd

; 通用異常處理
general_exception_handler:
         mov ebx,excep_msg
         call flat_4gb_code_seg_sel:put_string
         hlt

; 0x70中斷處理
rtm_0x70_interrupt_handle:   
         pushad
         mov al,0x20       
         ; 向0xa0寫入0x20                
         out 0xa0,al     
         ; 向0x20寫入0x20                  
         out 0x20,al                       

         mov al,0x0c     
         ; 向0x70寫入0x0c                   
         out 0x70,al
         ; 從0x71讀取1位元組
         in al,0x71   

         mov eax,tcb_chain                  
  .b0:       
         ; 首次:取得tcb連結清單首個對象線性位址   
         ; 非首次:取得eax指向tcb對象下一個tcb對象線性位址                           
         mov ebx,[eax]                      
         or ebx,ebx
         ; 連結清單空
         jz .irtn     
         ; 判斷目前指向tcb對象狀态                      
         cmp word [ebx+0x04],0xffff
         ; 狀态忙        
         je .b1
         ; 更新eax
         mov eax,ebx                       
         jmp .b0         

  .b1:
         ; eax指向上一個tcb對象線性位址(初始指向tcb_chain)
         ; ebx指向目前tcb對象,它的狀态為忙
         ; 取得下一個tcb對象線性位址
         mov ecx,[ebx]      
         ; 完成忙對象從連結清單删除                
         ; 設定上一tcb對象下一個tcb對象為下下tcb對象
         mov [eax],ecx                     

  .b2:  
         ; 取得下一tcb對象                                    
         mov edx,[eax]
         or edx,edx       
         ; 下一tcb對象不存在                  
         jz .b3
         mov eax,edx
         jmp .b2
         
         ; 将狀态忙的tcb對象加傳入連結式結構尾部
  .b3:
         ; 設定下一tcb對象為忙的tcb對象
         mov [eax],ebx                 
         ; 設定忙tcb對象下一tcb對象為0x0000 0000     
         mov dword [ebx],0x00000000         
         
         ; 鍊式結構中無tcb對象
         mov eax,tcb_chain
         ; 從鍊式結構尋找狀态空閑的任務
  .b4:
         mov eax,[eax]
         or eax,eax                        
         jz .irtn             

         ; 如果eax指向tcb對象狀态是空閑            
         cmp word [eax+0x04],0x0000        
         jnz .b4
         
         ; 不忙的tcb對象狀态修改為忙
         not word [eax+0x04]  
         ; 狀态忙的tcb對象的狀态修改為不忙             
         not word [ebx+0x04]        
         ; 通過jmp實作任務切換        
         jmp far [eax+0x14]                
  .irtn:
         popad
         iretd

terminate_current_task:                    
         mov eax,tcb_chain
  .b0:                                      
         mov ebx,[eax]                      
         cmp word [ebx+0x04],0xffff         
         je .b1
         mov eax,ebx                       
         jmp .b0
         
  .b1:
         ; 修改任務狀态為0x3333
         mov word [ebx+0x04],0x3333    
  .b2:
         hlt                                
         jmp .b2 

         pgdt             dw  0             
                          dd  0

         pidt             dw  0
                          dd  0
         ; 屬于核心自己出于邏輯實作需要弄處理的東西。處理器層面無
         tcb_chain        dd  0 
         core_tcb   times  32  db 0        
         page_bit_map     db  0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55
                          db  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
                          db  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
                          db  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
                          db  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55
                          db  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
                          db  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
                          db  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
         page_map_len     equ $-page_bit_map
         salt:
         salt_1           db  '@PrintString'
                     times 256-($-salt_1) db 0
                          dd  put_string
                          dw  flat_4gb_code_seg_sel

         salt_2           db  '@ReadDiskData'
                     times 256-($-salt_2) db 0
                          dd  read_hard_disk_0
                          dw  flat_4gb_code_seg_sel

         salt_3           db  '@PrintDwordAsHexString'
                     times 256-($-salt_3) db 0
                          dd  put_hex_dword
                          dw  flat_4gb_code_seg_sel

         salt_4           db  '@TerminateProgram'
                     times 256-($-salt_4) db 0
                          dd  terminate_current_task
                          dw  flat_4gb_code_seg_sel

         salt_item_len   equ $-salt_4
         salt_items      equ ($-salt)/salt_item_len

         excep_msg        db  '********Exception encounted********',0

         message_0        db  '  Working in system core with protection '
                          db  'and paging are all enabled.System core is mapped '
                          db  'to address 0x80000000.',0x0d,0x0a,0

         message_1        db  '  System wide CALL-GATE mounted.',0x0d,0x0a,0
         
         message_3        db  '********No more pages********',0
         
         core_msg0        db  '  System core task running!',0x0d,0x0a,0
         
         bin_hex          db '0123456789ABCDEF'
         core_buf   times 512 db 0         
         cpu_brnd0        db 0x0d,0x0a,'  ',0
         cpu_brand  times 52 db 0
         cpu_brnd1        db 0x0d,0x0a,0x0d,0x0a,0

; 在使用者任務的ldt安裝8位元組描述符
fill_descriptor_in_ldt:                    
         push eax
         push edx
         push edi
         ; ldt基位址---線性位址
         mov edi,[ebx+0x0c]                
         
         xor ecx,ecx
         ; ldt界限
         mov cx,[ebx+0x0a]                  
         inc cx                            
         
         mov [edi+ecx+0x00],eax
         mov [edi+ecx+0x04],edx             

         add cx,8                           
         dec cx                             
         mov [ebx+0x0a],cx                  
         mov ax,cx
         xor dx,dx
         mov cx,8
         div cx
         
         mov cx,ax
         shl cx,3        
         ; 得到剛剛安裝8位元組描述符的選擇子                   
         or cx,0000_0000_0000_0100B        

         pop edi
         pop edx
         pop eax
         ret
      
load_relocate_program:     
         pushad
         mov ebp,esp

         ; 目前用的是核心任務的頁目錄表
         ; 将此頁目錄表前512項設定為0x0000 0000
         mov ebx,0xfffff000
         xor esi,esi
  .b1:
         mov dword [ebx+esi*4],0x00000000
         inc esi
         cmp esi,512
         jl .b1
         
         mov eax,cr3
         ; 可以使得快表内所有項失效
         ; 塊表是一個寄存器,包含多個項
         ; 每個向給出線性位址--實體位址映射,可以加快位址轉換
         ; 頁目錄表,頁表更新後,快表的更新需要手動觸發
         ; 快表不命中時,會自動進行更新
         mov cr3,eax                        
         
         mov eax,[ebp+40]        
         mov ebx,core_buf                  
         call flat_4gb_code_seg_sel:read_hard_disk_0

         mov eax,[core_buf]                
         mov ebx,eax
         and ebx,0xfffff000                
         add ebx,0x1000                        
         test eax,0x00000fff               
         mov eax,ebx                   

         mov ecx,eax
         ; ecx代表了容納使用者任務所需的4kb頁數量
         shr ecx,12                        
         
         mov eax,[ebp+40]          
         ; tcb線性位址
         mov esi,[ebp+36]                  
  .b2:
         alloc_user_linear                   
         push ecx
         mov ecx,8
  .b3:
         call flat_4gb_code_seg_sel:read_hard_disk_0               
         inc eax
         loop .b3

         pop ecx
         loop .b2

         ; 在核心任務虛拟區域劃分可用4kb用作使用者任務的tss
         alloc_core_linear   
         ; TCB對象結構
         ; 0x44      2位元組頭部選擇子
         ; 0x40      2特權級棧的初始ESP
         ; 0x3e      2特權級棧選擇子
         ; 0x3a      2特權級棧基位址
         ; 0x36      2特權級棧以4KB為機關的長度
         ; 0x32      1特權級棧的初始ESP
         ; 0x30      1特權級棧選擇子
         ; 0x2c      1特權級棧基位址
         ; 0x28      1特權級棧以4kb為機關的長度
         ; 0x24      0特權級棧的初始ESP
         ; 0x22      0特權級棧選擇子
         ; 0x1e      0特權級棧基位址
         ; 0x1a      0特權級棧以4kb為機關的長度
         ; 0x18      tss選擇子
         ; 0x14      tss基位址
         ; 0x12      tss界限值
         ; 0x10      ldt選擇子
         ; 0x0c      ldt基位址
         ; 0x0a      ldt目前界限值
         ; 0x06      程式加載基位址
         ; 0x04      任務狀态
         ; 0x00      下一個tcb基位址
         
         ; 使用者任務tcb中設定使用者任務tss基位址--線性位址
         mov [esi+0x14],ebx                
         ; 使用者任務tcb中設定使用者任務tss界限
         mov word [esi+0x12],103         
         ; 在使用者任務虛拟區域劃分可用4kb區域用作使用者任務ldt區域   
         alloc_user_linear                 
         ; 使用者任務tcb中設定ldt基位址--線性位址
         mov [esi+0x0c],ebx   

         mov eax,0x00000000
         mov ebx,0x000fffff
         ; 4kb計量 32位 段在記憶體 特權級3 非系統段 代碼段                 
         mov ecx,0x00c0f800   
         ; 構造代碼段             
         call flat_4gb_code_seg_sel:make_seg_descriptor
         mov ebx,esi 
         ; 在使用者任務ldt區域安裝代碼段描述符                       
         call fill_descriptor_in_ldt
         ; 段選擇子請求特權級是3
         or cx,0000_0000_0000_0011B       
         
         mov ebx,[esi+0x14]  
         ; TSS格式
         ; I/OMapAddr       Reserved      100
         ; Reserved         LDT_Sector    96
         ; Reserved         GS            92
         ; Reserved         FS            88
         ; Reserved         DS            84
         ; Reserved         SS            80
         ; Reserved         CS            76
         ; Reserved         ES            72
         ; EDI                            68
         ; ESI                            64
         ; EBP                            60
         ; ESP                            56
         ; EBX                            52
         ; EDX                            48
         ; ECX                            44
         ; EAX                            40
         ; EFLAGS                         36
         ; EIP                            32
         ; CR3(PDBR)                      28
         ; Reserved         SS2           24
         ; ESP2                           20
         ; Reserved         SS1           16
         ; ESP1                           12
         ; Reserved         SS0           8
         ; ESP0                           4
         ; Reserved         Pre_Task_Tss  0  
         ; 在使用者任務tss中設定cs--代碼段選擇子
         mov [ebx+76],cx                  

         mov eax,0x00000000
         mov ebx,0x000fffff    
         ; 4kb計量 32位 段在記憶體 特權級3 非系統段 可讀可寫資料段             
         mov ecx,0x00c0f200                
         call flat_4gb_code_seg_sel:make_seg_descriptor
         mov ebx,esi                        
         call fill_descriptor_in_ldt
         or cx,0000_0000_0000_0011B         
         
         mov ebx,[esi+0x14]  
         ; 在使用者任務tss中設定ds,es,fs,gs--資料段選擇子            
         mov [ebx+84],cx                   
         mov [ebx+72],cx                  
         mov [ebx+88],cx                 
         mov [ebx+92],cx                
         
         alloc_user_linear                 
         mov ebx,[esi+0x14] 
         ; 在使用者任務tss中設定ss--棧段選擇子              
         mov [ebx+80],cx                   
         mov edx,[esi+0x06]                
         ; 在使用者任務tss中設定esp--棧段的esp,初始時刻指向區域尾後位置
         mov [ebx+56],edx  

         ; 使用者任務虛拟空間内劃分4kb可用空間用于特權級0棧                
         alloc_user_linear                
         mov eax,0x00000000
         mov ebx,0x000fffff
         mov ecx,0x00c09200                 
         call flat_4gb_code_seg_sel:make_seg_descriptor
         mov ebx,esi      
         ; 在使用者任務ldt區域安裝段描述符                
         call fill_descriptor_in_ldt
         or cx,0000_0000_0000_0000B        

         mov ebx,[esi+0x14]   
         ; 在使用者任務tss中設定ss0--0特權級棧段選擇子             
         mov [ebx+8],cx                    
         mov edx,[esi+0x06] 
         ; 在使用者任務tss中設定esp0--0特權級棧段的esp                
         mov [ebx+4],edx   

         alloc_user_linear                 
         mov eax,0x00000000
         mov ebx,0x000fffff
         mov ecx,0x00c0b200                
         call flat_4gb_code_seg_sel:make_seg_descriptor
         mov ebx,esi                       
         call fill_descriptor_in_ldt
         or cx,0000_0000_0000_0001B        
         mov ebx,[esi+0x14]    
         ; 在使用者任務tss中設定ss1--1特權級棧段選擇子            
         mov [ebx+16],cx                    
         mov edx,[esi+0x06]   
         ; 在使用者任務tss中設定esp1--1特權級棧段的esp               
         mov [ebx+12],edx                 

         alloc_user_linear                  
         mov eax,0x00000000
         mov ebx,0x000fffff
         mov ecx,0x00c0d200                
         call flat_4gb_code_seg_sel:make_seg_descriptor
         mov ebx,esi                       
         call fill_descriptor_in_ldt
         or cx,0000_0000_0000_0010B        
         mov ebx,[esi+0x14]  
         ; 在使用者任務tss中設定ss2--2特權級棧段選擇子                
         mov [ebx+24],cx                   
         mov edx,[esi+0x06]  
         ; 在使用者任務tss中設定esp2--2特權級棧段的esp               
         mov [ebx+20],edx                   
         cld

         ; 對使用者任務的每個符号進行内循環處理
         ; 使用者任務符号數
         mov ecx,[0x0c]    
         ; 首個符号的段内偏移                
         mov edi,[0x08]                    
  .b4:
         push ecx
         push edi
         
         ; 對使用者任務目前符号edi,依次将核心每個符号與其比對
         ; 核心任務符号數
         mov ecx,salt_items
         ; 核心任務首個符号偏移---就是符号的線性位址
         mov esi,salt
  .b5:
         push edi
         push esi
         push ecx

         mov ecx,64                        
         repe cmpsd                         
         jnz .b6
         ; 比較并比對
         mov eax,[esi] 
         ; 使用者任務在符号頭存儲4位元組段内偏移                     
         mov [edi-256],eax                 
         mov ax,[esi+4]
         or ax,0000000000000011B  
         ; 使用者任務在符号頭5,6位元組存儲門選擇子(請求特權級是3)          
         mov [edi-252],ax                   
  .b6:
         pop ecx
         pop esi
         ; esi指向核心下一符号
         add esi,salt_item_len
         pop edi                           
         loop .b5
      
         pop edi
         ; edi指向使用者任務下一符号
         add edi,256
         pop ecx
         loop .b4
         
         ; 使用者任務tcb對象線性位址
         mov esi,[ebp+36]   
         ; TCB對象結構
         ; 0x44      2位元組頭部選擇子
         ; 0x40      2特權級棧的初始ESP
         ; 0x3e      2特權級棧選擇子
         ; 0x3a      2特權級棧基位址
         ; 0x36      2特權級棧以4KB為機關的長度
         ; 0x32      1特權級棧的初始ESP
         ; 0x30      1特權級棧選擇子
         ; 0x2c      1特權級棧基位址
         ; 0x28      1特權級棧以4kb為機關的長度
         ; 0x24      0特權級棧的初始ESP
         ; 0x22      0特權級棧選擇子
         ; 0x1e      0特權級棧基位址
         ; 0x1a      0特權級棧以4kb為機關的長度
         ; 0x18      tss選擇子
         ; 0x14      tss基位址
         ; 0x12      tss界限值
         ; 0x10      ldt選擇子
         ; 0x0c      ldt基位址
         ; 0x0a      ldt目前界限值
         ; 0x06      程式加載基位址
         ; 0x04      任務狀态
         ; 0x00      下一個tcb基位址
         ; 使用者任務ldt基位址--線性位址               
         mov eax,[esi+0x0c]   
         ; 使用者任務ldt區域界限             
         movzx ebx,word [esi+0x0a]  
         ; 位元組計量 32位 段在記憶體 特權級0 系統段 可讀可寫資料段       
         mov ecx,0x00408200                 
         call flat_4gb_code_seg_sel:make_seg_descriptor
         ; 使用者任務ldt區域的描述符需要安裝在gdt
         call flat_4gb_code_seg_sel:set_up_gdt_descriptor
         ; 使用者任務tcb對象中設定ldt段的選擇子
         mov [esi+0x10],cx                 

         mov ebx,[esi+0x14]  
         ; TSS格式
         ; I/OMapAddr       Reserved      100
         ; Reserved         LDT_Sector    96
         ; Reserved         GS            92
         ; Reserved         FS            88
         ; Reserved         DS            84
         ; Reserved         SS            80
         ; Reserved         CS            76
         ; Reserved         ES            72
         ; EDI                            68
         ; ESI                            64
         ; EBP                            60
         ; ESP                            56
         ; EBX                            52
         ; EDX                            48
         ; ECX                            44
         ; EAX                            40
         ; EFLAGS                         36
         ; EIP                            32
         ; CR3(PDBR)                      28
         ; Reserved         SS2           24
         ; ESP2                           20
         ; Reserved         SS1           16
         ; ESP1                           12
         ; Reserved         SS0           8
         ; ESP0                           4
         ; Reserved         Pre_Task_Tss  0  
         ; 使用者任務tss對象中設定使用者任務ldt區域的選擇子              
         mov [ebx+96],cx   
         ; 使用者任務tss對象中設定前一任務tss選擇子為0x00 00               
         mov word [ebx+0],0                
      
         mov dx,[esi+0x12]   
         ; 使用者任務tss對象中設定i/o映射資訊              
         mov [ebx+102],dx                   
         mov word [ebx+100],0             
         
         ; 入口點的段内偏移
         mov eax,[0x04]  
         ; 使用者任務tss對象中設定eip                
         mov [ebx+32],eax               
         
         ; 擷取目前eflags
         pushfd
         pop edx
         ; 使用者任務tss對象中設定eflags
         mov [ebx+36],edx  

         ; 使用者任務tss基位址                
         mov eax,[esi+0x14]  
         ; 使用者任務tss界限值              
         movzx ebx,word [esi+0x12] 
         ; 位元組計量 32位 段在記憶體 0特權級 系統段 代碼段&已經通路         
         mov ecx,0x00408900                
         call flat_4gb_code_seg_sel:make_seg_descriptor
         call flat_4gb_code_seg_sel:set_up_gdt_descriptor
         ; 使用者任務tcb中設定tss段的選擇子
         mov [esi+0x18],cx                  
         
         ; 配置設定4kb實體頁,将目前頁目錄表拷貝到新配置設定的實體頁
         call flat_4gb_code_seg_sel:create_copy_cur_pdir
         mov ebx,[esi+0x14]  
         ; 使用者任務tss對象中設定cr3---使用者任務頁目錄表的實體位址              
         mov dword [ebx+28],eax   

         popad
         ; 出棧并控制跳轉,跳轉前繼續出棧8位元組
         ret 8   

; 加入tcb鍊式結構                          
append_to_tcb_link:
         cli
         push eax
         push ebx
         mov eax,tcb_chain
  .b0:        
         ; 取出下一tcb對象                              
         mov ebx,[eax]                    
         or ebx,ebx
         ; 下一tcb對象不存在
         jz .b1                            
         mov eax,ebx                      
         jmp .b0

  .b1:
         ; 設定下一tcb對象
         mov [eax],ecx
         ; 設定傳入tcb對象的下一tcb對象為不存在
         mov dword [ecx],0x00000000         
         pop ebx
         pop eax
         sti
         ret
         
start:
         mov eax,general_exception_handler
         mov bx,flat_4gb_code_seg_sel
         ; P DPL 0 TYPE(1100) 000 參數個數(5位) 
         ; 門指向代碼在記憶體 特權級0 類别
         mov cx,0x8e00 
         call flat_4gb_code_seg_sel:make_gate_descriptor

         mov ebx,idt_linear_address    
         xor esi,esi
  .idt0:
         mov [ebx+esi*8],eax
         mov [ebx+esi*8+4],edx
         inc esi
         cmp esi,19                        
         jle .idt0
         
         mov eax,general_interrupt_handler
         mov bx,flat_4gb_code_seg_sel    
         ; 門指向代碼在記憶體 特權級0 類别  
         mov cx,0x8e00                     
         call flat_4gb_code_seg_sel:make_gate_descriptor
         mov ebx,idt_linear_address         
  .idt1:
         mov [ebx+esi*8],eax
         mov [ebx+esi*8+4],edx
         inc esi
         cmp esi,255                       
         jle .idt1
         
         mov eax,rtm_0x70_interrupt_handle
         mov bx,flat_4gb_code_seg_sel
         ; 門指向代碼在記憶體 特權級0 類别 
         mov cx,0x8e00                     
         call flat_4gb_code_seg_sel:make_gate_descriptor

         mov ebx,idt_linear_address         
         mov [ebx+0x70*8],eax
         mov [ebx+0x70*8+4],edx
         
         ; 設定idt區域前256個8位元組描述符&通知處理器
         mov word [pidt],256*8-1
         mov dword [pidt+2],idt_linear_address
         lidt [pidt]                        

         mov al,0x11
         ; 向0x20寫入0x11
         out 0x20,al                       
         mov al,0x20
         ; 向0x21寫入0x20
         out 0x21,al                       
         mov al,0x04
         ; 向0x21寫入0x04
         out 0x21,al                       
         mov al,0x01
         ; 向0x21寫入0x01
         out 0x21,al                       

         mov al,0x11
         ; 向0xa0寫入0x11
         out 0xa0,al                       
         mov al,0x70
         ; 向0xa1寫入0x70
         out 0xa1,al                       
         mov al,0x04
         ; 向0xa1寫入0x04
         out 0xa1,al                      
         mov al,0x01
         ; 向0xa1寫入0x01
         out 0xa1,al                      

         mov al,0x0b      
         ; 得到0x8b                  
         or al,0x80
         ; 向0x70寫入0x8b                        
         out 0x70,al
         mov al,0x12     
         ; 向0x71寫入0x12                  
         out 0x71,al                        
         
         ; 從0xa1讀取1位元組
         in al,0xa1       
         ; 讀取1位元組最低位設定為0                 
         and al,0xfe             
         ; 向0xa1寫入a1          
         out 0xa1,al                        

         mov al,0x0c
         ; 向0x70寫入0x0c
         out 0x70,al
         ; 從0x71讀取1位元組
         in al,0x71       

         ; 進入核心任務是硬體中斷是關閉的,中斷機制準備就緒後,才開啟硬體中斷
         sti           

         mov ebx,message_0
         call flat_4gb_code_seg_sel:put_string
         
         mov eax,0x80000002
         cpuid
         mov [cpu_brand + 0x00],eax
         mov [cpu_brand + 0x04],ebx
         mov [cpu_brand + 0x08],ecx
         mov [cpu_brand + 0x0c],edx
         
         mov eax,0x80000003
         cpuid
         mov [cpu_brand + 0x10],eax
         mov [cpu_brand + 0x14],ebx
         mov [cpu_brand + 0x18],ecx
         mov [cpu_brand + 0x1c],edx
         
         mov eax,0x80000004
         cpuid
         mov [cpu_brand + 0x20],eax
         mov [cpu_brand + 0x24],ebx
         mov [cpu_brand + 0x28],ecx
         mov [cpu_brand + 0x2c],edx
         
         mov ebx,cpu_brnd0                  
         call flat_4gb_code_seg_sel:put_string
         mov ebx,cpu_brand
         call flat_4gb_code_seg_sel:put_string
         mov ebx,cpu_brnd1
         call flat_4gb_code_seg_sel:put_string

         mov edi,salt                      
         mov ecx,salt_items                 
  .b4:
         push ecx   
         mov eax,[edi+256]
         mov bx,[edi+260]
         ; P DPL 0 TYPE(1100) 000 參數個數(5位) 
         ; 門指向代碼在記憶體 特權級3 類别
         mov cx,1_11_0_1100_000_00000B
         call flat_4gb_code_seg_sel:make_gate_descriptor
         call flat_4gb_code_seg_sel:set_up_gdt_descriptor
         ; 符号中本來存儲段選擇子的現在存儲門選擇子
         mov [edi+260],cx                   
         add edi,salt_item_len             
         pop ecx
         loop .b4
         
         mov ebx,message_1
         call far [salt_1+256]

         ; TCB對象結構
         ; 0x44      2位元組頭部選擇子
         ; 0x40      2特權級棧的初始ESP
         ; 0x3e      2特權級棧選擇子
         ; 0x3a      2特權級棧基位址
         ; 0x36      2特權級棧以4KB為機關的長度
         ; 0x32      1特權級棧的初始ESP
         ; 0x30      1特權級棧選擇子
         ; 0x2c      1特權級棧基位址
         ; 0x28      1特權級棧以4kb為機關的長度
         ; 0x24      0特權級棧的初始ESP
         ; 0x22      0特權級棧選擇子
         ; 0x1e      0特權級棧基位址
         ; 0x1a      0特權級棧以4kb為機關的長度
         ; 0x18      tss選擇子
         ; 0x14      tss基位址
         ; 0x12      tss界限值
         ; 0x10      ldt選擇子
         ; 0x0c      ldt基位址
         ; 0x0a      ldt目前界限值
         ; 0x06      程式加載基位址
         ; 0x04      任務狀态
         ; 0x00      下一個tcb基位址

         ; 設定任務狀态
         mov word [core_tcb+0x04],0xffff
         ; 設定核心任務下一可用線性位址   
         mov dword [core_tcb+0x06],0x80100000   
         ; 設定ldt目前界限值 
         mov word [core_tcb+0x0a],0xffff
         ; tcb對象加傳入連結式結構    
         mov ecx,core_tcb
         call append_to_tcb_link   

         ; 配置設定4kb可用虛拟區域 ---用于存儲核心任務tss對象     
         alloc_core_linear    
         ; TSS格式
         ; I/OMapAddr       Reserved      100
         ; Reserved         LDT_Sector    96
         ; Reserved         GS            92
         ; Reserved         FS            88
         ; Reserved         DS            84
         ; Reserved         SS            80
         ; Reserved         CS            76
         ; Reserved         ES            72
         ; EDI                            68
         ; ESI                            64
         ; EBP                            60
         ; ESP                            56
         ; EBX                            52
         ; EDX                            48
         ; ECX                            44
         ; EAX                            40
         ; EFLAGS                         36
         ; EIP                            32
         ; CR3(PDBR)                      28
         ; Reserved         SS2           24
         ; ESP2                           20
         ; Reserved         SS1           16
         ; ESP1                           12
         ; Reserved         SS0           8
         ; ESP0                           4
         ; Reserved         Pre_Task_Tss  0    
         ; tss對象設定前一任務tss選擇子        
         mov word [ebx+0],0                
         mov eax,cr3
         ; tss對象設定頁目錄表---每個任務有自己的頁目錄表,這裡存儲的是頁目錄表的實體位址
         ; 頁目錄表,頁表中目錄項的位址資訊也是實體位址的資訊
         mov dword [ebx+28],eax
         ; tss對象設定ldt選擇子             
         mov word [ebx+96],0   
         ; tss對象設定i/o映射            
         mov word [ebx+100],0              
         mov word [ebx+102],103            
         
         mov eax,ebx
         mov ebx,103
         ; 位元組計量 32位 段在記憶體 特權級0 系統段 代碼段&被通路過
         mov ecx,0x00408900     
         call flat_4gb_code_seg_sel:make_seg_descriptor
         call flat_4gb_code_seg_sel:set_up_gdt_descriptor
         mov [core_tcb+0x18],cx
         ltr cx
         
         alloc_core_linear        
         ; 新的區域用于使用者任務tcb對象
         ; TCB對象結構
         ; 0x44      2位元組頭部選擇子
         ; 0x40      2特權級棧的初始ESP
         ; 0x3e      2特權級棧選擇子
         ; 0x3a      2特權級棧基位址
         ; 0x36      2特權級棧以4KB為機關的長度
         ; 0x32      1特權級棧的初始ESP
         ; 0x30      1特權級棧選擇子
         ; 0x2c      1特權級棧基位址
         ; 0x28      1特權級棧以4kb為機關的長度
         ; 0x24      0特權級棧的初始ESP
         ; 0x22      0特權級棧選擇子
         ; 0x1e      0特權級棧基位址
         ; 0x1a      0特權級棧以4kb為機關的長度
         ; 0x18      tss選擇子
         ; 0x14      tss基位址
         ; 0x12      tss界限值
         ; 0x10      ldt選擇子
         ; 0x0c      ldt基位址
         ; 0x0a      ldt目前界限值
         ; 0x06      程式加載基位址
         ; 0x04      任務狀态
         ; 0x00      下一個tcb基位址

         ; tcb對象設定任務狀态
         mov word [ebx+0x04],0
         ; tcb對象設定使用者任務下一可用線性位址             
         mov dword [ebx+0x06],0            
         ; tcb對象設定ldt目前界限值
         mov word [ebx+0x0a],0xffff        
         
         push dword 50       
         push ebx             
         call load_relocate_program

         mov ecx,ebx         
         call append_to_tcb_link

         alloc_core_linear         
         ; 新的區域用于使用者任務tcb對象
         ; TCB對象結構
         ; 0x44      2位元組頭部選擇子
         ; 0x40      2特權級棧的初始ESP
         ; 0x3e      2特權級棧選擇子
         ; 0x3a      2特權級棧基位址
         ; 0x36      2特權級棧以4KB為機關的長度
         ; 0x32      1特權級棧的初始ESP
         ; 0x30      1特權級棧選擇子
         ; 0x2c      1特權級棧基位址
         ; 0x28      1特權級棧以4kb為機關的長度
         ; 0x24      0特權級棧的初始ESP
         ; 0x22      0特權級棧選擇子
         ; 0x1e      0特權級棧基位址
         ; 0x1a      0特權級棧以4kb為機關的長度
         ; 0x18      tss選擇子
         ; 0x14      tss基位址
         ; 0x12      tss界限值
         ; 0x10      ldt選擇子
         ; 0x0c      ldt基位址
         ; 0x0a      ldt目前界限值
         ; 0x06      程式加載基位址
         ; 0x04      任務狀态
         ; 0x00      下一個tcb基位址        
         mov word [ebx+0x04],0             
         mov dword [ebx+0x06],0            
         mov word [ebx+0x0a],0xffff       
         
         push dword 100      
         push ebx                 
         call load_relocate_program

         mov ecx,ebx
         call append_to_tcb_link      

  .core:
         mov ebx,core_msg0
         call flat_4gb_code_seg_sel:put_string
         jmp .core
core_code_end:
SECTION core_trail
core_end:
           

3.使用者任務

program_length   dd program_end          
         entry_point      dd start               
         salt_position    dd salt_begin           
         salt_items       dd (salt_end-salt_begin)/256 
         salt_begin:                                     
         PrintString      db  '@PrintString'
                     times 256-($-PrintString) db 0
         TerminateProgram db  '@TerminateProgram'
                     times 256-($-TerminateProgram) db 0
         ReadDiskData     db  '@ReadDiskData'
                     times 256-($-ReadDiskData) db 0
         PrintDwordAsHex  db  '@PrintDwordAsHexString'
                     times 256-($-PrintDwordAsHex) db 0
         salt_end:
         message_0        db  '  User task A->;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'
                          db  0x0d,0x0a,0
      [bits 32]
start:
         mov ebx,message_0
         call far [PrintString]
         jmp start
         call far [TerminateProgram]               
program_end:
           

4.使用者任務2

program_length   dd program_end        
         entry_point      dd start               
         salt_position    dd salt_begin            
         salt_items       dd (salt_end-salt_begin)/256 
         salt_begin:                                     
         PrintString      db  '@PrintString'
                     times 256-($-PrintString) db 0
         TerminateProgram db  '@TerminateProgram'
                     times 256-($-TerminateProgram) db 0
         ReadDiskData     db  '@ReadDiskData'
                     times 256-($-ReadDiskData) db 0
         PrintDwordAsHex  db  '@PrintDwordAsHexString'
                     times 256-($-PrintDwordAsHex) db 0
         salt_end:
         message_0        db  '  User task B->$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
                          db  0x0d,0x0a,0
      [bits 32]
start:
         mov ebx,message_0
         call far [PrintString]
         jmp start  
         call far [TerminateProgram]             
program_end:
           

繼續閱讀