注册 登录
编程论坛 汇编论坛

【求助】关于汇编中调用API只能是ASCII版本的问题

非人间的雪 发布于 2013-01-20 13:33, 658 次点击
撸主昨日闲来无事看了下《windows程序设计》,里面有这么一段话“wndclass.lpszClassName = szAppName ;         
至于该字符串由ASCII字符组成或由Unicode字符组成,取决于是否定义了UNICODE标识符。

撸主突然想到在Win32汇编里,它是怎么确定用哪个版本的,于是撸主用MessageBox做下实验,写了一段代码:
程序代码:
.386
.model flat, stdcall
option casemap:none

include        windows.inc
include        user32.inc
includelib    user32.lib
include        kernel32.inc
includelib    kernel32.lib


.const
szMsgText    db    '几时心绪浑无事,得几游丝百尺长?',0
szCaption    db    '诗句',0

.code
start:
        invoke    MessageBoxA,NULL,offset szMsgText,offset szCaption,MB_OK
        mov    eax, sizeof szCaption
        .if    eax == 5
            invoke    MessageBox, NULL, NULL, NULL, MB_OK
        .endif
      
        invoke    ExitProcess,NULL

        end    start

使用eax对szCaption的长度进行判断时,撸主试了几次,惊奇的发现它的长度居然是5!中文的确是用两个byte表示了,但最后一个0仍然是一个byte!
问题有:
一、使用MessageBoxA的时候没有任何问题,但是为什么可以呢?这个不是只能处理ASCII字符串么??
二、修改下代码,使用MessageBoxW的时候就会产生乱码,为什么呢?
三、再修改一下代码,将两个字符串用DW定义,这时候编译就不能通过了:“constant value too large”,这是为什么?撸主注意到使用ml编译的时候
有个提示  ASCII build, 所有这些问题是不是都跟这个有关?

好吧,坐等各路大神解答


6 回复
#2
wp2319572013-01-20 13:39
szCaption    db    '诗句',0  长度就是5  
MessageBoxA  谁说他不能处理中文字符串啊
#3
wp2319572013-01-20 13:47
这里有z版的 W函数的示例
https://bbs.bccn.net/thread-360011-1-1.html
#4
非人间的雪2013-01-20 13:53
回复 2楼 wp231957
代码好长啊,大神,还有钩子。。。书都还没看到那呢,有短点的代码么...如果MessageBoxA能处理中文,那干嘛还弄个MessageBoxW??
的确是不明白,用db定义的中文为什么会变成两个字节的??
#5
x64asm2013-01-20 18:38
UNICODE编码的字符不是等长数据,他既有8位的,又有16位的。原来的ANSI标准字符是8位,
阿拉伯语,日语,韩语,正体中文等都是16位的编码。之所以推出UNICODE就是解决不等长问题的.
16位自然是占2个字节, 至于ANSI的零,自然是1个字节了.
#6
非人间的雪2013-01-20 23:56
回复 5楼 x64asm
那大神能告诉我为什么用MessageBoxW就会乱码呢,而且ASCII版的MessageBoxA怎么分辨,当前的字符串有没有汉字?API是操作系统提供的
在独立的DLL中,编译器和连接器都不可能影响到DLL中的函数,换句话说,在独立的DLL中,MessageBoxA是不可能知道传递给它的字符串到底
是纯英文,还是混有汉字。所以它到底是怎么做到可以分辨出汉字进而将两个字节的数据解释为一个汉字的呢??
#7
GoldenSpider2013-01-22 21:33
首先,一个问题是你的源码文件是什么格式存储的。
    通常汇编编译器只支持ANSI编码的源码文件,也就是说在预处理阶段的输入对象是ANSI编码文件。
ANSI编码可以简单理解为0~127的1个字节用来存储字符+2个字节的GB2312汉字编码,比如:"a啊b长長"编码为:61 B0A1 62 B3A4 E94C
可以看到a的编码是0x61,啊的编码是0xB0A1

那么,接下来的问题是给你这一串编码数字,你如何解释为一个汉字呢?
    这就与上面的编码规则相关了,ANSI编码的字符为单字节保存的,最高位为0,所以最大为0x7F;简体汉字为双字节,两个字节的最高位均为1;从这两点你就可以知道了,
只要单字节的扫描数据,如果扫到小于0x80的,为字符,最高位为1是汉字。
可是呢,呵呵,可以看到"長"的编码是0xE94C,如果是繁体字呢,首字节的最高位是1,次字节的最高位为0。
这样,字符+简体字+繁体字,单字节扫描,最高位为1的,接下来的一个字节将一起作为汉字的编码,其它情形小于0x80的为字符。

管中窥豹,UNICODE等诸如,可见一斑。

扩展阅读:
《信息交换用汉字编码字符集--基本集》—即国家标准 GB2312-80

1