拼命尝试使用wprintf在64位NASM x86程序集中打印unicode

时间:2014-05-06 11:24:53

标签: assembly unicode x86 nasm

这是我的代码到目前为止。我已经得到它来打印很多问号,它甚至不能识别我格式的换行符。我想最终能够增加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寄存器存在问题,但我不确定如何解决它

2 个答案:

答案 0 :(得分:1)

您的第一个错误是/u0021应为\u0021。但是,由于wprintf期望宽字符,因此在Linux上通常为UTF-32,因此无法帮助您。 NASM的\u语法创建了UTF-8字符串。

现在似乎在NASM中除了使用dd指定一个代码点值数组之外别无他法。例如。类似的东西:

uchar:
      dd '!', 0

第二个问题是您正在使用期望零终止字符序列的%ls,并且您正在传递单个字符。这就是为什么我在上面添加零。

第三个问题是格式字符串也应该是一个宽字符串。试试这个:

fmt:
        dd '%', 'l', 's', 0

答案 1 :(得分:0)

正如伊戈尔指出的,\ u用于UTF-8字符。根据Nasm文档,您可以使用these macros定义不同类型的UTF字符串。您可能必须在Linux上使用UTF-32,在Windows上使用UTF-16。