当前位置:   article > 正文

获取物理内存容量(下)

获取物理内存容量(下)

我们这节课BIOS提供的(int 0x15)号中断的高级功能(eax = 0xE820),遍历主机上所有的内存范围(内存地址段),获取各个内存范围的详细信息

int 0x15 进阶版功能

中断参数

  • eax = 0xE820 (固定值)
  • edx = 0x534D4150 (固定值)
  • ebx --> 初始参数必须为0,终止标志
  • ecx --> ARDS 结构体大小 (20字节)
  • es : di --> ARDS 结构体数组 (每个元素占用20字节)



地址范围描述结构 (Address Range Descriptor Structure)

int 0x15 进阶功能示例

  1. %include "inc.asm"
  2. org 0x9000
  3. jmp ENTRY_SEGMENT
  4. [section .gdt]
  5. ; GDT definition
  6. ; 段基址, 段界限, 段属性
  7. GDT_ENTRY : Descriptor 0, 0, 0
  8. CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_32 + DA_C
  9. VIDEO_DESC : Descriptor 0xb8000, 0x7fff, DA_32 + DA_DRWA
  10. DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_32 + DA_DRW
  11. STACK32_DESC : Descriptor 0, TopOfStack32, DA_32 + DA_DRW
  12. ; GDT end
  13. GdtLen equ $ - GDT_ENTRY
  14. GdtPtr:
  15. dw GdtLen - 1
  16. dd 0
  17. ; GDT Selector
  18. Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
  19. VideoSelector equ (0x0002 << 3) + SA_TIG + SA_RPL0
  20. Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL0
  21. Stack32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
  22. ; end of [section .gdt]
  23. TopOfStack16 equ 0x7c00
  24. ; get hardware memory infomation
  25. MEM_SIZE times 4 db 0x00 ; int mem_size = 0
  26. MEM_ARDS_NUM times 4 db 0x00 ; int men_addr_num = 0
  27. MEM_ARDS times 20 * 64 db 0x00 ; ARDS mem_adrs[64] = {0}
  28. [section .dat]
  29. [bits 32]
  30. DATA32_SEGMENT:
  31. DTOS db "D.T.OS!", 0
  32. DTOS_Offset equ DTOS - $$
  33. HELLOWORLD db "Hello, World!", 0
  34. HELLOWORLD_Offset equ HELLOWORLD - $$
  35. Data32SegLen equ $ - DATA32_SEGMENT
  36. [section .s16]
  37. [bits 16]
  38. ENTRY_SEGMENT:
  39. mov ax, cs
  40. mov ds, ax
  41. mov es, ax
  42. mov ss, ax
  43. mov sp, TopOfStack16
  44. ;
  45. call InitSysMemBuf
  46. ; initialize GDT for 32 bits code segment
  47. mov esi, CODE32_SEGMENT
  48. mov edi, CODE32_DESC
  49. call InitDescItem
  50. mov esi, DATA32_SEGMENT
  51. mov edi, DATA32_DESC
  52. call InitDescItem
  53. mov esi, STACK32_SEGMENT
  54. mov edi, STACK32_DESC
  55. call InitDescItem
  56. ; initalize GDT pointer struct
  57. mov eax, 0
  58. mov ax, ds
  59. shl eax, 4
  60. add eax, GDT_ENTRY
  61. mov dword [GdtPtr + 2], eax
  62. ; 1. load GDT
  63. lgdt [GdtPtr]
  64. ; 2. close interrupt
  65. cli
  66. ; 3. open A20
  67. in al, 0x92
  68. or al, 00000010b
  69. out 0x92, al
  70. ; 4. enter protect mode
  71. mov eax, cr0
  72. or eax, 0x01
  73. mov cr0, eax
  74. ; 5. jump to 32 bits code
  75. jmp dword Code32Selector : 0
  76. ; esi --> code segment labelBACK_ENTRY_SEGMENT
  77. ; edi --> descriptor label
  78. InitDescItem:
  79. push eax
  80. mov eax, 0
  81. mov ax, cs
  82. shl eax, 4
  83. add eax, esi
  84. mov word [edi + 2], ax
  85. shr eax, 16
  86. mov byte [edi + 4], al
  87. mov byte [edi + 7], ah
  88. pop eax
  89. ret
  90. ;
  91. ;
  92. GetMemSize:
  93. push eax
  94. push ebx
  95. push ecx
  96. push edx
  97. mov dword [MEM_SIZE], 0
  98. xor eax, eax
  99. mov eax, 0xE801
  100. int 0x15
  101. jc geterr
  102. mov ecx, 1
  103. shl eax, 10 ; eax = eax * 1024
  104. shl ebx, 6 ; ebx = ebx * 64
  105. shl ebx, 10 ; ebx = ebx * 1024
  106. shl ecx, 20 ; ecx = 1M
  107. add [MEM_SIZE], eax
  108. add [MEM_SIZE], ebx
  109. add [MEM_SIZE], ecx
  110. jmp getok
  111. geterr:
  112. mov dword [MEM_SIZE], 0
  113. getok:
  114. pop edx
  115. pop ecx
  116. pop ebx
  117. pop eax
  118. ret
  119. ; return
  120. ; eax --> 0 : successd 1 : failed
  121. InitSysMemBuf:
  122. push edi
  123. push edx
  124. push ebx
  125. push ecx
  126. mov edi, MEM_ARDS
  127. mov ebx, 0
  128. doloop:
  129. mov eax, 0xE820
  130. mov edx, 0x534D4150
  131. mov ecx, 20
  132. int 0x15
  133. jc memerr
  134. add edi, 20
  135. inc dword [MEM_ARDS_NUM]
  136. cmp ebx, 0
  137. jne doloop
  138. mov eax, 0
  139. jmp memok
  140. memerr:
  141. mov eax, 1
  142. memok:
  143. pop ecx
  144. pop ebx
  145. pop edx
  146. pop edi
  147. ret
  148. [section .s32]
  149. [bits 32]
  150. CODE32_SEGMENT:
  151. mov ax, VideoSelector
  152. mov gs, ax
  153. mov ax, Stack32Selector
  154. mov ss, ax
  155. mov eax, TopOfStack32
  156. mov esp, eax
  157. mov ax, Data32Selector
  158. mov ds, ax
  159. mov ebp, DTOS_Offset
  160. mov bx, 0x0c
  161. mov dh, 13
  162. mov dl, 33
  163. call PrintString
  164. mov ebp, HELLOWORLD_Offset
  165. mov bx, 0x0c
  166. mov dh, 14
  167. mov dl, 30
  168. call PrintString
  169. jmp $
  170. ; ds:ebp --> string address
  171. ; bx --> attribute
  172. ; dx --> dh : row, dl : col
  173. PrintString:
  174. push ebp
  175. push cx
  176. push eax
  177. push dx
  178. push edi
  179. print:
  180. mov cl, [ds:ebp]
  181. cmp cl, 0
  182. je end
  183. mov eax, 80
  184. mul dh
  185. add al, dl
  186. shl eax, 1
  187. mov edi, eax
  188. mov ah, bl
  189. mov al, cl
  190. mov [gs:edi], ax
  191. inc ebp
  192. inc dl
  193. jmp print
  194. end:
  195. pop edi
  196. pop dx
  197. pop eax
  198. pop cx
  199. pop ebp
  200. ret
  201. Code32SegLen equ $ - CODE32_SEGMENT
  202. [section .gs]
  203. [bits 32]
  204. STACK32_SEGMENT:
  205. times 1024 * 4 db 0
  206. Stack32SegLen equ $ - STACK32_SEGMENT
  207. TopOfStack32 equ Stack32SegLen - 1

 第33行我们定义了MEM_ARDS_NUM,MEM_ARDS_NUM表示主机上有多少个段。第34行我们定义了MEM_ARDS,MEM_ARDS为ARDS数组的起始地址,大小我们定义为64个ARDS,每个ARDS为20个字节。

157 - 193行,我们定义了InitSysMemBuf,这个函数利用BIOS提供的 int 0x15 的高级功能来获取主机上所有段的段信息。

第57行,我们通过调用InitSysMemBuf这个函数来获取主机上的所有段信息。

下面我们来进行断点调试

 InitSysMemBuf函数调用前,MEM_ARDS_NUM = 0;InitSysMemBuf函数调用后,eax = 0,说明这个函数没有调用出错,MEM_ARDS_NUM = 6,表明这个主机上一共有6个段。

下面我们来查看这6个段的具体信息

 在查看前6个段的段信息时,它的值不为0。在查看第7个段的段信息,它的值为0,则又说明了这个我们一个查到了6个段。

ARDS记录中并没有包含物理内存容量的信息,那么获取这些记录有什么意义?


ARDS结构体中的TYPE成员

1 - AddressRangeMemory

  • 这段内存可以被操作系统使用

2 - AddressRangeReserved

  • 内存使用中或被保留,操作系统不可用

其他值 - 未定义

  • 保留,可用作 AddressRangeMemory 处理

在32位系统中

ARDS结构体中的 BaseAddrHigh 和 LengthHigh 均为0

物理内存容量需要通过属性为1的内存段计算

计算方式为:max{BaseAddrLow + LengthLow}

  • BaseAddrLow + LengthLow 是一段内存的地址上限

 根据ARDS记录计算物理内存

我们修改了InitSysMemBuf这个函数,如下

  1. ; return
  2. ; eax --> 0 : successd 1 : failed
  3. InitSysMemBuf:
  4. push edi
  5. push edx
  6. push ebx
  7. push ecx
  8. mov edi, MEM_ARDS
  9. mov ebx, 0
  10. doloop:
  11. mov eax, 0xE820
  12. mov edx, 0x534D4150
  13. mov ecx, 20
  14. int 0x15
  15. jc memerr
  16. mov eax, [edi + 16]
  17. cmp eax, 1
  18. jne next
  19. mov eax, [edi]
  20. add eax, [edi + 8]
  21. cmp dword [MEM_SIZE], eax
  22. jnb next
  23. mov dword [MEM_SIZE], eax
  24. next:
  25. add edi, 20
  26. inc dword [MEM_ARDS_NUM]
  27. cmp ebx, 0
  28. jne doloop
  29. mov eax, 0
  30. jmp memok
  31. memerr:
  32. mov eax, 1
  33. memok:
  34. pop ecx
  35. pop ebx
  36. pop edx
  37. pop edi
  38. ret

 TYPE为1表示这段物理内存可被操作系统使用,我们取这段物理内存的最大值,放入MEM_SIZE中。

下面,我们来进行断点调试,查看MEM_SIZE的值

在调用 InitSysMemBuf 之后,MEM_SIZE = 0x01FF0000字节,并不等于我们设置的32M,我们来查看ARDS中的值,来判断我们实现的算法是否存在错误

我们发现TYPE为1的最大物理内存为 0x01FF0000字节,和我们得到的大小是一样的,这样就证明了我们实现的算法并没有出错。

 这里有一个TYPE为3的一个段,大小为0x10000,我们获取到的物理内存加上这个大小就为32M。我们猜想:我们要获得的物理内存大小可能和这个段有关系。

Linux中获取物理内存的策略

 在Linux中,获取物理内存是比对了BIOS中断提供的三种获取物理内存的办法。

 实验中使用的策略

  1. 通过 0xE801 计算物理内存大小
  2. 通过 0xE820 获取各个ARDS 并填入结构体数组
  3. 根据 ARDS 结构体数组计算物理内存大小
  4.  选择计算得到的较大内存容量作为最终结果
  1. %include "inc.asm"
  2. org 0x9000
  3. jmp ENTRY_SEGMENT
  4. [section .gdt]
  5. ; GDT definition
  6. ; 段基址, 段界限, 段属性
  7. GDT_ENTRY : Descriptor 0, 0, 0
  8. CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_32 + DA_C
  9. VIDEO_DESC : Descriptor 0xb8000, 0x7fff, DA_32 + DA_DRWA
  10. DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_32 + DA_DRW
  11. STACK32_DESC : Descriptor 0, TopOfStack32, DA_32 + DA_DRW
  12. SYSDAT32_DESC : Descriptor 0, SysDat32SegLen - 1, DA_32 + DA_DR
  13. ; GDT end
  14. GdtLen equ $ - GDT_ENTRY
  15. GdtPtr:
  16. dw GdtLen - 1
  17. dd 0
  18. ; GDT Selector
  19. Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
  20. VideoSelector equ (0x0002 << 3) + SA_TIG + SA_RPL0
  21. Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL0
  22. Stack32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
  23. SysDat32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
  24. ; end of [section .gdt]
  25. TopOfStack16 equ 0x7c00
  26. [section .sysdat]
  27. SYSDAT32_SEGMENT:
  28. MEM_SIZE times 4 db 0x00 ; int mem_size = 0
  29. MEM_SIZE_OFFSET equ MEM_SIZE - $$
  30. MEM_ARDS_NUM times 4 db 0x00 ; int men_addr_num = 0
  31. MEM_ADDR_NUM_OFFSET equ MEM_ARDS_NUM - $$
  32. MEM_ARDS times 20 * 64 db 0x00 ; ARDS mem_adrs[64] = {0}
  33. MEM_ARDS_OFFSET equ MEM_ARDS - $$
  34. SysDat32SegLen equ $ - SYSDAT32_SEGMENT
  35. [section .d16]
  36. DATA16_SEGMENT:
  37. MEM_ERR_MSG db "[FAILED] memory check error..."
  38. MEM_ERR_MSG_LEN equ $ - MEM_ERR_MSG
  39. Data16SegLen equ $ - DATA16_SEGMENT
  40. [section .dat]
  41. [bits 32]
  42. DATA32_SEGMENT:
  43. DTOS db "D.T.OS!", 0
  44. DTOS_Offset equ DTOS - $$
  45. HELLOWORLD db "Hello, World!", 0
  46. HELLOWORLD_Offset equ HELLOWORLD - $$
  47. Data32SegLen equ $ - DATA32_SEGMENT
  48. [section .s16]
  49. [bits 16]
  50. ENTRY_SEGMENT:
  51. mov ax, cs
  52. mov ds, ax
  53. mov es, ax
  54. mov ss, ax
  55. mov sp, TopOfStack16
  56. ; get system memory information
  57. call InitSysMemBuf
  58. cmp eax, 0
  59. jnz CODE16_MEM_ERROR
  60. ; initialize GDT for 32 bits code segment
  61. mov esi, CODE32_SEGMENT
  62. mov edi, CODE32_DESC
  63. call InitDescItem
  64. mov esi, DATA32_SEGMENT
  65. mov edi, DATA32_DESC
  66. call InitDescItem
  67. mov esi, STACK32_SEGMENT
  68. mov edi, STACK32_DESC
  69. call InitDescItem
  70. mov esi, SYSDAT32_SEGMENT
  71. mov edi, SYSDAT32_DESC
  72. call InitDescItem
  73. ; initalize GDT pointer struct
  74. mov eax, 0
  75. mov ax, ds
  76. shl eax, 4
  77. add eax, GDT_ENTRY
  78. mov dword [GdtPtr + 2], eax
  79. ; 1. load GDT
  80. lgdt [GdtPtr]
  81. ; 2. close interrupt
  82. cli
  83. ; 3. open A20
  84. in al, 0x92
  85. or al, 00000010b
  86. out 0x92, al
  87. ; 4. enter protect mode
  88. mov eax, cr0
  89. or eax, 0x01
  90. mov cr0, eax
  91. ; 5. jump to 32 bits code
  92. jmp dword Code32Selector : 0
  93. CODE16_MEM_ERROR:
  94. mov bp, MEM_ERR_MSG
  95. mov cx, MEM_ERR_MSG_LEN
  96. call Print
  97. jmp $
  98. ; es:bp --> string address
  99. ; cx --> string length
  100. Print:
  101. push ax
  102. push bx
  103. mov dx, 0
  104. mov ax, 0x1301
  105. mov bx, 0x0007
  106. int 0x10
  107. pop bx
  108. pop ax
  109. ret
  110. ; esi --> code segment labelBACK_ENTRY_SEGMENT
  111. ; edi --> descriptor label
  112. InitDescItem:
  113. push eax
  114. mov eax, 0
  115. mov ax, cs
  116. shl eax, 4
  117. add eax, esi
  118. mov word [edi + 2], ax
  119. shr eax, 16
  120. mov byte [edi + 4], al
  121. mov byte [edi + 7], ah
  122. pop eax
  123. ret
  124. ;
  125. ;
  126. GetMemSize:
  127. push eax
  128. push ebx
  129. push ecx
  130. push edx
  131. mov dword [MEM_SIZE], 0
  132. xor eax, eax
  133. mov eax, 0xE801
  134. int 0x15
  135. jc geterr
  136. mov ecx, 1
  137. shl eax, 10 ; eax = eax * 1024
  138. shl ebx, 6 ; ebx = ebx * 64
  139. shl ebx, 10 ; ebx = ebx * 1024
  140. shl ecx, 20 ; ecx = 1M
  141. add [MEM_SIZE], eax
  142. add [MEM_SIZE], ebx
  143. add [MEM_SIZE], ecx
  144. jmp getok
  145. geterr:
  146. mov dword [MEM_SIZE], 0
  147. getok:
  148. pop edx
  149. pop ecx
  150. pop ebx
  151. pop eax
  152. ret
  153. ; return
  154. ; eax --> 0 : successd 1 : failed
  155. InitSysMemBuf:
  156. push edi
  157. push edx
  158. push ebx
  159. push ecx
  160. call GetMemSize
  161. mov edi, MEM_ARDS
  162. mov ebx, 0
  163. doloop:
  164. mov eax, 0xE820
  165. mov edx, 0x534D4150
  166. mov ecx, 20
  167. int 0x15
  168. jc memerr
  169. mov eax, [edi + 16]
  170. cmp eax, 1
  171. jne next
  172. mov eax, [edi]
  173. add eax, [edi + 8]
  174. cmp dword [MEM_SIZE], eax
  175. jnb next
  176. mov dword [MEM_SIZE], eax
  177. next:
  178. add edi, 20
  179. inc dword [MEM_ARDS_NUM]
  180. cmp ebx, 0
  181. jne doloop
  182. mov eax, 0
  183. jmp memok
  184. memerr:
  185. mov eax, 1
  186. mov dword [MEM_SIZE], 0
  187. mov dword [MEM_ARDS_NUM], 0
  188. memok:
  189. pop ecx
  190. pop ebx
  191. pop edx
  192. pop edi
  193. ret
  194. [section .s32]
  195. [bits 32]
  196. CODE32_SEGMENT:
  197. mov ax, VideoSelector
  198. mov gs, ax
  199. mov ax, Stack32Selector
  200. mov ss, ax
  201. mov eax, TopOfStack32
  202. mov esp, eax
  203. mov ax, Data32Selector
  204. mov ds, ax
  205. mov ebp, DTOS_Offset
  206. mov bx, 0x0c
  207. mov dh, 13
  208. mov dl, 33
  209. call PrintString
  210. mov ebp, HELLOWORLD_Offset
  211. mov bx, 0x0c
  212. mov dh, 14
  213. mov dl, 30
  214. call PrintString
  215. jmp $
  216. ; ds:ebp --> string address
  217. ; bx --> attribute
  218. ; dx --> dh : row, dl : col
  219. PrintString:
  220. push ebp
  221. push cx
  222. push eax
  223. push dx
  224. push edi
  225. print:
  226. mov cl, [ds:ebp]
  227. cmp cl, 0
  228. je end
  229. mov eax, 80
  230. mul dh
  231. add al, dl
  232. shl eax, 1
  233. mov edi, eax
  234. mov ah, bl
  235. mov al, cl
  236. mov [gs:edi], ax
  237. inc ebp
  238. inc dl
  239. jmp print
  240. end:
  241. pop edi
  242. pop dx
  243. pop eax
  244. pop cx
  245. pop ebp
  246. ret
  247. Code32SegLen equ $ - CODE32_SEGMENT
  248. [section .gs]
  249. [bits 32]
  250. STACK32_SEGMENT:
  251. times 1024 * 4 db 0
  252. Stack32SegLen equ $ - STACK32_SEGMENT
  253. TopOfStack32 equ Stack32SegLen - 1

我们通过InitSysMemBuf这个函数返回 0xE820 和 0xE801 中较大的物理内存,MEM_SIZE记录了较大的物理内存。

 MEM_SIZE 的值为32M。

我们在16位实模式下新增了 InitSysMemBuf 这个函数的出错处理,我们打印一个出错字符串,我们在241行故意令eax = 1, 查看运行结果。

正确的打印出了出错字符串。

下面我们将有关物理内存大小的数据定义为32位保护模式下的只读数据段,因为系统上电后,一开始是工作在实模式下,进行初始化工作,包括获取物理内存,随后就进入了保护模式,系统大部分时间是运行在保护模式下的。这些数据是系统相关的数据,需要保护起来,并将特权级设为0,只有内核才能访问这段数据。 

  1. %include "inc.asm"
  2. org 0x9000
  3. jmp ENTRY_SEGMENT
  4. [section .gdt]
  5. ; GDT definition
  6. ; 段基址, 段界限, 段属性
  7. GDT_ENTRY : Descriptor 0, 0, 0
  8. CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_32 + DA_C
  9. VIDEO_DESC : Descriptor 0xb8000, 0x7fff, DA_32 + DA_DRWA
  10. DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_32 + DA_DRW
  11. STACK32_DESC : Descriptor 0, TopOfStack32, DA_32 + DA_DRW
  12. SYSDAT32_DESC : Descriptor 0, SysDat32SegLen - 1, DA_32 + DA_DR
  13. ; GDT end
  14. GdtLen equ $ - GDT_ENTRY
  15. GdtPtr:
  16. dw GdtLen - 1
  17. dd 0
  18. ; GDT Selector
  19. Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
  20. VideoSelector equ (0x0002 << 3) + SA_TIG + SA_RPL0
  21. Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL0
  22. Stack32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
  23. SysDat32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
  24. ; end of [section .gdt]
  25. TopOfStack16 equ 0x7c00
  26. [section .sysdat]
  27. SYSDAT32_SEGMENT:
  28. MEM_SIZE times 4 db 0x00 ; int mem_size = 0
  29. MEM_SIZE_OFFSET equ MEM_SIZE - $$
  30. MEM_ARDS_NUM times 4 db 0x00 ; int men_addr_num = 0
  31. MEM_ADDR_NUM_OFFSET equ MEM_ARDS_NUM - $$
  32. MEM_ARDS times 20 * 64 db 0x00 ; ARDS mem_adrs[64] = {0}
  33. MEM_ARDS_OFFSET equ MEM_ARDS - $$
  34. SysDat32SegLen equ $ - SYSDAT32_SEGMENT
  35. [section .d16]
  36. DATA16_SEGMENT:
  37. MEM_ERR_MSG db "[FAILED] memory check error..."
  38. MEM_ERR_MSG_LEN equ $ - MEM_ERR_MSG
  39. Data16SegLen equ $ - DATA16_SEGMENT
  40. [section .dat]
  41. [bits 32]
  42. DATA32_SEGMENT:
  43. DTOS db "D.T.OS!", 0
  44. DTOS_Offset equ DTOS - $$
  45. HELLOWORLD db "Hello, World!", 0
  46. HELLOWORLD_Offset equ HELLOWORLD - $$
  47. Data32SegLen equ $ - DATA32_SEGMENT
  48. [section .s16]
  49. [bits 16]
  50. ENTRY_SEGMENT:
  51. mov ax, cs
  52. mov ds, ax
  53. mov es, ax
  54. mov ss, ax
  55. mov sp, TopOfStack16
  56. ; get system memory information
  57. call InitSysMemBuf
  58. cmp eax, 0
  59. jnz CODE16_MEM_ERROR
  60. ; initialize GDT for 32 bits code segment
  61. mov esi, CODE32_SEGMENT
  62. mov edi, CODE32_DESC
  63. call InitDescItem
  64. mov esi, DATA32_SEGMENT
  65. mov edi, DATA32_DESC
  66. call InitDescItem
  67. mov esi, STACK32_SEGMENT
  68. mov edi, STACK32_DESC
  69. call InitDescItem
  70. mov esi, SYSDAT32_SEGMENT
  71. mov edi, SYSDAT32_DESC
  72. call InitDescItem
  73. ; initalize GDT pointer struct
  74. mov eax, 0
  75. mov ax, ds
  76. shl eax, 4
  77. add eax, GDT_ENTRY
  78. mov dword [GdtPtr + 2], eax
  79. ; 1. load GDT
  80. lgdt [GdtPtr]
  81. ; 2. close interrupt
  82. cli
  83. ; 3. open A20
  84. in al, 0x92
  85. or al, 00000010b
  86. out 0x92, al
  87. ; 4. enter protect mode
  88. mov eax, cr0
  89. or eax, 0x01
  90. mov cr0, eax
  91. ; 5. jump to 32 bits code
  92. jmp dword Code32Selector : 0
  93. CODE16_MEM_ERROR:
  94. mov bp, MEM_ERR_MSG
  95. mov cx, MEM_ERR_MSG_LEN
  96. call Print
  97. jmp $
  98. ; es:bp --> string address
  99. ; cx --> string length
  100. Print:
  101. push ax
  102. push bx
  103. mov dx, 0
  104. mov ax, 0x1301
  105. mov bx, 0x0007
  106. mov eax, 0
  107. jmp memok
  108. int 0x10
  109. pop bx
  110. pop ax
  111. ret
  112. ; esi --> code segment labelBACK_ENTRY_SEGMENT
  113. ; edi --> descriptor label
  114. InitDescItem:
  115. push eax
  116. mov eax, 0
  117. mov ax, cs
  118. shl eax, 4
  119. add eax, esi
  120. mov word [edi + 2], ax
  121. shr eax, 16
  122. mov byte [edi + 4], al
  123. mov byte [edi + 7], ah
  124. pop eax
  125. ret
  126. ;
  127. ;
  128. GetMemSize:
  129. push eax
  130. push ebx
  131. push ecx
  132. push edx
  133. mov dword [MEM_SIZE], 0
  134. xor eax, eax
  135. mov eax, 0xE801
  136. int 0x15
  137. jc geterr
  138. mov ecx, 1
  139. shl eax, 10 ; eax = eax * 1024
  140. shl ebx, 6 ; ebx = ebx * 64
  141. shl ebx, 10 ; ebx = ebx * 1024
  142. shl ecx, 20 ; ecx = 1M
  143. add [MEM_SIZE], eax
  144. add [MEM_SIZE], ebx
  145. add [MEM_SIZE], ecx
  146. jmp getok
  147. geterr:
  148. mov dword [MEM_SIZE], 0
  149. getok:
  150. pop edx
  151. pop ecx
  152. pop ebx
  153. pop eax
  154. ret
  155. ; return
  156. ; eax --> 0 : successd 1 : failed
  157. InitSysMemBuf:
  158. push edi
  159. push edx
  160. push ebx
  161. push ecx
  162. call GetMemSize
  163. mov edi, MEM_ARDS
  164. mov ebx, 0
  165. doloop:
  166. mov eax, 0xE820
  167. mov edx, 0x534D4150
  168. mov ecx, 20
  169. int 0x15
  170. jc memerr
  171. mov eax, [edi + 16]
  172. cmp eax, 1
  173. jne next
  174. mov eax, [edi]
  175. add eax, [edi + 8]
  176. cmp dword [MEM_SIZE], eax
  177. jnb next
  178. mov dword [MEM_SIZE], eax
  179. next:
  180. add edi, 20
  181. inc dword [MEM_ARDS_NUM]
  182. cmp ebx, 0
  183. jne doloop
  184. mov eax, 0
  185. jmp memok
  186. memerr:
  187. mov eax, 1
  188. mov dword [MEM_SIZE], 0
  189. mov dword [MEM_ARDS_NUM], 0
  190. memok:
  191. pop ecx
  192. pop ebx
  193. pop edx
  194. pop edi
  195. ret
  196. [section .s32]
  197. [bits 32]
  198. CODE32_SEGMENT:
  199. mov ax, VideoSelector
  200. mov gs, ax
  201. mov ax, Stack32Selector
  202. mov ss, ax
  203. mov eax, TopOfStack32
  204. mov esp, eax
  205. mov ax, Data32Selector
  206. mov ds, ax
  207. mov ebp, DTOS_Offset
  208. mov bx, 0x0c
  209. mov dh, 13
  210. mov dl, 33
  211. call PrintString
  212. mov ebp, HELLOWORLD_Offset
  213. mov bx, 0x0c
  214. mov dh, 14
  215. mov dl, 30
  216. call PrintString
  217. jmp $
  218. ; ds:ebp --> string address
  219. ; bx --> attribute
  220. ; dx --> dh : row, dl : col
  221. PrintString:
  222. push ebp
  223. push cx
  224. push eax
  225. push dx
  226. push edi
  227. print:
  228. mov cl, [ds:ebp]
  229. cmp cl, 0
  230. je end
  231. mov eax, 80
  232. mul dh
  233. add al, dl
  234. shl eax, 1
  235. mov edi, eax
  236. mov ah, bl
  237. mov al, cl
  238. mov [gs:edi], ax
  239. inc ebp
  240. inc dl
  241. jmp print
  242. end:
  243. pop edi
  244. pop dx
  245. pop eax
  246. pop cx
  247. pop ebp
  248. ret
  249. Code32SegLen equ $ - CODE32_SEGMENT
  250. [section .gs]
  251. [bits 32]
  252. STACK32_SEGMENT:
  253. times 1024 * 4 db 0
  254. Stack32SegLen equ $ - STACK32_SEGMENT
  255. TopOfStack32 equ Stack32SegLen - 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/58735
推荐阅读
相关标签
  

闽ICP备14008679号