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

x86汇编两次输出字符串至控制台异常问题排查

x86汇编多字符串输出乱码问题解决

问题场景

作为x86汇编新手,编写控制台输出程序时,单个字符串输出正常,但添加第二个字符串后出现乱码。

单字符串正常代码:

section .data
    str: db "0000", 0xA
    len: db 5

global _start

section .text
_start:
    ; system call to print the string
    mov eax, 4  ; "write" system call
    mov ebx, 1  ; Indicates to write to standard out
    mov ecx, str    ; The string
    mov edx, [len]  ; The length of the string
    int 0x80

    ; exit the program
    mov eax, 1
    mov ebx, 0
    int 0x80

添加第二个字符串后的出错代码:

section .data
    str: db "0000", 0xA
    len: db 5
    otherStr: db "1111", 0xA
    otherLen: db 5

global _start

section .text
_start:
    ; system call to print the string
    mov eax, 4  ; "write" system call
    mov ebx, 1  ; Indicates to write to standard out
    mov ecx, str    ; The string
    mov edx, [len]  ; The length of the string
    int 0x80

    ; system call to print the string
    mov eax, 4  ; "write" system call
    mov ebx, 1  ; Indicates to write to standard out
    mov ecx, otherStr   ; The string
    mov edx, [otherLen]     ; The length of the string
    int 0x80

    ; exit the program
    mov eax, 1
    mov ebx, 0
    int 0x80

错误输出:

0000
1111
    
(#
/
    6
    sha.asmstrlenotherStrotherLen__bss_start_edata_end.symtab.strtab.shstrtab.text.dat:! 
                                                                                                ;!'1111

预期输出:

0000
1111

使用环境:Fedora Linux,NASM汇编器,编译链接命令:

nasm -f elf32 example.asm -o ex1.o
ld -m elf_i386 ex1.o -o ex1

错误原因

32位Linux的write系统调用(eax=4)要求edx参数传递32位(双字)长度值,但你用db定义了长度变量(仅占1字节)。当执行mov edx, [len]时,32位寄存器edx会从内存中读取连续4个字节——除了len本身的1字节,剩下3字节会读取到后面的otherStr、otherLen等数据,导致实际传递给系统调用的长度远大于预期,从而输出了多余的内存内容,出现乱码。

第一个程序能正常运行是巧合:len后面没有其他数据,读取的多余3字节可能是零值,刚好长度参数正确,所以输出正常。

修复方法

有两种可行的修复方式:

方式1:用双字定义长度变量

把db改成dd(定义32位双字),确保每个长度变量占4字节,mov edx, [len]会正确读取完整的32位长度值:

section .data
    str: db "0000", 0xA
    len: dd 5  ; 用dd定义双字长度
    otherStr: db "1111", 0xA
    otherLen: dd 5  ; 用dd定义双字长度

global _start

section .text
_start:
    ; 输出第一个字符串
    mov eax, 4
    mov ebx, 1
    mov ecx, str
    mov edx, [len]
    int 0x80

    ; 输出第二个字符串
    mov eax, 4
    mov ebx, 1
    mov ecx, otherStr
    mov edx, [otherLen]
    int 0x80

    ; 退出程序
    mov eax, 1
    mov ebx, 0
    int 0x80

方式2:零扩展字节到32位寄存器

保持db定义长度,使用movzx指令将字节数据零扩展为32位,避免读取多余内存:

; 替换原有的 mov edx, [len]
movzx edx, byte [len]
; 替换原有的 mov edx, [otherLen]
movzx edx, byte [otherLen]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:27:34