[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
75# hanyeguxing

原来如此,学习了。追问一下:“在DEBUG命令状态下查看环境,首先查看偏移量2C处的两个字节:”这里的2C是怎么的出来的呢?

TOP

本帖最后由 hanyeguxing 于 2011-4-23 09:23 编辑

  系统每运行一次命令解释器都要生成一个256字节的内存块——程序段前缀PSP(Program Segment Prefix),它包含了一些比较重要的信息,如内存单元、矢量、命令行上键入的文件名、命令行本身(用户运行程序的命令行的拷贝)、各种保留缓冲器存储地点的信息。只要涉及环境,那些存储地点之一就会保存系统环境地址。

  打开命令解释器,运行 for /l %a in (1,1,100) do set "#%a=%a" ,设置这些变量,接着运行 DEBUG

  在DEBUG命令状态下查看环境,首先查看偏移量2C处的两个字节:

  -D2CL2
   0B2DA:0020  66 05

  数据66 05是在某系统上得到的计算机环境的段地址值(操作时应以实际显示数为准),把这两对数以相反的顺序,并在后面跟上偏移量0,就能在DEBUG命令上显示系统环境。

  -D0566:0

附件: 您需要登录才可以下载或查看附件。没有帐号?注册
1

评分人数

    • plp626: debug方法确实能反映本质。用代码的输出只是 ...技术 + 1
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

本帖最后由 plp626 于 2011-4-23 10:35 编辑

垃圾变量名集合 不含有待赋值变量 与 含有待赋值变量 的比较

上面那个代码设定
set loop=4500
set p=150
set "pre1=_"      :: 垃圾变量前缀
set "pre2=#"      :: 待赋值变量前缀
set "med=set"    :: 赋值方式

set loop=4500
set p=150
set "pre1=_"      :: 垃圾变量前缀
set "pre2=_"      :: 待赋值变量前缀
set "med=set"    :: 赋值方式
的输出:分别为
  1. 待测试变量数占垃圾变量数(4500个)的比:1/150
  2. “垃圾变量名”中【不含有】待赋值变量的测试
  3. ====================================
  4. 执行4500次set _1=1耗时:161,阶差:161 // 第一个阶差不做参考
  5. 执行4500次set _2=1耗时:161,阶差:0
  6. 执行4500次set _3=1耗时:163,阶差:2
  7. 执行4500次set _4=1耗时:162,阶差:-1
  8. 执行4500次set _5=1耗时:163,阶差:1
  9. 执行4500次set _6=1耗时:161,阶差:-2
  10. 执行4500次set _7=1耗时:161,阶差:0
  11. 执行4500次set _8=1耗时:161,阶差:0
  12. 执行4500次set _9=1耗时:164,阶差:3
  13. 执行4500次set _10=1耗时:161,阶差:-3
  14. 执行4500次set _11=1耗时:161,阶差:0
  15. 执行4500次set _12=1耗时:161,阶差:0
  16. 执行4500次set _13=1耗时:161,阶差:0
  17. 执行4500次set _14=1耗时:159,阶差:-2
  18. 执行4500次set _15=1耗时:159,阶差:0
  19. 执行4500次set _16=1耗时:162,阶差:3
  20. 执行4500次set _17=1耗时:163,阶差:1
  21. 执行4500次set _18=1耗时:160,阶差:-3
  22. 执行4500次set _19=1耗时:161,阶差:1
  23. 执行4500次set _20=1耗时:162,阶差:1
  24. 执行4500次set _21=1耗时:161,阶差:-1
  25. 执行4500次set _22=1耗时:161,阶差:0
  26. 执行4500次set _23=1耗时:161,阶差:0
  27. 执行4500次set _24=1耗时:161,阶差:0
  28. 执行4500次set _25=1耗时:161,阶差:0
  29. 执行4500次set _26=1耗时:161,阶差:0
  30. 执行4500次set _27=1耗时:162,阶差:1
  31. 执行4500次set _28=1耗时:164,阶差:2
  32. 执行4500次set _29=1耗时:163,阶差:-1
  33. 执行4500次set _30=1耗时:162,阶差:-1
  34. 请按任意键继续. . .
复制代码
::::::::::::::::::::::::::::::::::::::::::::::::
  1. 待测试变量数占垃圾变量数(4500个)的比:1/150
  2. “垃圾变量名”中【含有】待赋值变量的测试
  3. ====================================
  4. 执行4500次set _1=1耗时:67,阶差:67
  5. 执行4500次set _2=1耗时:91,阶差:24
  6. 执行4500次set _3=1耗时:116,阶差:25
  7. 执行4500次set _4=1耗时:139,阶差:23
  8. 执行4500次set _5=1耗时:155,阶差:16
  9. 执行4500次set _6=1耗时:155,阶差:0  // 略微变化
  10. 执行4500次set _7=1耗时:158,阶差:3
  11. 执行4500次set _8=1耗时:162,阶差:4
  12. 执行4500次set _9=1耗时:164,阶差:2
  13. 执行4500次set _10=1耗时:68,阶差:-96 // 显著变化
  14. 执行4500次set _11=1耗时:73,阶差:5
  15. 执行4500次set _12=1耗时:72,阶差:-1
  16. 执行4500次set _13=1耗时:73,阶差:1
  17. 执行4500次set _14=1耗时:75,阶差:2
  18. 执行4500次set _15=1耗时:78,阶差:3
  19. 执行4500次set _16=1耗时:79,阶差:1
  20. 执行4500次set _17=1耗时:83,阶差:4
  21. 执行4500次set _18=1耗时:84,阶差:1
  22. 执行4500次set _19=1耗时:88,阶差:4
  23. 执行4500次set _20=1耗时:91,阶差:3
  24. 执行4500次set _21=1耗时:94,阶差:3
  25. 执行4500次set _22=1耗时:95,阶差:1
  26. 执行4500次set _23=1耗时:98,阶差:3
  27. 执行4500次set _24=1耗时:100,阶差:2
  28. 执行4500次set _25=1耗时:105,阶差:5
  29. 执行4500次set _26=1耗时:106,阶差:1
  30. 执行4500次set _27=1耗时:108,阶差:2
  31. 执行4500次set _28=1耗时:111,阶差:3
  32. 执行4500次set _29=1耗时:112,阶差:1
  33. 执行4500次set _30=1耗时:116,阶差:4
  34. 请按任意键继续. . .
复制代码

TOP

看了plp626老兄几次测试数据,百思不得其解为什么只要循环到变量名为_1n的时候,阶差会突然间低得可怜,居然还有负的...和_1完全不在一个档次上,这是什么原因呢?

TOP

奇怪,你们为什么就不用debug直接查询本地化变量在内存中的存储呢,很容易的事
hanyeguxing 发表于 2011-4-23 09:01

门外汉表示没学过...麻烦您教教呗

TOP

69# zm900612


不错,因为 set /a =%#39999% 这一句,在预处理 a 变量时,搜索指针就已经经过了 #39999 变量,一次预处理得到了a,#399992个值,所以实际耗时就是一次取值 "a "的耗时。
所以hanyeguxin的代码才没有测试出差距。

TOP

奇怪,你们为什么就不用debug直接查询本地化变量在内存中的存储呢,很容易的事
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

@echo off&setlocal enabledelayedexpansion
set n=10000 1 39999
rem set n=39999 -1 10000
echo %time%开始%n%
for /l %%a in (%n%) do set #%%a=1
echo %time%赋值完成
for /l %%a in (%n%) do set a=!#1 ...
caruko 发表于 2011-4-23 08:37

%和!在for中的耗时明显不一样,一个语块只解释一次%str%,而!str!的解释次数与相应语句的执行次数成正比,假如在六千次循环中分别用%str%和!str!测试,!str!会比%str%多出5999次花在预处理中的耗时

TOP

有很多因素影响赋值操作的

TOP

设定
set loop=10000
set "pre1=_"      :: 垃圾变量前缀
set "pre2=_"      :: 待赋值变量前缀
set "med=set/a"    :: 赋值方式
  1. @echo off&setlocal EnableDelayedExpansion
  2. :: loop值也是垃圾变量的数量,不能过小,便于比较出差异
  3. set/a loop=10000
  4. set/a p=500
  5. set/a num=loop/p
  6. set "pre1=_"      :: 垃圾变量前缀
  7. set "pre2=_"      :: 待赋值变量前缀
  8. set "med=set "    :: 赋值方式
  9. ======================%测试开始%=========================
  10. echo 待测试变量数占垃圾变量数(%loop%个)的比:1/%p%
  11. if "%pre1%"=="%pre2%" (
  12.         echo “垃圾变量名”中【含有】待赋值变量的测试
  13. ) else (
  14.         echo “垃圾变量名”中【不含有】待赋值变量的测试
  15. )
  16. echo ====================================
  17. :: 生成“垃圾变量”
  18. for /l %%a in (1,1,%loop%) do set %pre1%%%a=1
  19. :: 测试赋值耗时变化
  20. for /l %%z in (1 1 %num%)do (set/a tp=tt,tt=0
  21.         set t1=!time!
  22.         for /l %%a in (1 1 %loop%)do %med% %pre2%%%z=1
  23.         set t2=!time!
  24. set/a tt=1!t2:~-5,2!!t2:~-2!-1!t1:~-5,2!!t1:~-2!,tt+="-6000*(tt>>31)"
  25. set /a cc=tt-tp
  26. echo  执行%loop%次%med% %pre2%%%z=1耗时:!tt!,阶差:!cc!
  27. )
  28. pause
复制代码
  1. 待测试变量数占垃圾变量数(10000个)的比:1/500
  2. “垃圾变量名”中【含有】待赋值变量的测试
  3. ====================================
  4. 执行10000次set _1=1耗时:328,阶差:328 // 注释,第一个阶差不做参考
  5. 执行10000次set _2=1耗时:359,阶差:31
  6. 执行10000次set _3=1耗时:432,阶差:73
  7. 执行10000次set _4=1耗时:491,阶差:59
  8. 执行10000次set _5=1耗时:550,阶差:59
  9. 执行10000次set _6=1耗时:603,阶差:53
  10. 执行10000次set _7=1耗时:653,阶差:50
  11. 执行10000次set _8=1耗时:717,阶差:64
  12. 执行10000次set _9=1耗时:775,阶差:58
  13. 执行10000次set _10=1耗时:342,阶差:-433 // 注意垃圾变量数的千分之一
  14. 执行10000次set _11=1耗时:339,阶差:-3
  15. 执行10000次set _12=1耗时:323,阶差:-16
  16. 执行10000次set _13=1耗时:330,阶差:7
  17. 执行10000次set _14=1耗时:348,阶差:18
  18. 执行10000次set _15=1耗时:346,阶差:-2
  19. 执行10000次set _16=1耗时:348,阶差:2
  20. 执行10000次set _17=1耗时:380,阶差:32
  21. 执行10000次set _18=1耗时:384,阶差:4
  22. 执行10000次set _19=1耗时:400,阶差:16
  23. 执行10000次set _20=1耗时:384,阶差:-16
  24. 请按任意键继续. . .
复制代码

TOP

本帖最后由 caruko 于 2011-4-23 08:57 编辑

如果以上成立的话,那么以后写代码,在大量变量存在的空间,能不用!!就尽量不用了。

还有,hanyeguxin 如果你的逐字搜索来说,那么 set _10000 比set _9 快 无法解释。
而且set _x 比所有 _number 慢也无法解释。

逐字搜索,需要类似数据库映射表,这样才会加快速度。但 set _10000 比 set _9 快很多,可见不成立。
而如果搜索一个单字符,也是遍历进行的,那么假如变量字符很长,需要搜索的次数反而应该大大增加吧?

TOP

  1. @echo off&setlocal enabledelayedexpansion
  2. set n=10000 1 39999
  3. rem set n=39999 -1 10000
  4. echo %time%开始%n%
  5. for /l %%a in (%n%) do set #%%a=1
  6. echo %time%赋值完成
  7. for /l %%a in (%n%) do set a=!#10000!
  8. echo %time%第一批完成
  9. for /l %%a in (%n%) do set a=!#39999!
  10. echo %time%第二批完成
  11. pause
复制代码
电脑太废...看结果
  1. 8:32:28.14开始10000 1 39999
  2. 8:33:11.32赋值完成
  3. 8:34:32.75第一批完成
  4. 8:36:49.43第二批完成
  5. 请按任意键继续. . .
复制代码

TOP

设定
set loop=6000
set "pre1=_"      :: 垃圾变量前缀
set "pre2=_"      :: 待赋值变量前缀
set "med=set/a"    :: 赋值方式
  1. @echo off&setlocal EnableDelayedExpansion
  2. :: loop值也是垃圾变量的数量,不能过小,便于比较出差异
  3. set/a loop=6000
  4. set/a p=500
  5. set/a num=loop/p
  6. set "pre1=_"      :: 垃圾变量前缀
  7. set "pre2=_"      :: 待赋值变量前缀
  8. set "med=set "    :: 赋值方式
  9. ======================%测试开始%=========================
  10. echo 待测试变量数占垃圾变量数(%loop%个)的比:1/%p%
  11. if "%pre1%"=="%pre2%" (
  12.         echo “垃圾变量名”中【含有】待赋值变量的测试
  13. ) else (
  14.         echo “垃圾变量名”中【不含有】待赋值变量的测试
  15. )
  16. echo ====================================
  17. :: 生成“垃圾变量”
  18. for /l %%a in (1,1,%loop%) do set %pre1%%%a=1
  19. :: 测试赋值耗时变化
  20. for /l %%z in (1 1 %num%)do (set/a tp=tt,tt=0
  21.         set t1=!time!
  22.         for /l %%a in (1 1 %loop%)do %med% %pre2%%%z=1
  23.         set t2=!time!
  24. set/a tt=1!t2:~-5,2!!t2:~-2!-1!t1:~-5,2!!t1:~-2!,tt+="-6000*(tt>>31)"
  25. set /a cc=tt-tp
  26. echo  执行%loop%次%med% %pre2%%%z=1耗时:!tt!,阶差:!cc!
  27. )
  28. pause
复制代码
输出:
  1. 待测试变量数占垃圾变量数(6000个)的比:1/500
  2. “垃圾变量名”中【含有】待赋值变量的测试
  3. ====================================
  4. 执行6000次set/a _1=1耗时:130,阶差:130
  5. 执行6000次set/a _2=1耗时:223,阶差:93
  6. 执行6000次set/a _3=1耗时:320,阶差:97
  7. 执行6000次set/a _4=1耗时:413,阶差:93
  8. 执行6000次set/a _5=1耗时:516,阶差:103
  9. 执行6000次set/a _6=1耗时:631,阶差:115
  10. 执行6000次set/a _7=1耗时:646,阶差:15
  11. 执行6000次set/a _8=1耗时:637,阶差:-9
  12. 执行6000次set/a _9=1耗时:648,阶差:11
  13. 执行6000次set/a _10=1耗时:124,阶差:-524
  14. 执行6000次set/a _11=1耗时:139,阶差:15
  15. 执行6000次set/a _12=1耗时:147,阶差:8
  16. 请按任意键继续. . .
复制代码

TOP

设定
set loop=6000
set "pre1=_"      :: 垃圾变量前缀
set "pre2=_"      :: 待赋值变量前缀
set "med=set "    :: 赋值方式
  1. @echo off&setlocal EnableDelayedExpansion
  2. :: loop值也是垃圾变量的数量,不能过小,便于比较出差异
  3. set/a loop=6000
  4. set/a p=500
  5. set/a num=loop/p
  6. set "pre1=_"      :: 垃圾变量前缀
  7. set "pre2=_"      :: 待赋值变量前缀
  8. set "med=set "    :: 赋值方式
  9. ======================%测试开始%=========================
  10. echo 待测试变量数占垃圾变量数(%loop%个)的比:1/%p%
  11. if "%pre1%"=="%pre2%" (
  12.         echo “垃圾变量名”中【含有】待赋值变量的测试
  13. ) else (
  14.         echo “垃圾变量名”中【不含有】待赋值变量的测试
  15. )
  16. echo ====================================
  17. :: 生成“垃圾变量”
  18. for /l %%a in (1,1,%loop%) do set %pre1%%%a=1
  19. :: 测试赋值耗时变化
  20. for /l %%z in (1 1 %num%)do (set/a tp=tt,tt=0
  21.         set t1=!time!
  22.         for /l %%a in (1 1 %loop%)do %med% %pre2%%%z=1
  23.         set t2=!time!
  24. set/a tt=1!t2:~-5,2!!t2:~-2!-1!t1:~-5,2!!t1:~-2!,tt+="-6000*(tt>>31)"
  25. set /a cc=tt-tp
  26. echo  执行%loop%次%med% %pre2%%%z=1耗时:!tt!,阶差:!cc!
  27. )
  28. pause
复制代码
输出:
  1. 待测试变量数占垃圾变量数(6000个)的比:1/500
  2. “垃圾变量名”中【含有】待赋值变量的测试
  3. =====================================
  4. 执行6000次set _1=1耗时:116,阶差:116
  5. 执行6000次set _2=1耗时:152,阶差:36
  6. 执行6000次set _3=1耗时:185,阶差:33
  7. 执行6000次set _4=1耗时:221,阶差:36
  8. 执行6000次set _5=1耗时:250,阶差:29
  9. 执行6000次set _6=1耗时:286,阶差:36
  10. 执行6000次set _7=1耗时:289,阶差:3
  11. 执行6000次set _8=1耗时:294,阶差:5
  12. 执行6000次set _9=1耗时:299,阶差:5
  13. 执行6000次set _10=1耗时:117,阶差:-182
  14. 执行6000次set _11=1耗时:118,阶差:1
  15. 执行6000次set _12=1耗时:122,阶差:4
复制代码

TOP

57# hanyeguxing


从你的代码来看,假如CMD预处理时只取一次变量因为是%%而不是!!,而其中变量 a 是排在最后的,所以每次搜索到"a", 也必然搜索到了前面的#数字变量。
那么花的时候必然相同。
或许使用!!试一试会不一样。

TOP

返回列表