你说的不是你自己写的代码是错误的!要使用相同大小的位图填充整个 320x200 256 色屏幕,Y 坐标必须从 199 变为 0。此代码当前从 200 循环到 1,因此从不显示位图的底线。这很容易解决。
当您告诉我们您已将屏幕分辨率更改为 800x600 时,您也应该告诉我们颜色分辨率。在下面的代码中,我假设它是 256 色,就像在示例代码中一样。此外,我将介绍一个使用 LinearFrameBuffer 方法的解决方案。存在窗口化方法,但更困难(当然,如果您不想走太多弯路)。对于不再适合 64KB 图形窗口(800 * 600 = 480000 字节)的视频模式,它将涉及使用 VESA 进行库切换。
但是 320x200 的例子也可以使用 LFB 方法。
视频窗口位于分段地址 0A000h:0000h。这实际上是线性地址 000A0000h。
; On entry BX is handle for the file with filepointer at bitmap data!!!
proc CopyBitmap
; BMP graphics are saved upside-down.
; Read the graphic line by line (200 lines in VGA format),
; displaying the lines from bottom to top.
push es
xor ax, ax
mov es, ax
mov cx, 200
PrintBMPLoop:
push cx
; Point to the correct screen line
dec cx ; Y ranging from 199 to 0
movzx edi, cx
imul edi, 320
add edi, 000A0000h
; Read one line
mov dx, offset ScrLine
mov cx, 320
mov ah, 3Fh ; DOS.ReadFile
int 21h
jc WhatIfError?
cmp ax, cx
jne WhatIfError?
; Copy one line into video memory
mov si, dx
add dx, cx ; DX now points to the end of the buffer
CopyLoop:
lodsd ; Load 4 pixels together
stosd [edi] ; This generates an AddressSizePrefix
cmp si, dx
jb CopyLoop
pop cx
loop PrintBMPLoop
pop es
ret
endp CopyBitmap
和800x600的代码很相似。
您可以通过检查 VESA 4F01h ReturnVBEModeInformation 函数的结果获得 BytesPerScanLine 值和 LinearFrameBuffer 地址。
- ModeInfoBlock PhysBasePtr (dword) 的偏移量 +40
- ModeInfoBlock LinBytesPerScanLine 的偏移量 +50(字)
BytesPerScanLine 值不必是 800。图形环境可能很容易选择 1024 作为更合理的值。你需要检查而不是假设。
; On entry BX is handle for the file with filepointer at bitmap data!!!
proc CopyBitmap
; BMP graphics are saved upside-down.
; Read the graphic line by line (600 lines in SVGA format),
; displaying the lines from bottom to top.
push es
xor ax, ax
mov es, ax
mov cx, 600
PrintBMPLoop:
push cx
; Point to the correct screen line
dec cx ; Y ranging from 599 to 0
movzx edi, cx
imul edi, BytesPerScanLine
add edi, LinearFrameBuffer
; Read one line
mov dx, offset ScrLine
mov cx, 800
mov ah, 3Fh ; DOS.ReadFile
int 21h
jc WhatIfError?
cmp ax, cx
jne WhatIfError?
; Copy one line into video memory
mov si, dx
add dx, cx ; DX now points to the end of the buffer
CopyLoop:
lodsd ; Load 4 pixels together
stosd [edi] ; This generates an AddressSizePrefix
cmp si, dx
jb CopyLoop
pop cx
loop PrintBMPLoop
pop es
ret
endp CopyBitmap