汇编中NULL字符未终止字符串:是否混淆C与汇编逻辑?
问题:汇编代码输出不符合预期的原因分析
你正在学习汇编语言并编写了一段测试代码:
1 global _start 2 3 section .data 4 msg db "HelloWo",0,10,117 5 lenmsg equ $-msg 6 7 section .text 8 _start: 9 mov eax , 4 10 mov ebx , 1 11 mov ecx , msg 12 mov edx , lenmsg 13 int 0x80 14 mov eax ,1 15 mov ebx ,0 16 int 0x80
原本预期输出为HelloWo,因为在"o"后有一个NULL(\0)字符,但实际所有字符都被输出到控制台,结果为:
HelloWo u
编译运行命令:
nasm -f elf32 tes.asm -o tes.o [[ -f tes.o ]] && ld -m elf_i386 tes.o -o tes [[ -f tes ]] && ./tes
提问:我的理解误区在哪里?是否混淆了C语言与汇编语言的逻辑?
解答
你的核心误区就是混淆了C语言字符串的规则和Linux系统调用的底层逻辑:
- C语言里的字符串依赖
\0作为终止符,printf、puts这类库函数会自动识别\0并停止输出;但你用的是Linux的int 0x80系统调用(eax=4对应write系统调用),它完全不关心\0——它只会严格按照你在edx里指定的长度(也就是lenmsg,这里等于整个msg的字节数:"HelloWo"7个字符+0+换行符(10)+字符'u'(117),共10字节),从ecx指向的内存地址开始,输出对应长度的所有字节。 - 你定义的
lenmsg equ $-msg计算的是从msg标签到当前位置的字节差,也就是整个msg数据段的总长度,所以write会把这些字节全部输出到控制台。
如果要实现只输出HelloWo,有两种简单方式:
- 方式一:调整
msg的定义,只保留"HelloWo",让lenmsg自动计算为7字节; - 方式二:手动将
edx的值设为7,替代lenmsg,强制write只输出前7个字符。
内容的提问来源于stack exchange,提问作者mНBr
相关产品推荐
相关产品推荐

