首页
社区
课程
招聘
[原创]windows xp下直接写屏试验
发表于: 2010-10-21 17:01 18098

[原创]windows xp下直接写屏试验

2010-10-21 17:01
18098

在dos下可以通过直接填充显示缓冲区,实现快速绘图,在windows下能否实现呢?
windows下一般用户程序运行在ring3下,没法直接读写物理内存,因此只能通过运行在ring0下的驱动来实现。
dos下,图形模式下显示缓冲区的地址是0A000H段,长度只有64k,太小了,跨段操作很麻烦。
在windows下,显卡的显示缓冲区地址是多少?我们打开设备管理器看看,我的机器上显卡型号是GeForce 7050,它占用的资源是:内存范围FD000000-FDFFFFFF D0000000-DFFFFFFF
FC000000-FCFFFFFF  000A0000-000BFFFF,看来dos下0a000段缓冲区还能用,但太小了,每次操作64k很慢,况且也不知道怎么在保护模式下换页,放弃。
剩下的三段中哪一段是和当前屏幕对应的呢?经过试验,D0000000-DFFFFFFF这段就是,是连续的256M,不需要换页。
下面的工作就是写一个小驱动,直接操作这段内存,让屏幕上显示一小幅bmp图片。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (24)
雪    币: 1644
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
用directx吧。
2010-10-21 18:31
0
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
很早就想实现这个功能 ,希望楼主研究好了,告诉我一声
2010-10-21 18:35
0
雪    币: 272
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
win有段显存缓存,操作一般都是在这上面进行的,然后再提交给显卡。

在开启显卡驱动的情况下,000A0000-000BFFFF win就没有用到了,不过还是映射到显存中的,直接操作应该还是有效,只是效率低
2010-10-21 18:36
0
雪    币: 166
活跃值: (84)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
5
试验了两天,已经在1024*768 32位真彩色模式下实现这个功能,以下是小驱动的源码:
;填充显示缓冲区,显示一幅bmp图片的小驱动 作者:盛玉增 (www.aogosoft.com 电子管)
;2010年10月20日 WinXP masm32v8 kmdkit1.8下调试通过。
;@echo off
;goto make
.386
.model flat, stdcall
option casemap:none
include \masm32\include\w2k\ntstatus.inc
include \masm32\include\w2k\ntddk.inc
include \masm32\include\w2k\ntoskrnl.inc
includelib \masm32\lib\w2k\ntoskrnl.lib
.code
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
           pushad
           invoke MmMapIoSpace,0d0000000h,0,4*1024*1024,MmNonCached ;物理地址映射为线性地址,长度4M,返回值在eax
                       cmp eax,0   ;eax==0,失败
                       jz   ta_1
                       cli
                       mov edi,eax    ;eax是显示缓冲区的首地址
                       mov ecx,320    ;共320行,每行240个像素
                       mov esi,offset bmp_2 ;bmp文件中的像素数据开始地址
            ta_2:      push ecx
                       mov ecx,960   ;每像素4个字节,240*4=960,图片一行送显示缓冲区
                       rep movsb
                       add edi,1024*4-960  ;1024*768显示模式
                                           ;320*240的bmp图片,每行占用960个字节
                       pop ecx
                       loop ta_2
                       sti  
            ta_1:
        popad
        mov eax, STATUS_DEVICE_CONFIGURATION_ERROR
        ret

DriverEntry endp;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.data
  ; 以下为bmp格式的320*240的bmp图片文件数据 长度307254 bytes
bmp_1  db 66,77,54,176,4,0,0,0,0,0,54,0,0,0,40,0    ;bmp文件头占用54个字节
  db 0,0,240,0,0,0,64,1,0,0,1,0,32,0,0,0
  db 0,0,0,176,4,0,0,0,0,0,0,0,0,0,0,0
  db 0,0,0,0,0,0
bmp_2 db 229,211,248,0,131,125,242,0,74,103      ;bmp_2为像素数据开始位置,每个像素占用4个字节,顺序为蓝、绿、红、保留,保留字节都为0
  db 248,0,45,88,251,0,40,66,255,0,48,71,247,0,63,103
  db 251,0,67,127,251,0,69,106,252,0,42,68,252,0,31,57
  db 255,0,41,76,250,0,44,86,247,0,41,74,254,0,32,57
  db 255,0,30,53,253,0,21,55,245,0,39,78,255,0,51,102
  db 249,0,43,100,233,0,28,74,239,0,27,63,255,0,24,60
;......数据省略

end DriverEntry

:make

set drv=bmp1

\masm32\bin\ml /nologo /c /coff %drv%.bat
\masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj

del %drv%.obj

echo.
pause
end DriverEntry

:make

set drv=bmp1

\masm32\bin\ml /nologo /c /coff %drv%.bat
\masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj

del %drv%.obj

echo.
pause

图片在屏幕的左上角显示,发现图像是上下颠倒的。原来bmp文件中的数据是从下向上保存的,并不是从左上角到右下角,而是从左下角开始,逐行到最上一行。
为了显示美观,我的图片是事先颠倒过的。
(顺便说一句,图片的作者是云门光影,一个摄影爱好者,版权所有,图片不得用于其它目的,哈哈)
2010-10-21 19:52
0
雪    币: 166
活跃值: (84)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
6
加载这个小驱动用了kmdkit中的beeper中的小程序scp.exe,稍微改了一下。也可以用其它加载驱动的程序,注册这个驱动后,start就能显示图片。
加载驱动的小程序源码如下:
;加载驱动程序的代码 电子管(qq5611409) 2010年10月20日在winxp masm32v8 kmdkit1.8下调试通过
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\advapi32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\advapi32.lib
include \masm32\Macros\Strings.mac
.code
start proc
local hSCManager:HANDLE
local hService:HANDLE
local acDriverPath[MAX_PATH]:CHAR
        invoke OpenSCManager, NULL, NULL, SC_MANAGER_CREATE_SERVICE
        .if eax != NULL
                mov hSCManager, eax
                push eax
                invoke GetFullPathName, $CTA0("bmp1.sys"), sizeof acDriverPath, addr

acDriverPath, esp
            pop eax
                ; Register driver in SCM active database
                invoke CreateService, hSCManager, $CTA0("bemp1"), $CTA0("Nice Melody bmp1"),

\
                                SERVICE_START + DELETE, SERVICE_KERNEL_DRIVER,

SERVICE_DEMAND_START, \
                                SERVICE_ERROR_IGNORE, addr acDriverPath, NULL, NULL, NULL,

NULL, NULL
                .if eax != NULL
                        mov hService, eax
                        invoke StartService, hService, 0, NULL
                        invoke DeleteService, hService
                        invoke CloseServiceHandle, hService
                .else
                        invoke MessageBox, NULL, $CTA0("注册驱动失败."), NULL, MB_ICONSTOP
                .endif
                invoke CloseServiceHandle, hSCManager
        .else
                invoke MessageBox, NULL, $CTA0("Can't connect to Service Control Manager."),

\
                                                        NULL, MB_ICONSTOP
        .endif
        invoke ExitProcess, 0
start endp
end start
2010-10-21 19:58
0
雪    币: 166
活跃值: (84)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
7
这里是编译后的可执行文件,运行时bmp1.exe必须和bmp1.sys在同一个目录下。显示器必须设置成1024*768 32位真彩色模式,其它模式可能花屏,刷新一下就可以恢复原样。
上传的附件:
2010-10-21 20:07
0
雪    币: 242
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
为什么执行文件打包,源码不打包呢?多不方便啊。。。还有这个应当可以用C实现
2010-10-21 20:19
0
雪    币: 166
活跃值: (84)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
9
8楼的朋友真是急性子,本人写的代码太乱,本想把代码整理一下。还是算了吧,自然美吧:-)
下面是所有源码和可执行文件,还有个加载驱动的小工具。
上传的附件:
2010-10-21 20:25
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
这个在xpsp3上没有测试成功。运行后屏幕色彩是全变了。没有出来图,最有可能是的搞坏了调色板。
2010-11-10 16:11
0
雪    币: 166
活跃值: (84)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
11
请注意:显示器必须设置成1024*768 32位真彩色模式,其它模式可能花屏,刷新一下就可以恢复原样。
32位真彩色模式下不牵涉调色板的问题。
2010-11-13 21:31
0
雪    币: 1259
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
stu
12
嗯,不错啊。
2010-11-14 17:09
0
雪    币: 1450
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
rxb
13
这个很经典。。
2010-11-15 17:14
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
我按照lz说的调了分辨率和模式,还是花屏
2010-11-21 09:43
0
雪    币: 166
活跃值: (84)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
15
你用的是我编译好的文件,还是自己编译的?我试验过三台机器,都正常的。
如果你用的是我编译的,显示模式没问题,那我也解释不了这种现象。
2010-11-23 17:25
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
用的编译好的。我自己编译一下驱动。再试试。
2010-11-24 00:41
0
雪    币: 253
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
好贴,楼主好人,我把你的代码用C实现了。
C语言版的,大家可以去下面地址下载。
http://bbs.pediy.com/showthread.php?t=125014
2010-11-24 09:53
0
雪    币: 166
活跃值: (84)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
18
祝贺你,玩开心就好。
2010-11-25 15:47
0
雪    币: 149
活跃值: (101)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
19
向樓主學習了,辛苦辛苦啊
2011-1-5 02:13
0
雪    币: 2307
活跃值: (1013)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
20
我来看大叔表演的
2011-1-5 13:10
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
挺好,支持下。以前一直是用汇编
2011-1-7 11:14
0
雪    币: 16
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
不错,收藏了。
2011-1-19 23:09
0
雪    币: 225
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
好贴,楼主好人,我把你的代码用C实现.
2011-1-21 18:40
0
雪    币: 246
活跃值: (91)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
24
花屏,整个屏幕变成红色...
2011-5-7 23:40
0
雪    币: 145
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
不错,有这个思路很好,一直也想这方面的,那个出现花屏可以是大家的那个显存范围不一样才造成的。不知是不是,我也不有去试一下。
2011-5-8 00:49
0
游客
登录 | 注册 方可回帖
返回
//