【问题标题】:Desperately trying to print unicode in 64 bit NASM x86 assembly with wprintf拼命尝试使用 wprintf 在 64 位 NASM x86 程序集中打印 unicode
【发布时间】: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 寄存器有问题,但我不确定如何解决它

【问题讨论】:

    标签: assembly unicode x86 nasm


    【解决方案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。

    【讨论】:

      猜你喜欢
      • 2013-08-06
      • 2015-05-04
      • 1970-01-01
      • 1970-01-01
      • 2015-06-09
      • 1970-01-01
      • 2022-01-01
      • 2023-01-11
      • 2015-02-20
      相关资源
      最近更新 更多