拼命尝试使用 wprintf 在 64 位 NASM x86 程序集中打印 unicode
Posted
技术标签:
【中文标题】拼命尝试使用 wprintf 在 64 位 NASM x86 程序集中打印 unicode【英文标题】:Desperately trying to print unicode in 64 bit NASM x86 assembly with wprintf 【发布时间】:2014-05-06 11:24:52 【问题描述】:到目前为止,这是我的代码。我已经让它打印了很多问号,它甚至无法识别我格式中的换行符。我希望最终能够增加 unicode 值,以便该函数打印一组大约 50 个 unicode 字符,但我很难让它只打印一个:S
; compile with
; nasm -felf64 Uniwc.asm && gcc Uniwc.o && ./a.out
global main
extern wprintf
section .text
main:
mov rdi, fmt
mov rsi, uchar
mov rax, 0
call wprintf
ret
uchar:
db '/u0021'
fmt:
db "%ls",0
编辑:通过确保在打印前对齐堆栈,我得到了类似的代码来打印 UTF-8 字符
; nasm -felf64 Uniwc.asm && gcc Uniwc.o && ./a.out
global main
extern printf
section .text
main:
push rbp
mov rdi, fmt
mov rsi, uchar
mov rax, 0
call printf
pop rbp
ret
uchar:
db 0x21, 0
fmt:
db "%c", 10, 0
现在我遇到了一个新问题,如果我更改 uchar 中的 unicode,例如,如果我将其更改为 0x7E (~),程序将不会返回新字符,它仍然会打印 0x21 (!) 我假设这是堆栈上的 rbp 寄存器有问题,但我不确定如何解决它
【问题讨论】:
【参考方案1】:您的第一个错误是 /u0021
应该是 \u0021
。但是,这对您没有帮助,因为 wprintf
需要 宽字符,在 Linux 上通常是 UTF-32。而 NASM 的 \u
语法会创建 UTF-8 字符串。
目前看来,在 NASM 中,除了使用 dd
指定代码点值数组之外别无他法。例如。类似:
uchar:
dd '!', 0
第二个问题是您正在使用%ls
,它需要一个以零结尾的字符序列,并且您正在传递一个字符。这就是为什么我在上面加了一个零。
第三个问题是格式字符串也应该是宽字符串。试试这个:
fmt:
dd '%', 'l', 's', 0
【讨论】:
只是想知道,wprintf()
是否真的使用加载到寄存器中的参数,还是应该将所有这些都压入堆栈?
它使用当前系统的任何调用约定。在 Linux x64 上它是 SysV AMD64 ABI,所以它使用 RDI、RSI 等。
感谢并为愚蠢的错误感到抱歉,但对于我正在尝试做的事情,我不能只硬编码值“!”我有一个工作的 nasm 程序可以做到这一点。我特别想做的是从 UTF-16 代码点打印。我会继续摆弄它。【参考方案2】:
正如 Igor 指出的,\u 用于 UTF-8 字符。根据 Nasm 文档,您可以使用 these macros 定义不同类型的 UTF 字符串。您可能必须在 Linux 上使用 UTF-32,在 Windows 上使用 UTF-16。
【讨论】:
以上是关于拼命尝试使用 wprintf 在 64 位 NASM x86 程序集中打印 unicode的主要内容,如果未能解决你的问题,请参考以下文章
在 RHEL 6 x64 中配置网络音频系统 [NAS] 时出错
为啥 wprintf 在 Linux 上将 Unicode 中的俄语文本音译成拉丁语?