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. 绘制矩形&绘制桌面

都是调色板的具体应用而已,没有新的知识点。

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