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


- %include "inc.asm"
-
- org 0x9000
-
- jmp ENTRY_SEGMENT
-
- [section .gdt]
- ; GDT definition
- ; 段基址, 段界限, 段属性
- GDT_ENTRY : Descriptor 0, 0, 0
- CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_32 + DA_C
- VIDEO_DESC : Descriptor 0xb8000, 0x7fff, DA_32 + DA_DRWA
- DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_32 + DA_DRW
- STACK32_DESC : Descriptor 0, TopOfStack32, DA_32 + DA_DRW
- ; GDT end
-
- GdtLen equ $ - GDT_ENTRY
- GdtPtr:
- dw GdtLen - 1
- dd 0
-
- ; GDT Selector
- Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
- VideoSelector equ (0x0002 << 3) + SA_TIG + SA_RPL0
- Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL0
- Stack32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
- ; end of [section .gdt]
-
- TopOfStack16 equ 0x7c00
-
- ; get hardware memory infomation
- MEM_SIZE times 4 db 0x00 ; int mem_size = 0
- MEM_ARDS_NUM times 4 db 0x00 ; int men_addr_num = 0
- MEM_ARDS times 20 * 64 db 0x00 ; ARDS mem_adrs[64] = {0}
-
- [section .dat]
- [bits 32]
- DATA32_SEGMENT:
- DTOS db "D.T.OS!", 0
- DTOS_Offset equ DTOS - $$
-
- HELLOWORLD db "Hello, World!", 0
- HELLOWORLD_Offset equ HELLOWORLD - $$
-
- Data32SegLen equ $ - DATA32_SEGMENT
-
- [section .s16]
- [bits 16]
- ENTRY_SEGMENT:
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov sp, TopOfStack16
-
- ;
- call InitSysMemBuf
-
- ; initialize GDT for 32 bits code segment
- mov esi, CODE32_SEGMENT
- mov edi, CODE32_DESC
- call InitDescItem
-
- mov esi, DATA32_SEGMENT
- mov edi, DATA32_DESC
- call InitDescItem
-
- mov esi, STACK32_SEGMENT
- mov edi, STACK32_DESC
- call InitDescItem
-
- ; initalize GDT pointer struct
- mov eax, 0
- mov ax, ds
- shl eax, 4
- add eax, GDT_ENTRY
- mov dword [GdtPtr + 2], eax
-
- ; 1. load GDT
- lgdt [GdtPtr]
-
- ; 2. close interrupt
- cli
-
- ; 3. open A20
- in al, 0x92
- or al, 00000010b
- out 0x92, al
-
- ; 4. enter protect mode
- mov eax, cr0
- or eax, 0x01
- mov cr0, eax
-
- ; 5. jump to 32 bits code
- jmp dword Code32Selector : 0
-
-
- ; esi --> code segment labelBACK_ENTRY_SEGMENT
- ; edi --> descriptor label
- InitDescItem:
- push eax
-
- mov eax, 0
- mov ax, cs
- shl eax, 4
- add eax, esi
- mov word [edi + 2], ax
- shr eax, 16
- mov byte [edi + 4], al
- mov byte [edi + 7], ah
-
- pop eax
-
- ret
-
- ;
- ;
- GetMemSize:
- push eax
- push ebx
- push ecx
- push edx
-
- mov dword [MEM_SIZE], 0
-
- xor eax, eax
- mov eax, 0xE801
- int 0x15
-
- jc geterr
-
- mov ecx, 1
-
- shl eax, 10 ; eax = eax * 1024
- shl ebx, 6 ; ebx = ebx * 64
- shl ebx, 10 ; ebx = ebx * 1024
- shl ecx, 20 ; ecx = 1M
-
- add [MEM_SIZE], eax
- add [MEM_SIZE], ebx
- add [MEM_SIZE], ecx
-
- jmp getok
-
- geterr:
- mov dword [MEM_SIZE], 0
-
- getok:
- pop edx
- pop ecx
- pop ebx
- pop eax
-
- ret
-
- ; return
- ; eax --> 0 : successd 1 : failed
- InitSysMemBuf:
- push edi
- push edx
- push ebx
- push ecx
-
- mov edi, MEM_ARDS
- mov ebx, 0
-
- doloop:
- mov eax, 0xE820
- mov edx, 0x534D4150
- mov ecx, 20
- int 0x15
-
- jc memerr
-
- add edi, 20
- inc dword [MEM_ARDS_NUM]
-
- cmp ebx, 0
- jne doloop
-
- mov eax, 0
- jmp memok
-
- memerr:
- mov eax, 1
-
- memok:
- pop ecx
- pop ebx
- pop edx
- pop edi
-
- ret
-
- [section .s32]
- [bits 32]
- CODE32_SEGMENT:
- mov ax, VideoSelector
- mov gs, ax
-
- mov ax, Stack32Selector
- mov ss, ax
-
- mov eax, TopOfStack32
- mov esp, eax
-
- mov ax, Data32Selector
- mov ds, ax
-
- mov ebp, DTOS_Offset
- mov bx, 0x0c
- mov dh, 13
- mov dl, 33
- call PrintString
-
- mov ebp, HELLOWORLD_Offset
- mov bx, 0x0c
- mov dh, 14
- mov dl, 30
- call PrintString
-
-
- jmp $
-
- ; ds:ebp --> string address
- ; bx --> attribute
- ; dx --> dh : row, dl : col
- PrintString:
- push ebp
- push cx
- push eax
- push dx
- push edi
-
- print:
- mov cl, [ds:ebp]
- cmp cl, 0
- je end
- mov eax, 80
- mul dh
- add al, dl
- shl eax, 1
- mov edi, eax
- mov ah, bl
- mov al, cl
- mov [gs:edi], ax
- inc ebp
- inc dl
- jmp print
-
- end:
- pop edi
- pop dx
- pop eax
- pop cx
- pop ebp
-
- ret
-
- Code32SegLen equ $ - CODE32_SEGMENT
-
-
- [section .gs]
- [bits 32]
- STACK32_SEGMENT:
- times 1024 * 4 db 0
-
- Stack32SegLen equ $ - STACK32_SEGMENT
- 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记录中并没有包含物理内存容量的信息,那么获取这些记录有什么意义?
1 - AddressRangeMemory
2 - AddressRangeReserved
其他值 - 未定义
ARDS结构体中的 BaseAddrHigh 和 LengthHigh 均为0
物理内存容量需要通过属性为1的内存段计算
计算方式为:max{BaseAddrLow + LengthLow}


我们修改了InitSysMemBuf这个函数,如下
- ; return
- ; eax --> 0 : successd 1 : failed
- InitSysMemBuf:
- push edi
- push edx
- push ebx
- push ecx
-
- mov edi, MEM_ARDS
- mov ebx, 0
-
- doloop:
- mov eax, 0xE820
- mov edx, 0x534D4150
- mov ecx, 20
- int 0x15
-
- jc memerr
-
- mov eax, [edi + 16]
- cmp eax, 1
- jne next
-
- mov eax, [edi]
- add eax, [edi + 8]
- cmp dword [MEM_SIZE], eax
- jnb next
-
- mov dword [MEM_SIZE], eax
-
- next:
- add edi, 20
- inc dword [MEM_ARDS_NUM]
-
- cmp ebx, 0
- jne doloop
-
- mov eax, 0
- jmp memok
-
- memerr:
- mov eax, 1
-
- memok:
- pop ecx
- pop ebx
- pop edx
- pop edi
-
- ret

TYPE为1表示这段物理内存可被操作系统使用,我们取这段物理内存的最大值,放入MEM_SIZE中。
下面,我们来进行断点调试,查看MEM_SIZE的值

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

我们发现TYPE为1的最大物理内存为 0x01FF0000字节,和我们得到的大小是一样的,这样就证明了我们实现的算法并没有出错。
这里有一个TYPE为3的一个段,大小为0x10000,我们获取到的物理内存加上这个大小就为32M。我们猜想:我们要获得的物理内存大小可能和这个段有关系。

在Linux中,获取物理内存是比对了BIOS中断提供的三种获取物理内存的办法。
- %include "inc.asm"
-
- org 0x9000
-
- jmp ENTRY_SEGMENT
-
- [section .gdt]
- ; GDT definition
- ; 段基址, 段界限, 段属性
- GDT_ENTRY : Descriptor 0, 0, 0
- CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_32 + DA_C
- VIDEO_DESC : Descriptor 0xb8000, 0x7fff, DA_32 + DA_DRWA
- DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_32 + DA_DRW
- STACK32_DESC : Descriptor 0, TopOfStack32, DA_32 + DA_DRW
- SYSDAT32_DESC : Descriptor 0, SysDat32SegLen - 1, DA_32 + DA_DR
- ; GDT end
-
- GdtLen equ $ - GDT_ENTRY
- GdtPtr:
- dw GdtLen - 1
- dd 0
-
- ; GDT Selector
- Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
- VideoSelector equ (0x0002 << 3) + SA_TIG + SA_RPL0
- Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL0
- Stack32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
- SysDat32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
- ; end of [section .gdt]
-
- TopOfStack16 equ 0x7c00
-
- [section .sysdat]
- SYSDAT32_SEGMENT:
- MEM_SIZE times 4 db 0x00 ; int mem_size = 0
- MEM_SIZE_OFFSET equ MEM_SIZE - $$
- MEM_ARDS_NUM times 4 db 0x00 ; int men_addr_num = 0
- MEM_ADDR_NUM_OFFSET equ MEM_ARDS_NUM - $$
- MEM_ARDS times 20 * 64 db 0x00 ; ARDS mem_adrs[64] = {0}
- MEM_ARDS_OFFSET equ MEM_ARDS - $$
-
- SysDat32SegLen equ $ - SYSDAT32_SEGMENT
-
- [section .d16]
- DATA16_SEGMENT:
- MEM_ERR_MSG db "[FAILED] memory check error..."
- MEM_ERR_MSG_LEN equ $ - MEM_ERR_MSG
-
- Data16SegLen equ $ - DATA16_SEGMENT
-
- [section .dat]
- [bits 32]
- DATA32_SEGMENT:
- DTOS db "D.T.OS!", 0
- DTOS_Offset equ DTOS - $$
-
- HELLOWORLD db "Hello, World!", 0
- HELLOWORLD_Offset equ HELLOWORLD - $$
-
- Data32SegLen equ $ - DATA32_SEGMENT
-
- [section .s16]
- [bits 16]
- ENTRY_SEGMENT:
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov sp, TopOfStack16
-
- ; get system memory information
- call InitSysMemBuf
-
- cmp eax, 0
- jnz CODE16_MEM_ERROR
-
- ; initialize GDT for 32 bits code segment
- mov esi, CODE32_SEGMENT
- mov edi, CODE32_DESC
- call InitDescItem
-
- mov esi, DATA32_SEGMENT
- mov edi, DATA32_DESC
- call InitDescItem
-
- mov esi, STACK32_SEGMENT
- mov edi, STACK32_DESC
- call InitDescItem
-
- mov esi, SYSDAT32_SEGMENT
- mov edi, SYSDAT32_DESC
- call InitDescItem
-
- ; initalize GDT pointer struct
- mov eax, 0
- mov ax, ds
- shl eax, 4
- add eax, GDT_ENTRY
- mov dword [GdtPtr + 2], eax
-
- ; 1. load GDT
- lgdt [GdtPtr]
-
- ; 2. close interrupt
- cli
-
- ; 3. open A20
- in al, 0x92
- or al, 00000010b
- out 0x92, al
-
- ; 4. enter protect mode
- mov eax, cr0
- or eax, 0x01
- mov cr0, eax
-
- ; 5. jump to 32 bits code
- jmp dword Code32Selector : 0
-
- CODE16_MEM_ERROR:
- mov bp, MEM_ERR_MSG
- mov cx, MEM_ERR_MSG_LEN
- call Print
-
- jmp $
-
- ; es:bp --> string address
- ; cx --> string length
- Print:
- push ax
- push bx
-
- mov dx, 0
- mov ax, 0x1301
- mov bx, 0x0007
-
- int 0x10
-
- pop bx
- pop ax
-
- ret
-
- ; esi --> code segment labelBACK_ENTRY_SEGMENT
- ; edi --> descriptor label
- InitDescItem:
- push eax
-
- mov eax, 0
- mov ax, cs
- shl eax, 4
- add eax, esi
- mov word [edi + 2], ax
- shr eax, 16
- mov byte [edi + 4], al
- mov byte [edi + 7], ah
-
- pop eax
-
- ret
-
- ;
- ;
- GetMemSize:
- push eax
- push ebx
- push ecx
- push edx
-
- mov dword [MEM_SIZE], 0
-
- xor eax, eax
- mov eax, 0xE801
- int 0x15
-
- jc geterr
-
- mov ecx, 1
-
- shl eax, 10 ; eax = eax * 1024
- shl ebx, 6 ; ebx = ebx * 64
- shl ebx, 10 ; ebx = ebx * 1024
- shl ecx, 20 ; ecx = 1M
-
- add [MEM_SIZE], eax
- add [MEM_SIZE], ebx
- add [MEM_SIZE], ecx
-
- jmp getok
-
- geterr:
- mov dword [MEM_SIZE], 0
-
- getok:
- pop edx
- pop ecx
- pop ebx
- pop eax
-
- ret
-
- ; return
- ; eax --> 0 : successd 1 : failed
- InitSysMemBuf:
- push edi
- push edx
- push ebx
- push ecx
-
- call GetMemSize
-
- mov edi, MEM_ARDS
- mov ebx, 0
-
- doloop:
- mov eax, 0xE820
- mov edx, 0x534D4150
- mov ecx, 20
- int 0x15
-
- jc memerr
-
- mov eax, [edi + 16]
- cmp eax, 1
- jne next
-
- mov eax, [edi]
- add eax, [edi + 8]
- cmp dword [MEM_SIZE], eax
- jnb next
-
- mov dword [MEM_SIZE], eax
-
- next:
- add edi, 20
- inc dword [MEM_ARDS_NUM]
-
- cmp ebx, 0
- jne doloop
-
- mov eax, 0
- jmp memok
-
- memerr:
- mov eax, 1
- mov dword [MEM_SIZE], 0
- mov dword [MEM_ARDS_NUM], 0
-
- memok:
- pop ecx
- pop ebx
- pop edx
- pop edi
-
- ret
-
- [section .s32]
- [bits 32]
- CODE32_SEGMENT:
- mov ax, VideoSelector
- mov gs, ax
-
- mov ax, Stack32Selector
- mov ss, ax
-
- mov eax, TopOfStack32
- mov esp, eax
-
- mov ax, Data32Selector
- mov ds, ax
-
- mov ebp, DTOS_Offset
- mov bx, 0x0c
- mov dh, 13
- mov dl, 33
- call PrintString
-
- mov ebp, HELLOWORLD_Offset
- mov bx, 0x0c
- mov dh, 14
- mov dl, 30
- call PrintString
-
-
- jmp $
-
- ; ds:ebp --> string address
- ; bx --> attribute
- ; dx --> dh : row, dl : col
- PrintString:
- push ebp
- push cx
- push eax
- push dx
- push edi
-
- print:
- mov cl, [ds:ebp]
- cmp cl, 0
- je end
- mov eax, 80
- mul dh
- add al, dl
- shl eax, 1
- mov edi, eax
- mov ah, bl
- mov al, cl
- mov [gs:edi], ax
- inc ebp
- inc dl
- jmp print
-
- end:
- pop edi
- pop dx
- pop eax
- pop cx
- pop ebp
-
- ret
-
- Code32SegLen equ $ - CODE32_SEGMENT
-
-
- [section .gs]
- [bits 32]
- STACK32_SEGMENT:
- times 1024 * 4 db 0
-
- Stack32SegLen equ $ - STACK32_SEGMENT
- TopOfStack32 equ Stack32SegLen - 1

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

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

正确的打印出了出错字符串。
下面我们将有关物理内存大小的数据定义为32位保护模式下的只读数据段,因为系统上电后,一开始是工作在实模式下,进行初始化工作,包括获取物理内存,随后就进入了保护模式,系统大部分时间是运行在保护模式下的。这些数据是系统相关的数据,需要保护起来,并将特权级设为0,只有内核才能访问这段数据。
- %include "inc.asm"
-
- org 0x9000
-
- jmp ENTRY_SEGMENT
-
- [section .gdt]
- ; GDT definition
- ; 段基址, 段界限, 段属性
- GDT_ENTRY : Descriptor 0, 0, 0
- CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_32 + DA_C
- VIDEO_DESC : Descriptor 0xb8000, 0x7fff, DA_32 + DA_DRWA
- DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_32 + DA_DRW
- STACK32_DESC : Descriptor 0, TopOfStack32, DA_32 + DA_DRW
- SYSDAT32_DESC : Descriptor 0, SysDat32SegLen - 1, DA_32 + DA_DR
- ; GDT end
-
- GdtLen equ $ - GDT_ENTRY
- GdtPtr:
- dw GdtLen - 1
- dd 0
-
- ; GDT Selector
- Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
- VideoSelector equ (0x0002 << 3) + SA_TIG + SA_RPL0
- Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL0
- Stack32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
- SysDat32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0
- ; end of [section .gdt]
-
- TopOfStack16 equ 0x7c00
-
- [section .sysdat]
- SYSDAT32_SEGMENT:
- MEM_SIZE times 4 db 0x00 ; int mem_size = 0
- MEM_SIZE_OFFSET equ MEM_SIZE - $$
- MEM_ARDS_NUM times 4 db 0x00 ; int men_addr_num = 0
- MEM_ADDR_NUM_OFFSET equ MEM_ARDS_NUM - $$
- MEM_ARDS times 20 * 64 db 0x00 ; ARDS mem_adrs[64] = {0}
- MEM_ARDS_OFFSET equ MEM_ARDS - $$
-
- SysDat32SegLen equ $ - SYSDAT32_SEGMENT
-
- [section .d16]
- DATA16_SEGMENT:
- MEM_ERR_MSG db "[FAILED] memory check error..."
- MEM_ERR_MSG_LEN equ $ - MEM_ERR_MSG
-
- Data16SegLen equ $ - DATA16_SEGMENT
-
- [section .dat]
- [bits 32]
- DATA32_SEGMENT:
- DTOS db "D.T.OS!", 0
- DTOS_Offset equ DTOS - $$
-
- HELLOWORLD db "Hello, World!", 0
- HELLOWORLD_Offset equ HELLOWORLD - $$
-
- Data32SegLen equ $ - DATA32_SEGMENT
-
- [section .s16]
- [bits 16]
- ENTRY_SEGMENT:
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov sp, TopOfStack16
-
- ; get system memory information
- call InitSysMemBuf
-
- cmp eax, 0
- jnz CODE16_MEM_ERROR
-
- ; initialize GDT for 32 bits code segment
- mov esi, CODE32_SEGMENT
- mov edi, CODE32_DESC
- call InitDescItem
-
- mov esi, DATA32_SEGMENT
- mov edi, DATA32_DESC
- call InitDescItem
-
- mov esi, STACK32_SEGMENT
- mov edi, STACK32_DESC
- call InitDescItem
-
- mov esi, SYSDAT32_SEGMENT
- mov edi, SYSDAT32_DESC
- call InitDescItem
-
- ; initalize GDT pointer struct
- mov eax, 0
- mov ax, ds
- shl eax, 4
- add eax, GDT_ENTRY
- mov dword [GdtPtr + 2], eax
-
- ; 1. load GDT
- lgdt [GdtPtr]
-
- ; 2. close interrupt
- cli
-
- ; 3. open A20
- in al, 0x92
- or al, 00000010b
- out 0x92, al
-
- ; 4. enter protect mode
- mov eax, cr0
- or eax, 0x01
- mov cr0, eax
-
- ; 5. jump to 32 bits code
- jmp dword Code32Selector : 0
-
- CODE16_MEM_ERROR:
- mov bp, MEM_ERR_MSG
- mov cx, MEM_ERR_MSG_LEN
- call Print
-
- jmp $
-
- ; es:bp --> string address
- ; cx --> string length
- Print:
- push ax
- push bx
-
- mov dx, 0
- mov ax, 0x1301
- mov bx, 0x0007
- mov eax, 0
- jmp memok
-
- int 0x10
-
- pop bx
- pop ax
-
- ret
-
- ; esi --> code segment labelBACK_ENTRY_SEGMENT
- ; edi --> descriptor label
- InitDescItem:
- push eax
-
- mov eax, 0
- mov ax, cs
- shl eax, 4
- add eax, esi
- mov word [edi + 2], ax
- shr eax, 16
- mov byte [edi + 4], al
- mov byte [edi + 7], ah
-
- pop eax
-
- ret
-
- ;
- ;
- GetMemSize:
- push eax
- push ebx
- push ecx
- push edx
-
- mov dword [MEM_SIZE], 0
-
- xor eax, eax
- mov eax, 0xE801
- int 0x15
-
- jc geterr
-
- mov ecx, 1
-
- shl eax, 10 ; eax = eax * 1024
- shl ebx, 6 ; ebx = ebx * 64
- shl ebx, 10 ; ebx = ebx * 1024
- shl ecx, 20 ; ecx = 1M
-
- add [MEM_SIZE], eax
- add [MEM_SIZE], ebx
- add [MEM_SIZE], ecx
-
- jmp getok
-
- geterr:
- mov dword [MEM_SIZE], 0
-
- getok:
- pop edx
- pop ecx
- pop ebx
- pop eax
-
- ret
-
- ; return
- ; eax --> 0 : successd 1 : failed
- InitSysMemBuf:
- push edi
- push edx
- push ebx
- push ecx
-
- call GetMemSize
-
- mov edi, MEM_ARDS
- mov ebx, 0
-
- doloop:
- mov eax, 0xE820
- mov edx, 0x534D4150
- mov ecx, 20
- int 0x15
-
- jc memerr
-
- mov eax, [edi + 16]
- cmp eax, 1
- jne next
-
- mov eax, [edi]
- add eax, [edi + 8]
- cmp dword [MEM_SIZE], eax
- jnb next
-
- mov dword [MEM_SIZE], eax
-
- next:
- add edi, 20
- inc dword [MEM_ARDS_NUM]
-
- cmp ebx, 0
- jne doloop
-
- mov eax, 0
- jmp memok
-
- memerr:
- mov eax, 1
- mov dword [MEM_SIZE], 0
- mov dword [MEM_ARDS_NUM], 0
-
- memok:
- pop ecx
- pop ebx
- pop edx
- pop edi
-
- ret
-
- [section .s32]
- [bits 32]
- CODE32_SEGMENT:
- mov ax, VideoSelector
- mov gs, ax
-
- mov ax, Stack32Selector
- mov ss, ax
-
- mov eax, TopOfStack32
- mov esp, eax
-
- mov ax, Data32Selector
- mov ds, ax
-
- mov ebp, DTOS_Offset
- mov bx, 0x0c
- mov dh, 13
- mov dl, 33
- call PrintString
-
- mov ebp, HELLOWORLD_Offset
- mov bx, 0x0c
- mov dh, 14
- mov dl, 30
- call PrintString
-
-
- jmp $
-
- ; ds:ebp --> string address
- ; bx --> attribute
- ; dx --> dh : row, dl : col
- PrintString:
- push ebp
- push cx
- push eax
- push dx
- push edi
-
- print:
- mov cl, [ds:ebp]
- cmp cl, 0
- je end
- mov eax, 80
- mul dh
- add al, dl
- shl eax, 1
- mov edi, eax
- mov ah, bl
- mov al, cl
- mov [gs:edi], ax
- inc ebp
- inc dl
- jmp print
-
- end:
- pop edi
- pop dx
- pop eax
- pop cx
- pop ebp
-
- ret
-
- Code32SegLen equ $ - CODE32_SEGMENT
-
-
- [section .gs]
- [bits 32]
- STACK32_SEGMENT:
- times 1024 * 4 db 0
-
- Stack32SegLen equ $ - STACK32_SEGMENT
- TopOfStack32 equ Stack32SegLen - 1

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。