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

汇编中db命令的空字符作用是什么?附测试案例分析

汇编.data段中空字符(0)的作用解析

首先明确核心:C标准库的字符串处理函数(比如你用到的printf),是以空字符\0(汇编里写为0)作为字符串的终止标志的。你写的三组测试代码,本质就是验证了这个规则,下面逐一拆解:

代码1:正确写法(所有字符串加0结尾)

section .data
        out: db "%s",10,0
        mes1: db "a",0
        mes2: db "b",0
section .text
        extern printf
        global main
main:
        push rbp
        mov rdi,out
        mov rsi,mes1
        mov rax,0
        call printf
        mov rdi,out
        mov rsi,mes2
        mov rax,0
        call printf
        pop rbp
        mov rax,0
        ret

这里的out格式串、mes1、mes2都用,0结尾,printf能准确识别每个字符串的边界:

  • 第一次调用printf时,格式串"%s\n\0"告诉函数:先输出rsi指向的字符串(mes1的"a\0"),然后输出换行,之后格式串结束。
  • 第二次调用同理,输出mes2的"b"加换行,结果完全符合预期。

代码2:格式串未加0结尾

section .data
        out: db "%s",10 ; no 0
        mes1: db "a",0
        mes2: db "b",0

out格式串没有加0,printf就不知道格式串在哪里结束,会从out的地址开始越界读取后续内存,直到偶然遇到0为止。
你的内存布局里,out的内容是'%' 's' '\n',后面紧接着就是mes1的'a' 0,所以printf会把"%s\n\a\0"当成格式串来解析:

  • 第一次调用时,%s输出mes1的"a"加换行,然后格式串里的'a'不是格式符,直接输出,于是第一行是a,第二行是ab;
  • 后续因为格式串越界读取导致寄存器/栈状态混乱,又输出了a,出现了不可预测的结果。

代码3:输出字符串未加0结尾

section .data
        out: db "%s",10,0
        mes1: db "a"
        mes2: db "b"

mes1和mes2没有加0,printf用%s输出时,会从mes1的地址开始读,直到遇到0:

  • mes1后面紧接着就是mes2的'b',而mes2之后的内存刚好有0(可能是.data段的末尾填充),所以第一次printf会把"ab"当成一个完整字符串输出;
  • 第二次printf读取mes2的'b'后遇到0,所以输出b,这就是你看到的结果。

总结一下:

  • 用db定义要给C标准库函数用的字符串时,必须手动添加,0作为终止符;
  • 没有终止符的话,函数会越界读取内存,导致输出错误、程序崩溃等不可控行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 08:05:21