Board logo

标题: [其他] [疑惑]灵异的 37 代码页 [打印本页]

作者: CrLf    时间: 2012-4-16 13:12     标题: [疑惑]灵异的 37 代码页

本帖最后由 CrLf 于 2012-4-16 13:15 编辑

本来是要测试代码页与点阵字体尺寸对应关系的,结果无意间遇到了一个神奇的代码页...
  1. chcp 37
  2. in
复制代码
请复制上面的代码保存于 .bat 脚本运行,注意 n 后面必须有个空格
(win7 实测,xp 下待验证)运行后发现创建了一个以空格为名的文件(正常文件名不允许以空格结尾),于是尝试用 unc 路径创建同样的文件:
  1. cd .>"\\?\%cd%\ "
复制代码
结果发现虽然成功创建空文件名的文件,但是却无法删除,看来和前者还是有区别的。

至于 "in " 在 37 代码页下为何会有此效果,我以unicode格式查看37代码页发现其内容十分奇异,下图是 936、437、37 代码页开头部分的内容对照图,可以看到 37 代码页的内容是十分混乱的:
[attach]5151[/attach]

用 cmd /k 运行脚本查看预处理结果:
  1. Active code page: 37
  2. C:\Users\Administrator\Desktop>i1> @
  3. operable program or batch file.rnal or external command,
  4. C:\Users\Administrator\Desktop>
复制代码
可以看到 "in " 在 37 代码页下被预处理为 "i1> @"也就是说 "n" 被映射为 ">"
这里的 "i" 其实只代表一个不存在的命令名称,可以是其他字符,但要留意该代码页下的字符映射关系
而 "n" 后的空格也可以是其他非字母字符,比如:
  1. chcp 37
  2. in
  3. in;
  4. in,
  5. in:
  6. in#
复制代码
其结果是分别创建了五个以空格为名的文件...简直匪夷所思,同目录下,同名文件居然也能共存?
没有做更深入的测试,至少我将 37 代码页下的预处理结果放到 936 和 437 代码页下运行时是报错的,更没有听说过同名文件共存的先例,所以只能认为 37 代码页另有玄机,不能以常理揣度,发个帖子看看有没有专业人士来解惑。
作者: applba    时间: 2012-4-16 15:25

并不是真的空格,只是无法显示
作者: CrLf    时间: 2012-4-17 23:16

回复 2# applba


    也许吧,不过我用 debug 查看 dir 的输出结果,发现文件名均为 0x3F
作者: qzwqzw    时间: 2012-4-18 11:43

并不是真的空格,只是无法显示
applba 发表于 2012-4-16 15:25

完全赞同

cmd乃至Windows内部以Unicode存储和识别字符
看到的空格只是该字符针对当前字符集的一种映射
我这里看到的不是空格
而是一个方框号
通过从WinHex查询
确认in空格产生的文件名是0x80字符
in分号产生的文件名是0x9B字符

你看到的混乱文本
是字符集31在ANSI字符集(很可能是GBK)的一种未经转换的表现
由于字符集的字符数量不同
字符集的字符很可能无法一一对应
更很难有线性的映射关系
肯定是混乱而且很可能是有重复的

debug看到的结果
也是ntvdm经过映射转换的结果
不是在存储上的直接表示
所以无法作为参考依据

另:
代码页37经查是IBM EBCDIC (US-Canada)
简称IBM037
参考链接:
http://mincomp.ycool.com/post.1896603.html
作者: Taurus    时间: 2012-5-7 03:04

繁體win 7 x64報告:

代碼完全沒效果
作者: 秋风·飞扬    时间: 2012-5-7 12:12

留名学习;‘;’
作者: Demon    时间: 2012-7-20 00:58

37代码页对应的是EBCDIC 037,与我们常见的ASCII相差很大。

维基百科上有EBCDIC 037与Unicode的映射表http://en.wikipedia.org/wiki/EBCDIC_037

第一行代码中的chcp 37命令将当前的代码页切换成了EBCDIC 037,这样CMD在调用MultiByteToWideChar函数将第二行代码转换成Unicode时就会使用37代码页,

类似于这样:
  1. MultiByteToWideChar(37, MB_PRECOMPOSED, "in ", 3, Buf, 8191);
复制代码
"in "用十六进制表示为69 6E 20,通过查表(上面的维基百科链接)可知

EBCDIC 037的第105(0x69)个字符为Ñ,对应的Unicode代码点为U+00D1
EBCDIC 037的第110(0x6E)个字符为>,对应的Unicode代码点为U+003E
EBCDIC 037的第32(0x20)个字符为不可打印字符,对应的Unicode代码点为U+0080

所以转成Unicode后的代码为Ñ>[\x0080],文件名只是无法显示的U+0080,并不是空格U+0020

空格(0x20) 分号(0x3B) 逗号(0x2C) 冒号(0x3A) 井号(0x23)在EBCDIC 037下分别对应U+0080 U+009B U+008C U+009A U+0083,

所以得到的是5个不同名称的文件,只不过这些字符都无法显示,看起来一样罢了。




欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2