Linux操作系統, 構建自己的內核——6.使用調色板繪製系統界面

學習課程:
使用調色板繪製系統界面

在上一課程中,通過往0xA0000-0xAFFFF共64KB的的顯存空間寫入0-255的字符,來繪製界面。
0-255表示的顏色非常有限,畫出來的效果很單調。利用調色板功能,能夠繪製出更豐富的圖案。

使用調色板功能時,顯存空間的每個字符不再表示顏色,而是表示顏色的下標。
真正的顏色存儲在一個數組中。因爲一個字節最大隻能表示到255,所以,表示顏色的數組最大也只能255。
在表示顏色的數組中,使用RGB方法表示顏色,每種顏色用3個字節表示,分別對應red,green,blue。
要打開調色板功能,和寫入表示顏色的數組,都需要與硬件的端口打交道。

1. 使用調色板

kernel.asm

%include "pm.inc"

org   0x9000

VRAM_ADDRESS  equ  0x000a0000

jmp   LABEL_BEGIN

[SECTION .gdt]
 ;                                  段基址          段界限                屬性
LABEL_GDT:          Descriptor        0,            0,                   0
LABEL_DESC_CODE32:  Descriptor        0,      SegCode32Len - 1,       DA_C + DA_32
LABEL_DESC_VRAM:    Descriptor        0,         0ffffffffh,            DA_DRW
LABEL_DESC_STACK:   Descriptor        0,             TopOfStack,        DA_DRWA+DA_32

GdtLen     equ    $ - LABEL_GDT
GdtPtr     dw     GdtLen - 1
           dd     0

SelectorCode32    equ   LABEL_DESC_CODE32 -  LABEL_GDT
SelectorStack     equ   LABEL_DESC_STACK  -  LABEL_GDT
SelectorVram      equ   LABEL_DESC_VRAM   -  LABEL_GDT


[SECTION  .s16]
[BITS  16]
LABEL_BEGIN:
     mov   ax, cs
     mov   ds, ax
     mov   es, ax
     mov   ss, ax
     mov   sp, 0100h

     mov   al, 0x13
     mov   ah, 0
     int   0x10

     xor   eax, eax
     mov   ax,  cs
     shl   eax, 4
     add   eax, LABEL_SEG_CODE32
     mov   word [LABEL_DESC_CODE32 + 2], ax
     shr   eax, 16
     mov   byte [LABEL_DESC_CODE32 + 4], al
     mov   byte [LABEL_DESC_CODE32 + 7], ah

     xor   eax, eax
     mov   ax,  cs
     shl   eax, 4
     add   eax, LABEL_STACK
     mov   word [LABEL_DESC_STACK + 2], ax
     shr   eax, 16
     mov   byte [LABEL_DESC_STACK + 4], al
     mov   byte [LABEL_DESC_STACK + 7], ah

     xor   eax, eax
     mov   ax, ds
     shl   eax, 4
     add   eax,  LABEL_GDT
     mov   dword  [GdtPtr + 2], eax

     lgdt  [GdtPtr]

     cli   ;關中斷

     in    al,  92h
     or    al,  00000010b
     out   92h, al

     mov   eax, cr0
     or    eax , 1
     mov   cr0, eax

     jmp   dword  SelectorCode32: 0

     [SECTION .s32]
     [BITS  32]
     LABEL_SEG_CODE32:
     ;initialize stack for c code
     mov  ax, SelectorStack
     mov  ss, ax
     mov  esp, TopOfStack

     mov  ax, SelectorVram
     mov  ds,  ax

C_CODE_ENTRY:
     %include "palette1.asm"


    io_hlt:  ;void io_hlt(void);
      HLT
      RET

io_in8:
      mov  edx, [esp + 4]
      mov  eax, 0
      in   al, dx

    io_in16:
      mov  edx, [esp + 4]
      mov  eax, 0
      in   ax, dx

    io_in32:
      mov edx, [esp + 4]
      in  eax, dx
      ret

    io_out8:
       mov edx, [esp + 4]
       mov al, [esp + 8]
       out dx, al
       ret

    io_out16:
       mov edx, [esp + 4]
       mov eax, [esp + 8]
       out dx, ax
       ret

    io_out32:
        mov edx, [esp + 4]
        mov eax, [esp + 8]
        out dx, eax
        ret

    io_cli:
      CLI
      RET
    io_load_eflags:
        pushfd
        pop  eax
        ret

    io_store_eflags:
        mov eax, [esp + 4]
        push eax
        popfd
        ret



SegCode32Len   equ  $ - LABEL_SEG_CODE32

[SECTION .gs]
ALIGN 32
[BITS 32]
LABEL_STACK:
times 512  db 0
TopOfStack  equ  $ - LABEL_STACK

操作端口的這幾個彙編函數,是很不錯的封裝,簡化了在c語言中的使用。
可以看出來,
[esp+4]表示函數的第一個參數
[esp+8]表示函數的第二個參數

那便有一個疑問,[esp]表示的是什麼呢?
esp表示的是上一個函數的返回地址。也就是這個函數執行完成之後,要執行的下一條指令。
而參數是按照從右向左的方式入棧的,所以取的時候,esp+4的位置便取到的是第一個參數。

write_vga.asm

; Disassembly of file: write_vga.o
; Sun Sep  8 06:05:48 2019
; Mode: 32 bits
; Syntax: YASM/NASM
; Instruction set: 80386






CMain:  ; Function begin
        push    ebp                                     ; 0000 _ 55
        mov     ebp, esp                                ; 0001 _ 89. E5
        sub     esp, 24                                 ; 0003 _ 83. EC, 18
        mov     dword [ebp-0CH], 0                      ; 0006 _ C7. 45, F4, 00000000
        call    init_palette                            ; 000D _ E8, FFFFFFFC(rel)
        mov     dword [ebp-10H], 655360                 ; 0012 _ C7. 45, F0, 000A0000
        jmp     ?_002                                   ; 0019 _ EB, 17

?_001:  mov     eax, dword [ebp-10H]                    ; 001B _ 8B. 45, F0
        mov     dword [ebp-0CH], eax                    ; 001E _ 89. 45, F4
        mov     eax, dword [ebp-10H]                    ; 0021 _ 8B. 45, F0
        and     eax, 0FH                                ; 0024 _ 83. E0, 0F
        mov     edx, eax                                ; 0027 _ 89. C2
        mov     eax, dword [ebp-0CH]                    ; 0029 _ 8B. 45, F4
        mov     byte [eax], dl                          ; 002C _ 88. 10
        add     dword [ebp-10H], 1                      ; 002E _ 83. 45, F0, 01
?_002:  cmp     dword [ebp-10H], 720895                 ; 0032 _ 81. 7D, F0, 000AFFFF
        jle     ?_001                                   ; 0039 _ 7E, E0
?_003:  call    io_hlt                                  ; 003B _ E8, FFFFFFFC(rel)
        jmp     ?_003                                   ; 0040 _ EB, F9
; CMain End of function

init_palette:; Function begin
        push    ebp                                     ; 0042 _ 55
        mov     ebp, esp                                ; 0043 _ 89. E5
        sub     esp, 24                                 ; 0045 _ 83. EC, 18
        mov     dword [esp+8H], table_rgb.1397          ; 0048 _ C7. 44 24, 08, 00000000(d)
        mov     dword [esp+4H], 15                      ; 0050 _ C7. 44 24, 04, 0000000F
        mov     dword [esp], 0                          ; 0058 _ C7. 04 24, 00000000
        call    set_palette                             ; 005F _ E8, FFFFFFFC(rel)
        nop                                             ; 0064 _ 90
        leave                                           ; 0065 _ C9
        ret                                             ; 0066 _ C3
; init_palette End of function

set_palette:; Function begin
        push    ebp                                     ; 0067 _ 55
        mov     ebp, esp                                ; 0068 _ 89. E5
        sub     esp, 40                                 ; 006A _ 83. EC, 28
        call    io_load_eflags                          ; 006D _ E8, FFFFFFFC(rel)
        mov     dword [ebp-0CH], eax                    ; 0072 _ 89. 45, F4
        call    io_cli                                  ; 0075 _ E8, FFFFFFFC(rel)
        mov     eax, dword [ebp+8H]                     ; 007A _ 8B. 45, 08
        mov     dword [esp+4H], eax                     ; 007D _ 89. 44 24, 04
        mov     dword [esp], 968                        ; 0081 _ C7. 04 24, 000003C8
        call    io_out8                                 ; 0088 _ E8, FFFFFFFC(rel)
        mov     eax, dword [ebp+8H]                     ; 008D _ 8B. 45, 08
        mov     dword [ebp-10H], eax                    ; 0090 _ 89. 45, F0
        jmp     ?_005                                   ; 0093 _ EB, 59

?_004:  mov     eax, dword [ebp+10H]                    ; 0095 _ 8B. 45, 10
        movzx   eax, byte [eax]                         ; 0098 _ 0F B6. 00
        movzx   eax, al                                 ; 009B _ 0F B6. C0
        mov     dword [esp+4H], eax                     ; 009E _ 89. 44 24, 04
        mov     dword [esp], 969                        ; 00A2 _ C7. 04 24, 000003C9
        call    io_out8                                 ; 00A9 _ E8, FFFFFFFC(rel)
        mov     eax, dword [ebp+10H]                    ; 00AE _ 8B. 45, 10
        add     eax, 1                                  ; 00B1 _ 83. C0, 01
        movzx   eax, byte [eax]                         ; 00B4 _ 0F B6. 00
        movzx   eax, al                                 ; 00B7 _ 0F B6. C0
        mov     dword [esp+4H], eax                     ; 00BA _ 89. 44 24, 04
        mov     dword [esp], 969                        ; 00BE _ C7. 04 24, 000003C9
        call    io_out8                                 ; 00C5 _ E8, FFFFFFFC(rel)
        mov     eax, dword [ebp+10H]                    ; 00CA _ 8B. 45, 10
        add     eax, 2                                  ; 00CD _ 83. C0, 02
        movzx   eax, byte [eax]                         ; 00D0 _ 0F B6. 00
        movzx   eax, al                                 ; 00D3 _ 0F B6. C0
        mov     dword [esp+4H], eax                     ; 00D6 _ 89. 44 24, 04
        mov     dword [esp], 969                        ; 00DA _ C7. 04 24, 000003C9
        call    io_out8                                 ; 00E1 _ E8, FFFFFFFC(rel)
        add     dword [ebp+10H], 3                      ; 00E6 _ 83. 45, 10, 03
        add     dword [ebp-10H], 1                      ; 00EA _ 83. 45, F0, 01
?_005:  mov     eax, dword [ebp-10H]                    ; 00EE _ 8B. 45, F0
        cmp     eax, dword [ebp+0CH]                    ; 00F1 _ 3B. 45, 0C
        jle     ?_004                                   ; 00F4 _ 7E, 9F
        mov     eax, dword [ebp-0CH]                    ; 00F6 _ 8B. 45, F4
        mov     dword [esp], eax                        ; 00F9 _ 89. 04 24
        call    io_store_eflags                         ; 00FC _ E8, FFFFFFFC(rel)
        nop                                             ; 0101 _ 90
        leave                                           ; 0102 _ C9
        ret                                             ; 0103 _ C3
; set_palette End of function



table_rgb.1397:                                         ; byte
        db 00H, 00H, 00H, 0FFH, 00H, 00H, 00H, 0FFH     ; 0000 _ ........
        db 00H, 0FFH, 0FFH, 00H, 00H, 00H, 0FFH, 0FFH   ; 0008 _ ........
        db 00H, 0FFH, 00H, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH ; 0010 _ ........
        db 0C6H, 0C6H, 0C6H, 84H, 00H, 00H, 00H, 84H    ; 0018 _ ........
        db 00H, 84H, 84H, 00H, 00H, 00H, 84H, 84H       ; 0020 _ ........
        db 00H, 84H, 00H, 84H, 84H, 84H, 84H, 84H       ; 0028 _ ........

效果:
在這裏插入圖片描述

2. 繪製矩形&繪製桌面

都是調色板的具體應用而已,沒有新的知識點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章