You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NASM字符串中正确打印非ASCII字符?

问题:NASM程序无法正确显示非ASCII特殊字符

我写了一个小型NASM程序,用来读取第一个命令行参数并打印输出。ASCII输入下运行正常,比如执行myfile hello会返回argv = hello,但输入包含õ、ä、ö、ü这类特殊字母时,显示结果会变成§、õ、÷、³。

当前代码如下:

section .data
    input dw `argv = %s\n` , 0

section .bss

section .text
    global _main
    extern _printf

_main:
    push ebp
    mov ebp,esp
    push esi
    
    mov esi, [ebp + 12]
    mov ebx, 1
    mov eax, [esi + ebx * 4]
    push eax
    
    push input
    call _printf
    
    pop esi
    mov esp, ebp
    pop ebp
    ret

编译命令:

nasm -f win32 myfile.asm -o myfile.obj
gcc -m32 myfile.obj -o myfile.exe

如何修改才能支持任意类型的输入?

编辑补充:
把终端代码页设为1252确实解决了示例里的问题,但我需要更通用的方案,比如还是没法正常打印西里尔字符。试过用Unicode代码页(65001),但它会忽略所有非ASCII字符;也直接试过代码页1251,此时õ、ä、ö、ü会被转成俄语的х、д、ц、ь,但输入实际斯拉夫字母时只输出问号。怎么正确解决这个问题?


解决方案

问题根源在于Windows下命令行参数编码、终端代码页与C标准库函数的编码不匹配。要实现通用Unicode支持,需切换到宽字符(UTF-16)处理流程,具体步骤如下:

1. 改用宽字符版本的入口和打印函数

Windows原生命令行参数为UTF-16编码,改用_wmain作为入口点,配合wprintf打印宽字符串,避免编码转换丢失信息。

修改后的NASM代码:

section .data
    input dw `argv = %ls\n`, 0  ; %ls 用于宽字符串格式化

section .bss

section .text
    global _wmain                ; 宽字符版本入口
    extern _wprintf              ; 宽字符版本printf

_wmain:
    push ebp
    mov ebp, esp
    push esi

    mov esi, [ebp + 12]          ; 获取宽字符版argv数组地址
    mov ebx, 1
    mov eax, [esi + ebx * 4]     ; 取第一个命令行参数(宽字符串指针)
    push eax

    push input
    call _wprintf

    pop esi
    mov esp, ebp
    pop ebp
    ret

2. 配置终端支持Unicode输出

编译运行前,在命令行执行以下命令,将终端切换为UTF-8代码页:

chcp 65001

3. 编译命令保持不变

继续使用原编译命令即可:

nasm -f win32 myfile.asm -o myfile.obj
gcc -m32 myfile.obj -o myfile.exe

原理说明

  • _wmain直接接收Windows系统传递的UTF-16编码命令行参数,跳过ANSI代码页转换环节,避免非ASCII字符丢失或乱码。
  • wprintf会将UTF-16宽字符串转换为终端当前代码页(UTF-8)的编码输出,可正确显示所有Unicode字符,包括西里尔字母、特殊西欧字符等。

若需要更底层控制,也可直接调用Windows API的WriteConsoleW函数,直接向控制台输出UTF-16字符,完全绕过C标准库的编码转换。

内容的提问来源于stack exchange,提问作者tanler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:27:24