Lor*_*nzo 3 unicode console assembly x86-64 masm
我有一个 64 位 masm 代码,可以输出到控制台。问题是,通过使用WriteConsoleW,我无法重定向命令或任何内容的输出,因为它只写入控制台缓冲区。但使用WriteFile会在每个字符之间添加空格,因为 16 位字符的高位已清零。如何使用 打印 Unicode 文本WriteFile?
我在这里读到我可以使用 BOM,但这对我不起作用(我添加了另一个调用,该调用在第二次调用之前WriteFile写入两个字节,但它只打印了一个白色矩形,没有其他内容)。FF FEWriteFile
这是代码:
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
Run Code Online (Sandbox Code Playgroud)
当我交换WriteConsoleW到 时WriteFile,它在通过 Visual Studio 运行时正确打印,但是当我运行exe从命令行生成的文件时,Hello World!它不是打印而是打印H e l l o W o r l d !
有谁知道如何处理这个问题?
编辑:我不知道如何理解这一点,但不知何故,当我使用WriteFile它时,只有当我单独执行程序时,16 位字符才会打印错误。但是,当我将输出重定向到echo命令时,它会正常打印:

C++ 中的相同 API 会产生相同的控制台输出。 WriteConsoleW对控制台执行字符转换,但WriteFile不执行。\nWriteFile只是将字节发送到控制台,控制台在当前代码页中解释它们,对我来说是 437(美国 OEM)。
我可以通过调用SetConsoleOutputCP(65001)(将控制台代码页设置为 UTF-8)然后编写 UTF-8 字符串来使其在 C++ 中工作。请注意此代码页标识符列表,其中包括 UTF-16,但它仅适用于托管应用程序(例如 C#)。
我打印了一些非 ASCII 来看看它是否正确输出。
\n// compiled with MSVS "cl /W4 /utf-8 test.cpp"\n// source saved in UTF-8 as well.\n#include <windows.h>\n\nint main() {\n char s[] = u8"Hello, \xe9\xa9\xac\xe5\x85\x8b"; // Note: need a chinese font, but cut/paste\n // to Notepad and you\'ll see them if you don\'t.\n SetConsoleOutputCP(65001);\n auto h = GetStdHandle(STD_OUTPUT_HANDLE);\n DWORD written;\n WriteFile(h, s, sizeof(s), &written, nullptr);\n}\nRun Code Online (Sandbox Code Playgroud)\n输出:
\nHello, \xe9\xa9\xac\xe5\x85\x8b\nRun Code Online (Sandbox Code Playgroud)\n您应该能够轻松地将其适应 MASM。
\n如果您愿意使用 C 运行时库,那么如果您正确设置控制台和文件模式,这些 API 都适用于 UTF-16:
\n#include <stdio.h>\n#include <io.h>\n#include <fcntl.h>\n\nint main()\n{\n _setmode(_fileno(stdout), _O_U16TEXT);\n wchar_t s[] = L"Hello, \xe9\xa9\xac\xe5\x85\x8b!";\n _write(_fileno(stdout), s, sizeof(s));\n int fd = _open("test.txt", _O_CREAT | _O_WRONLY | _O_U16TEXT);\n _write(fd, s, sizeof(s));\n _close(fd);\n}\nRun Code Online (Sandbox Code Playgroud)\n输出到控制台:
\nHello, \xe9\xa9\xac\xe5\x85\x8b!\nRun Code Online (Sandbox Code Playgroud)\n输出到以 UTF-16LE 编码的 test.txt。请注意,\xe9\xa9\xac\xe5\x85\x8b 是两个 unicode 代码点 U+9A5C 和 U+514B:\n
编辑
\n这是一个GetFileType. 如果运行它会正确写入控制台。如果重定向到文件,例如“test > out.txt”,则输出文件包含UTF-16LE 编码的数据。
#include <windows.h>\n\nint main()\n{\n auto h = GetStdHandle(STD_OUTPUT_HANDLE);\n auto type = GetFileType(h);\n \n WCHAR s[] = L"Only 20\\u20AC!"; // U+20AC is EURO sign.\n DWORD written;\n \n if(type == FILE_TYPE_DISK)\n WriteFile(h, s, sizeof(s) - sizeof(WCHAR) /* don\'t send the null */, &written, nullptr);\n else\n WriteConsoleW(h, s, sizeof(s) / sizeof(WCHAR) - 1, &written, nullptr);\n}\nRun Code Online (Sandbox Code Playgroud)\n输出到控制台:
\nOnly 20\xe2\x82\xac!\nRun Code Online (Sandbox Code Playgroud)\n输出重定向到out.txt:\n
| 归档时间: |
|
| 查看次数: |
864 次 |
| 最近记录: |