汇编中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
相关产品推荐
相关产品推荐

