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

如何在NASM中实现字符串反转输出?

解决NASM 16位汇编字符串反转输出乱码问题

你遇到的这个问题很典型——尝试用16位NASM汇编实现字符串反转输出时,因为没精准控制读取的字符范围,导致输出了内存里的垃圾数据。咱们一步步拆解问题,看看怎么修正。

初始代码与问题分析

先看你最初的实现代码:

BITS 16 
org 0x7C00 

_start: 
    xor ax,ax ; set ax register to 0 
    mov ds,ax ; set data segment(ds) to 0 
    mov es,ax ; set extra segment(es) to 0 
    mov bx,0x8000 
    mov si,string 
    call reverse_print 
    jmp $ 

reverse_print: 
    mov ah,0Eh 
.rep_pre: 
    inc si 
    cmp al,0 
    je .rep_init 
    jmp .rep_pre 

.rep_init: 
    dec si 
    jmp .rep 

.rep: 
    std lodsb 
    cmp al,0 
    je .done 
    int 10h 
    jmp .rep 

.done: 
    cld 
    ret 

string db "ABC",0 
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s 
dw 0xAA55 ; The standard PC boot signature 

这段代码的核心问题在于:

  • .rep_pre循环里用cmp al,0判断是否到达字符串末尾,但al寄存器初始没有被赋值,这个判断完全无效,循环会一直执行直到越界,读取到内存里的随机数据
  • 后续.rep循环从错误的位置开始反向读取,直到遇到0才停止,自然会输出一堆乱码(你看到的A鈹溾伩 鈱∥樷瘓=鈾就是越界读取的垃圾数据)

修正思路与最终代码

你通过引入CX寄存器作为计数器的思路完全正确——用CX记录字符串的长度,就能精准控制反向读取的字符数量,避免越界。修正后的代码如下:

BITS 16 
org 0x7C00 

_start: 
    xor ax,ax ; set ax register to 0 
    mov ds,ax ; set data segment(ds) to 0 
    mov es,ax ; set extra segment(es) to 0 
    mov bx,0x8000 
    mov si,string 
    call reverse_print 
    jmp $ 

reverse_print: 
    mov ah,0Eh 
    mov cx,1 ; 初始化计数器,初始值对应字符串起始位置

.rep_pre: 
    inc si 
    inc cx ; 每移动一个字符,计数器加1
    cmp al,0 
    je .rep_init 
    jmp .rep_pre 

.rep_init: 
    inc si 
    inc cx 
    jmp .rep 

.rep: 
    std lodsb ; 反向读取字符
    dec cx ; 计数器减1
    cmp al,0 
    je .done 
    cmp cx,0 
    jl .done ; 计数器小于0时停止,避免读取多余数据
    int 10h ; 调用BIOS中断输出字符
    jmp .rep 

.done: 
    cld ; 恢复方向标志位
    ret 

string db "ABC",0 
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s 
dw 0xAA55 ; The standard PC boot signature 

关键修改点说明:

  1. 添加CX计数器:用CX记录字符串的总长度(包括终止空字符),确保我们只读取有效字符
  2. 同步计数器与SI指针:.rep_pre循环里每次移动SI指针时,同步递增CX,准确统计字符总数
  3. 终止条件优化:在.rep循环里,除了判断是否读取到终止符0,还通过cmp cx,0判断计数器是否耗尽,避免越界读取垃圾数据
  4. 调整指针定位:.rep_init里的调整确保SI刚好指向字符串末尾的前一个有效字符,保证反向读取从最后一个有效字符"C"开始

修正后结果

现在执行代码,就能得到你期望的输出:

CBA

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:02:11