Linux操作系统, 构建自己的内核——6.使用调色板绘制系统界面

﹏ヽ暗。殇╰゛Y 2024-04-18 15:32 125阅读 0赞

学习课程:
使用调色板绘制系统界面

在上一课程中,通过往0xA0000-0xAFFFF共64KB的的显存空间写入0-255的字符,来绘制界面。
0-255表示的颜色非常有限,画出来的效果很单调。利用调色板功能,能够绘制出更丰富的图案。

使用调色板功能时,显存空间的每个字符不再表示颜色,而是表示颜色的下标。
真正的颜色存储在一个数组中。因为一个字节最大只能表示到255,所以,表示颜色的数组最大也只能255。
在表示颜色的数组中,使用RGB方法表示颜色,每种颜色用3个字节表示,分别对应red,green,blue。
要打开调色板功能,和写入表示颜色的数组,都需要与硬件的端口打交道。

1. 使用调色板

kernel.asm

  1. %include "pm.inc"
  2. org 0x9000
  3. VRAM_ADDRESS equ 0x000a0000
  4. jmp LABEL_BEGIN
  5. [SECTION .gdt]
  6. ; 段基址 段界限 属性
  7. LABEL_GDT: Descriptor 0, 0, 0
  8. LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32
  9. LABEL_DESC_VRAM: Descriptor 0, 0ffffffffh, DA_DRW
  10. LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA+DA_32
  11. GdtLen equ $ - LABEL_GDT
  12. GdtPtr dw GdtLen - 1
  13. dd 0
  14. SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
  15. SelectorStack equ LABEL_DESC_STACK - LABEL_GDT
  16. SelectorVram equ LABEL_DESC_VRAM - LABEL_GDT
  17. [SECTION .s16]
  18. [BITS 16]
  19. LABEL_BEGIN:
  20. mov ax, cs
  21. mov ds, ax
  22. mov es, ax
  23. mov ss, ax
  24. mov sp, 0100h
  25. mov al, 0x13
  26. mov ah, 0
  27. int 0x10
  28. xor eax, eax
  29. mov ax, cs
  30. shl eax, 4
  31. add eax, LABEL_SEG_CODE32
  32. mov word [LABEL_DESC_CODE32 + 2], ax
  33. shr eax, 16
  34. mov byte [LABEL_DESC_CODE32 + 4], al
  35. mov byte [LABEL_DESC_CODE32 + 7], ah
  36. xor eax, eax
  37. mov ax, cs
  38. shl eax, 4
  39. add eax, LABEL_STACK
  40. mov word [LABEL_DESC_STACK + 2], ax
  41. shr eax, 16
  42. mov byte [LABEL_DESC_STACK + 4], al
  43. mov byte [LABEL_DESC_STACK + 7], ah
  44. xor eax, eax
  45. mov ax, ds
  46. shl eax, 4
  47. add eax, LABEL_GDT
  48. mov dword [GdtPtr + 2], eax
  49. lgdt [GdtPtr]
  50. cli ;关中断
  51. in al, 92h
  52. or al, 00000010b
  53. out 92h, al
  54. mov eax, cr0
  55. or eax , 1
  56. mov cr0, eax
  57. jmp dword SelectorCode32: 0
  58. [SECTION .s32]
  59. [BITS 32]
  60. LABEL_SEG_CODE32:
  61. ;initialize stack for c code
  62. mov ax, SelectorStack
  63. mov ss, ax
  64. mov esp, TopOfStack
  65. mov ax, SelectorVram
  66. mov ds, ax
  67. C_CODE_ENTRY:
  68. %include "palette1.asm"
  69. io_hlt: ;void io_hlt(void);
  70. HLT
  71. RET
  72. io_in8:
  73. mov edx, [esp + 4]
  74. mov eax, 0
  75. in al, dx
  76. io_in16:
  77. mov edx, [esp + 4]
  78. mov eax, 0
  79. in ax, dx
  80. io_in32:
  81. mov edx, [esp + 4]
  82. in eax, dx
  83. ret
  84. io_out8:
  85. mov edx, [esp + 4]
  86. mov al, [esp + 8]
  87. out dx, al
  88. ret
  89. io_out16:
  90. mov edx, [esp + 4]
  91. mov eax, [esp + 8]
  92. out dx, ax
  93. ret
  94. io_out32:
  95. mov edx, [esp + 4]
  96. mov eax, [esp + 8]
  97. out dx, eax
  98. ret
  99. io_cli:
  100. CLI
  101. RET
  102. io_load_eflags:
  103. pushfd
  104. pop eax
  105. ret
  106. io_store_eflags:
  107. mov eax, [esp + 4]
  108. push eax
  109. popfd
  110. ret
  111. SegCode32Len equ $ - LABEL_SEG_CODE32
  112. [SECTION .gs]
  113. ALIGN 32
  114. [BITS 32]
  115. LABEL_STACK:
  116. times 512 db 0
  117. TopOfStack equ $ - LABEL_STACK

操作端口的这几个汇编函数,是很不错的封装,简化了在c语言中的使用。
可以看出来,
[esp+4]表示函数的第一个参数
[esp+8]表示函数的第二个参数

那便有一个疑问,[esp]表示的是什么呢?
esp表示的是上一个函数的返回地址。也就是这个函数执行完成之后,要执行的下一条指令。
而参数是按照从右向左的方式入栈的,所以取的时候,esp+4的位置便取到的是第一个参数。

write_vga.asm

  1. ; Disassembly of file: write_vga.o
  2. ; Sun Sep 8 06:05:48 2019
  3. ; Mode: 32 bits
  4. ; Syntax: YASM/NASM
  5. ; Instruction set: 80386
  6. CMain: ; Function begin
  7. push ebp ; 0000 _ 55
  8. mov ebp, esp ; 0001 _ 89. E5
  9. sub esp, 24 ; 0003 _ 83. EC, 18
  10. mov dword [ebp-0CH], 0 ; 0006 _ C7. 45, F4, 00000000
  11. call init_palette ; 000D _ E8, FFFFFFFC(rel)
  12. mov dword [ebp-10H], 655360 ; 0012 _ C7. 45, F0, 000A0000
  13. jmp ?_002 ; 0019 _ EB, 17
  14. ?_001: mov eax, dword [ebp-10H] ; 001B _ 8B. 45, F0
  15. mov dword [ebp-0CH], eax ; 001E _ 89. 45, F4
  16. mov eax, dword [ebp-10H] ; 0021 _ 8B. 45, F0
  17. and eax, 0FH ; 0024 _ 83. E0, 0F
  18. mov edx, eax ; 0027 _ 89. C2
  19. mov eax, dword [ebp-0CH] ; 0029 _ 8B. 45, F4
  20. mov byte [eax], dl ; 002C _ 88. 10
  21. add dword [ebp-10H], 1 ; 002E _ 83. 45, F0, 01
  22. ?_002: cmp dword [ebp-10H], 720895 ; 0032 _ 81. 7D, F0, 000AFFFF
  23. jle ?_001 ; 0039 _ 7E, E0
  24. ?_003: call io_hlt ; 003B _ E8, FFFFFFFC(rel)
  25. jmp ?_003 ; 0040 _ EB, F9
  26. ; CMain End of function
  27. init_palette:; Function begin
  28. push ebp ; 0042 _ 55
  29. mov ebp, esp ; 0043 _ 89. E5
  30. sub esp, 24 ; 0045 _ 83. EC, 18
  31. mov dword [esp+8H], table_rgb.1397 ; 0048 _ C7. 44 24, 08, 00000000(d)
  32. mov dword [esp+4H], 15 ; 0050 _ C7. 44 24, 04, 0000000F
  33. mov dword [esp], 0 ; 0058 _ C7. 04 24, 00000000
  34. call set_palette ; 005F _ E8, FFFFFFFC(rel)
  35. nop ; 0064 _ 90
  36. leave ; 0065 _ C9
  37. ret ; 0066 _ C3
  38. ; init_palette End of function
  39. set_palette:; Function begin
  40. push ebp ; 0067 _ 55
  41. mov ebp, esp ; 0068 _ 89. E5
  42. sub esp, 40 ; 006A _ 83. EC, 28
  43. call io_load_eflags ; 006D _ E8, FFFFFFFC(rel)
  44. mov dword [ebp-0CH], eax ; 0072 _ 89. 45, F4
  45. call io_cli ; 0075 _ E8, FFFFFFFC(rel)
  46. mov eax, dword [ebp+8H] ; 007A _ 8B. 45, 08
  47. mov dword [esp+4H], eax ; 007D _ 89. 44 24, 04
  48. mov dword [esp], 968 ; 0081 _ C7. 04 24, 000003C8
  49. call io_out8 ; 0088 _ E8, FFFFFFFC(rel)
  50. mov eax, dword [ebp+8H] ; 008D _ 8B. 45, 08
  51. mov dword [ebp-10H], eax ; 0090 _ 89. 45, F0
  52. jmp ?_005 ; 0093 _ EB, 59
  53. ?_004: mov eax, dword [ebp+10H] ; 0095 _ 8B. 45, 10
  54. movzx eax, byte [eax] ; 0098 _ 0F B6. 00
  55. movzx eax, al ; 009B _ 0F B6. C0
  56. mov dword [esp+4H], eax ; 009E _ 89. 44 24, 04
  57. mov dword [esp], 969 ; 00A2 _ C7. 04 24, 000003C9
  58. call io_out8 ; 00A9 _ E8, FFFFFFFC(rel)
  59. mov eax, dword [ebp+10H] ; 00AE _ 8B. 45, 10
  60. add eax, 1 ; 00B1 _ 83. C0, 01
  61. movzx eax, byte [eax] ; 00B4 _ 0F B6. 00
  62. movzx eax, al ; 00B7 _ 0F B6. C0
  63. mov dword [esp+4H], eax ; 00BA _ 89. 44 24, 04
  64. mov dword [esp], 969 ; 00BE _ C7. 04 24, 000003C9
  65. call io_out8 ; 00C5 _ E8, FFFFFFFC(rel)
  66. mov eax, dword [ebp+10H] ; 00CA _ 8B. 45, 10
  67. add eax, 2 ; 00CD _ 83. C0, 02
  68. movzx eax, byte [eax] ; 00D0 _ 0F B6. 00
  69. movzx eax, al ; 00D3 _ 0F B6. C0
  70. mov dword [esp+4H], eax ; 00D6 _ 89. 44 24, 04
  71. mov dword [esp], 969 ; 00DA _ C7. 04 24, 000003C9
  72. call io_out8 ; 00E1 _ E8, FFFFFFFC(rel)
  73. add dword [ebp+10H], 3 ; 00E6 _ 83. 45, 10, 03
  74. add dword [ebp-10H], 1 ; 00EA _ 83. 45, F0, 01
  75. ?_005: mov eax, dword [ebp-10H] ; 00EE _ 8B. 45, F0
  76. cmp eax, dword [ebp+0CH] ; 00F1 _ 3B. 45, 0C
  77. jle ?_004 ; 00F4 _ 7E, 9F
  78. mov eax, dword [ebp-0CH] ; 00F6 _ 8B. 45, F4
  79. mov dword [esp], eax ; 00F9 _ 89. 04 24
  80. call io_store_eflags ; 00FC _ E8, FFFFFFFC(rel)
  81. nop ; 0101 _ 90
  82. leave ; 0102 _ C9
  83. ret ; 0103 _ C3
  84. ; set_palette End of function
  85. table_rgb.1397: ; byte
  86. db 00H, 00H, 00H, 0FFH, 00H, 00H, 00H, 0FFH ; 0000 _ ........
  87. db 00H, 0FFH, 0FFH, 00H, 00H, 00H, 0FFH, 0FFH ; 0008 _ ........
  88. db 00H, 0FFH, 00H, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH ; 0010 _ ........
  89. db 0C6H, 0C6H, 0C6H, 84H, 00H, 00H, 00H, 84H ; 0018 _ ........
  90. db 00H, 84H, 84H, 00H, 00H, 00H, 84H, 84H ; 0020 _ ........
  91. db 00H, 84H, 00H, 84H, 84H, 84H, 84H, 84H ; 0028 _ ........

效果:
在这里插入图片描述

2. 绘制矩形&绘制桌面

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

发表评论

表情:
评论列表 (有 0 条评论,125人围观)

还没有评论,来说两句吧...

相关阅读