| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1475 人关注过本帖
标题:问题来了。第九章,NMHDR.code 怎么会编译成常量?
只看楼主 加入收藏
okayyyy
Rank: 2
等 级:论坛游民
威 望:2
帖 子:102
专家分:70
注 册:2010-6-15
结帖率:81.82%
收藏
已结贴  问题点数:20 回复次数:12 
问题来了。第九章,NMHDR.code 怎么会编译成常量?
能给点提示吗?
我想来想去,也没记起在哪里碰到过

呵呵,我用老罗的FindFile.exe跟dir *.*/s比较了下。  还是DOS命令快几秒

[ 本帖最后由 okayyyy 于 2010-7-24 06:38 编辑 ]
搜索更多相关主题的帖子: 常量 NMHDR code 编译 
2010-07-24 03:14
东海一鱼
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:48
帖 子:757
专家分:4760
注 册:2009-8-10
收藏
得分:10 
没看过老罗的书,不知道它的这个NMHDR.code 是怎莫赋值的?
不过正常情况下这个NMHDR.code 应该就是WM_NOTIFY消息中WPARAM的高字。

老罗的FindFile.exe跟dir *.*/s比较了下。  还是DOS命令快几秒

这个比较,我想没有什莫意义吧。因为这里的速度只跟算法有关。NT的文件搜索貌似用的树算法,
而老罗估计用的是最普通的递归方式。

举世而誉之而不加劝,举世而非之而不加沮,定乎内外之分,辩乎荣辱之境,斯已矣。彼其于世未数数然也。
2010-07-24 10:36
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:10 
NMHDR STRUCT
    hwndFrom    DWORD ?
    idFrom      DWORD ?
    code        DWORD ?
NMHDR ends

不要被小写的code迷惑 这里就这么定义的(一般结构里面都大写 不知道这个为啥这样。。。)

我就用书里的内容回答你

3.3.4  数据结构

数据结构实际上是由多个字段组成的数据“样板”,相当于一种自定义的数据类型,数据结构中间的每一个字段可以是字节、字、双字、字符串或所有可能的数据类型。比如在API函数RegisterClass中要使用到一个叫做WNDCLASS的数据结构,Microsoft的手册上是如下定义的:

typedef struct _WNDCLASS {

  UINT style;

  WNDPROC   lpfnWndProc;

  Int   cbClsExtra;

  int cbWndExtra;

  HINSTANCE   hInstance;

  HICON   hIcon;

  HCURSOR   hCursor;

  HBRUSH hbrBackground;

  LPCTSTR   lpszMenuName;

  LPCTSTR   lpszClassName;

} WNDCLASS, *PWNDCLASS;

注意,这是C语言格式的,这个数据结构包含了10个字段,字段的名称是style,lpfnWndProc和cbClsExtra等,前面的UINT和WNDPROC等是这些字段的类型,在汇编中,数据结构的写法如下:

结构名   struct

 

字段1   类型   ?

字段2   类型   ?

……

 

结构名   ends

上面的WNDCLASS结构定义用汇编的格式来表示就是:

WNDCLASS   struct

 

Style DWORD   ?

LpfnWndProc DWORD   ?

cbClsExtra DWORD   ?

cbWndExtra   DWORD   ?

hInstance DWORD   ?

hIcon DWORD   ?

hCursor DWORD   ?

hbrBackground DWORD   ?

lpszMenuName DWORD   ?

lpszClassName DWORD   ?

 

WNDCLASS   ends

和大部分的常量一样,几乎所有API所涉及的数据结构在Windows.inc文件中都已经有定义了。要注意的是,定义了数据结构实际上只是定义了一个“样板”,上面的定义语句并不会在哪个段中产生数据,和Word中使用各种“信纸”与“文书”等模板类似,定义了数据结构以后就可以多次在源程序中用这个“样板”当做数据类型来定义数据,使用数据结构在数据段中定义数据的方法如下:

  .data?

stWndClass   WNDCLASS   <>

  

或者:

  .data

stWndClass   WNDCLASS   <1,1,1,1,1,1,1,1,1,1>

  ……

这个例子定义了一个以WNDCLASS为结构的变量stWndClass,第一段的定义方法是未初始化的定义方法,第二段是在定义的同时指定结构中各字段的初始值,各字段的初始值用逗号隔开,在这个例子中10个字段的初始值都指定为1。

在汇编中,数据结构的引用方法有好几种,以上面的定义为例,如果要使用stWndClass中的lpfnWndProc字段,最直接的办法是:

mov eax,stWndClass.lpfnWndProc

它表示把lpfnWndProc字段的值放入eax中去,假设stWndClass在内存中的地址是403000h,这句指令会被编译成mov eax,[403004h],因为lpfnWndProc是stWndClass中的第二个字段,第一个字段是dword,已经占用了4字节的空间。

在实际使用中,常常有使用指针存取数据结构的情况,如果使用esi寄存器做指针寻址,可以使用下列语句完成同样的功能:

mov esi,offset stWndClass

mov eax,[esi + WNDCLASS.lpfnWndProc]

注意:第二句是[esi + WNDCLASS.lpfnWndProc]而不是[esi + stWndClass.lpfnWndProc],因为前者会被编译成mov eax,[esi+4],而后者会被编译成mov eax,[esi+403004h],后者的结果显然是错误的!如果要对一个数据结构中的大量字段进行操作,这种写法显然比较烦琐,MASM还有一个用法,可以用assume伪指令把寄存器预先定义为结构指针,再进行操作:

mov esi,offset stWndClass

assume  esi:ptr WNDCLASS

mov eax,[esi].lpfnWndProc



assume  esi:nothing

这样,使用寄存器也可以用逗点引用字段名,程序的可读性比较好。这样的写法在最后编译成可执行程序的时候产生同样的代码。注意:在不再使用esi寄存器做指针的时候要用assume esi:nothing取消定义。

结构的定义也可以嵌套,如果要定义一个新的NEW_WNDCLASS结构,里面包含一个老的WNDCLASS结构和一个新的dwOption字段,那么可以如下定义:

NEW_WNDCLASS struct

 

DwOption dword ?

OldWndClass   WNDCLASS  <>

 

NEW_WNDCLASS ends

假设现在esi是指向一个NEW_WNDCLASS的指针,那么引用里面嵌套的oldWndClass中的lpfnWndProc字段时,就可以用下面的语句:

mov eax,[esi].oldWndClass.lpfnWndProc

结构的嵌套在Windows的数据定义中也常有,比如在第13章13.3节中使用的DEBUG_EVENT结构中竟然使用了4层数据结构的嵌套。 熟练掌握数据结构的使用对Win32汇编编程是很重要的!



注意:第二句是[esi + WNDCLASS.lpfnWndProc]而不是[esi + stWndClass.lpfnWndProc],因为前 者会被编译成mov eax,[esi+4],而后者会被编译成mov eax,[esi+403004h],后者的结果显然是错误的!
2010-07-24 10:44
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
没抢到沙发 复制粘贴费时。。。
2010-07-24 10:44
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用okayyyy在2010-7-24 03:14:18的发言:

能给点提示吗?
我想来想去,也没记起在哪里碰到过

呵呵,我用老罗的FindFile.exe跟dir *.*/s比较了下。  还是DOS命令快几秒

你所谓的dos命令应该是指 cmd 可能cmd实现的搜索比较快 不好说啊~
2010-07-24 10:46
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
本人实测

在system32

dir *.* /s 3'' 46'''

     所列文件总数:
            2854 个文件    613,265,347 字节
             923 个目录  5,581,844,480 可用字节

罗大的程序 2'' 15 '''

cmd还得解析 判断 输出 等等 自然比较慢啦

不过两者都是用的 FindFirstFile

4AD01B45   .  FF15 A011D04A CALL DWORD PTR DS:[<&KERNEL32.FindFirstF>; \FindFirstFileW

至于算法 遍历应该都差不多罢


[ 本帖最后由 zklhp 于 2010-7-24 14:10 编辑 ]
2010-07-24 14:08
okayyyy
Rank: 2
等 级:论坛游民
威 望:2
帖 子:102
专家分:70
注 册:2010-6-15
收藏
得分:0 
回复 5楼 zklhp
你那段解释  [esi + WNDCLASS.lpfnWndProc]的用法是在太及时了。唉 明明老罗的书提到过,就是记不起
2010-07-24 15:27
okayyyy
Rank: 2
等 级:论坛游民
威 望:2
帖 子:102
专家分:70
注 册:2010-6-15
收藏
得分:0 
回复 2楼 东海一鱼
问题没写详细,到把你给弄糊涂了  失误失误
其实就是:[esi + WNDCLASS.lpfnWndProc]这种用法
2010-07-24 15:30
okayyyy
Rank: 2
等 级:论坛游民
威 望:2
帖 子:102
专家分:70
注 册:2010-6-15
收藏
得分:0 
老大,你的功力很深啊。 用什么方法能找到dir的实际代码?我只知道这种命令实际是一个小程序

唉,老罗害死人。你看看他定义的变量 dwstatuswidth。

看到前缀,我定义一个相似的 dwstatuswidth  dw 10,20,30,40
搞老半天都没把,状态栏分成4个格子。

原来老罗的这个dwstatuswidth 是个 dd!!!!!!

浪费了2个小时

[ 本帖最后由 okayyyy 于 2010-7-24 17:03 编辑 ]
2010-07-24 16:00
东海一鱼
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:48
帖 子:757
专家分:4760
注 册:2009-8-10
收藏
得分:0 
以下是引用okayyyy在2010-7-24 15:30:30的发言:

问题没写详细,到把你给弄糊涂了  失误失误
其实就是:[esi + WNDCLASS.lpfnWndProc]这种用法
啊,这个呀。
我一般爱用 (WNDCLASS ptr[esi]).lpfnWndProc 这种形式。纯属个人爱好,哈。

举世而誉之而不加劝,举世而非之而不加沮,定乎内外之分,辩乎荣辱之境,斯已矣。彼其于世未数数然也。
2010-07-24 17:11
快速回复:问题来了。第九章,NMHDR.code 怎么会编译成常量?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.033666 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved