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

NASM 64位汇编:字符串字母转字母表序号输出乱码排查

问题排查:NASM 64位汇编字母转字母表序号功能实现错误

代码核心错误

  • 寄存器滥用:将栈指针寄存器esp作为临时变量存储字符值,直接破坏栈内存结构,引发读写异常。
  • 转换逻辑完全错误:
    1. 没有按规则计算序号:小写字母转1-26序号的正确计算方式是字符ASCII值 - 'a' + 1,原代码用xor 0x40属于无意义的位操作,结果完全不对。
    2. 没有做数值转ASCII字符的处理:序号是1-26的整数,不能直接当作ASCII字符写入输出缓冲区——比如序号13是数值,要输出成文本"13"必须拆成'1'(ASCII 0x31)和'3'(ASCII 0x33)两个字符,直接把数值当字符写必然输出乱码,这也是字符'm'转换后输出'-'的根本原因。
  • 标签重复定义:.data段和.bss段定义了同名的string标签,汇编时会出现地址冲突,导致读写内存位置错误。
  • 系统调用混用:64位程序错误使用32位int 0x80中断和32位系统调用号,传参规则不匹配,会导致IO输出异常。
  • 长度计算错误:原字符串32字节,但转换后单字母可能输出1-2位数字,总长度远大于32字节,固定按32字节输出会截断内容,预分配缓冲区长度不足也会引发内存越界。
  • 空格处理错误:遇到空格时写入的是esp寄存器的值(栈指针地址),不是空格的ASCII码0x20,导致空格位置输出乱码。

修正方案

统一遵循64位Linux系统调用规范,重新实现字符遍历、序号计算、数值转ASCII字符的完整逻辑,修正后的可运行代码如下:

SYS_EXIT  equ 60
SYS_WRITE equ 1
STDOUT    equ 1

global    _start

section   .text
_start:
; 打印提示行"e.\r\n"
    mov         rax, SYS_WRITE
    mov         rdi, STDOUT
    mov         rsi, e_msg
    mov         rdx, e_len
    syscall

; 打印原始字符串
    mov         rax, SYS_WRITE
    mov         rdi, STDOUT
    mov         rsi, raw_str
    mov         rdx, raw_len
    syscall
; 打印换行
    mov         rax, SYS_WRITE
    mov         rdi, STDOUT
    mov         rsi, line_break
    mov         rdx, 2
    syscall

; 初始化转换指针:rsi指向原字符串,rdi指向输出缓冲区
    mov         rsi, raw_str
    mov         rdi, out_buf
    xor         r9, r9 ; 原字符串遍历计数

convert_loop:
    cmp         r9, raw_len
    je          print_result
    mov         al, [rsi] ; 取当前字符
    cmp         al, ' '
    je          handle_space
; 处理字母:计算1-26序号
    sub         al, 'a' - 1 ; 等价于减96,得到a=1、b=2...z=26
    mov         bl, 10
    xor         ah, ah
    div         bl ; al存商(十位数值),ah存余数(个位数值)
    cmp         al, 0 ; 判断是否为两位数
    je          write_single_digit
; 两位数先写十位字符
    add         al, '0'
    mov         [rdi], al
    inc         rdi
write_single_digit:
; 写个位字符
    mov         al, ah
    add         al, '0'
    mov         [rdi], al
    inc         rdi
; 移动指针和计数
    inc         rsi
    inc         r9
    jmp         convert_loop

handle_space:
    mov         byte [rdi], ' '
    inc         rdi
    inc         rsi
    inc         r9
    jmp         convert_loop

print_result:
; 动态计算转换后字符串长度
    mov         rdx, rdi
    sub         rdx, out_buf
    mov         rax, SYS_WRITE
    mov         rdi, STDOUT
    mov         rsi, out_buf
    syscall
; 打印结尾换行
    mov         rax, SYS_WRITE
    mov         rdi, STDOUT
    mov         rsi, line_break
    mov         rdx, 2
    syscall

; 程序退出
    mov         rax, SYS_EXIT
    xor         rdi, rdi
    syscall

section   .data
e_msg:          db        "e.", 0xA,0xD
e_len           equ       $ - e_msg
raw_str:        db        "mostra os objetos e os morfismos"
raw_len         equ       $ - raw_str
line_break:     db        0xA,0xD

section   .bss
out_buf:        resb        128 ; 分配足够缓冲区避免越界

编译运行验证

使用以下命令编译执行:

nasm -f elf64 convert.asm -o convert.o
ld convert.o -o convert
./convert

运行输出与预期完全一致:

e.
mostra os objetos e os morfismos
13151920181 1519 152105201519 5 1519 1315186919131519

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:03:25