OS开发:在Netwide Assembler(NASM)中获取图形模式屏幕分辨率
获取实模式图形模式下的屏幕分辨率与逐行填充实现
一、获取屏幕分辨率的方法
1. 传统VGA固定模式(如0x13模式)
如果使用标准VGA图形模式(比如320×200 256色的模式0x13),这类模式的分辨率是固定的,可直接硬编码。若需动态确认,可通过BIOS中断获取当前模式信息:
- 调用
int 0x10,功能号AH=0x0F:- 返回
AH为当前视频模式编号 - 根据模式编号查表即可得到对应分辨率(比如模式0x13对应320×200)
- 返回
2. VBE扩展模式(支持高分辨率)
若需使用更高分辨率的图形模式(如640×480、800×600等),需借助VESA BIOS Extensions (VBE) 获取参数:
- 先调用
int 0x10,AX=0x4F00,获取VBE控制器信息,其中包含支持的模式列表 - 再调用
int 0x10,AX=0x4F01,传入目标模式编号,获取该模式的详细参数(含宽度、高度、位深等)
以下是获取当前VBE模式分辨率的NASM代码片段:
; 定义VBE模式信息结构体 struc VbeModeInfo .ModeAttr resw 1 .WinAAtttr resb 1 .WinBAttr resb 1 .WinGranularity resw 1 .WinSize resw 1 .WinASegment resw 1 .WinBSegment resw 1 .WinFuncPtr resd 1 .BytesPerScanLine resw 1 .XResolution resw 1 .YResolution resw 1 .XCharSize resb 1 .YCharSize resb 1 .NumberOfPlanes resb 1 .BitsPerPixel resb 1 .NumberOfBanks resb 1 .MemoryModel resb 1 .BankSize resb 1 .NumberOfImagePages resb 1 .Reserved0 resb 1 .RedMaskSize resb 1 .RedFieldPos resb 1 .GreenMaskSize resb 1 .GreenFieldPos resb 1 .BlueMaskSize resb 1 .BlueFieldPos resb 1 .RsvdMaskSize resb 1 .RsvdFieldPos resb 1 .DirectColorModeInfo resb 1 .PhysBasePtr resd 1 .Reserved1 resd 1 .Reserved2 resw 1 .Reserved3 resb 1 .LinearBytesPerScanLine resw 1 .BanksPerImage resb 1 .Reserved4 resb 3 .Reserved5 resd 1 .Reserved6 resd 1 .Reserved7 resb 16 endstruc ; 获取当前VBE模式的分辨率 get_vbe_resolution: pusha mov ax, 0x4F01 ; VBE功能:获取模式信息 mov cx, 0x101 ; 示例模式:640×480 256色,可替换为实际使用的模式号 mov di, vbe_mode_info int 0x10 ; 检查返回值,AH=0表示调用成功 cmp ah, 0 jne .error ; 分辨率存储在vbe_mode_info.XResolution(宽度)和.YResolution(高度)中 mov ax, [vbe_mode_info + VbeModeInfo.XResolution] mov bx, [vbe_mode_info + VbeModeInfo.YResolution] ; 此处可将AX、BX的值保存到内存或寄存器供后续使用 jmp .done .error: ; 调用失败时的 fallback 处理,比如切换到传统VGA模式 .done: popa ret section .bss vbe_mode_info resb VbeModeInfo_size
二、逐行填充屏幕的实现
以传统VGA模式0x13(320×200 256色)为例,显示内存起始地址为0xA0000,每个字节对应一个像素的颜色值。逐行填充只需按行遍历显示内存,每行写入对应数量的像素值:
; 设置VGA图形模式0x13 set_video_mode: mov ah, 0x00 mov al, 0x13 int 0x10 ret ; 逐行填充屏幕,颜色值存于BL中 fill_screen_rowwise: pusha mov ax, 0xA000 mov es, ax ; ES指向显示内存段 xor di, di ; DI初始化为0,指向显示内存起始位置 mov cx, 200 ; 总行数(Y分辨率) .fill_row: mov dx, 320 ; 每行像素数(X分辨率) mov al, bl ; 要填充的颜色值 rep stosb ; 填充一行320个像素 loop .fill_row ; 处理下一行 popa ret ; 主引导扇区代码 section .text org 0x7C00 start: call set_video_mode mov bl, 0x0F ; 256色模式下的白色值 call fill_screen_rowwise jmp $ ; 无限循环 ; 填充引导扇区到512字节 times 510 - ($ - $$) db 0 dw 0xAA55
如果使用VBE线性帧缓冲模式,只需将显示内存地址替换为vbe_mode_info.PhysBasePtr,再根据XResolution、YResolution和位深计算每行字节数(比如24位色每行字节数=宽度×3),即可按相同逻辑逐行填充。
注意事项
- Bochs默认支持VBE,可在配置文件中添加
vga: extension=vbe确保功能正常 - 不同图形模式的显示内存布局不同,需根据模式参数调整填充逻辑
- 实模式下内存寻址限制为1MB,高分辨率模式可能需要使用分页或段切换(若显示内存超过1MB)
内容的提问来源于stack exchange,提问作者user1234
相关产品推荐
相关产品推荐

