我有一个64位的masm代码,输出到控制台。问题是,通过使用WriteConsoleW
,我不能重定向命令或任何东西的输出,因为它只写入控制台缓冲区。但是使用WriteFile
会在每个字符之间增加空格,因为16位字符的高位被清零。如何使用WriteFile
打印Unicode文本?
我读到here,我可以使用BOM,但这对我不起作用(我添加了另一个WriteFile
调用,在第二个WriteFile
调用之前写入两个字节FF FE
,但它只是打印了一个白色矩形,没有其他内容)。
代码如下:
extern GetStdHandle: proc
extern WriteConsoleW: proc
.data?
written dq ?
.data
string dw 0048h,0065h,006ch,006ch,006fh,0020h,0057h,006fh,0072h,006ch,0064h,0021h
len equ $-string
.code
main proc
push rbp
mov rbp, rsp
sub rsp, 020h
and rsp, -10h
mov rcx, -11
call GetStdHandle
mov rcx, rax
mov rdx, offset string
mov r8, len
mov r9, written
call WriteConsoleW
add rsp, 020h
mov rsp, rbp
pop rbp
ret
main endp
end
当我将WriteConsoleW
交换为WriteFile
时,它在通过visual studio运行时可以正确打印,但是当我从命令行运行生成的exe
时,它打印的不是Hello World!
,而是H e l l o W o r l d !
。
有人知道怎么处理吗?
编辑:我不知道如何理解这一点,但不知何故,当我使用WriteFile
代替,16位字符得到打印错误,只有当我单独执行程序。但是,当我将输出重定向到echo
命令时,它会正常打印:
1条答案
按热度按时间sgtfey8w1#
C中的相同API产生相同的控制台输出。
WriteConsoleW
执行WriteFile
不执行的到控制台的字符转换。WriteFile
只是将字节发送到控制台,控制台在当前代码页中解释它们,对我来说是437(OEM美国)。我可以通过调用
SetConsoleOutputCP(65001)
(将控制台代码页设置为UTF-8),然后编写一个UTF-8字符串来让它在C中工作。请注意,list of code page identifiers包含UTF-16,但它仅适用于托管应用程序(例如C#)。我打印了一些非ASCII码,看看它是否正确。
输出:
您应该能够轻松地将其应用于MASM。
如果您愿意使用C运行时库,那么如果您适当地设置了控制台和文件模式,则这些API都适用于UTF-16:
输出到控制台:
Output to test.txt encoded in UTF-16LE. Note that 马克 is the two unicode code points U+9A5C and U+514B:
编辑
下面是
GetFileType
的演示。如果运行,它将正确写入控制台。如果重定向到文件,例如“test > out.txt”,输出文件包含UTF-16 LE编码的数据。输出到控制台:
输出重定向到
out.txt
: