NASM字符串未显式定义结束0字节却可正常识别的原因是什么
问题解答
第一个未加终止符的字符串正常运行的原因
这是不可靠的巧合,根本原因是ELF可执行文件的段对齐特性:
- Linux下编译生成的32位ELF程序,
.data段默认会按4字节/16字节对齐,段末尾未使用的填充字节默认填充为0x00 - 你的代码里
msg是.data段唯一定义的变量,'Hello!',0Ah一共7个字节,段对齐时后面补充的填充字节刚好是0,所以字符串遍历的时候刚好碰到这个填充的0作为终止符,才正常运行。
注意:这完全是不可靠的行为,如果
.data段在msg之后还有其他变量定义,或者段对齐规则改变,就会出现读取到垃圾内容、打印乱码甚至段错误的问题,必须按照规范手动添加0h终止符。
第二个sprintLF正常运行的原因
这个是32位x86架构的小端存储特性带来的巧合:
- 你执行
mov eax, 0Ah时,是给32位的eax寄存器赋值,最终eax的完整值是0x0000000A,高24位都是0 - 执行
push eax时,会把32位的eax完整压入栈,小端序下栈上的4个字节从低地址到高地址依次是0x0A、0x00、0x00、0x00 - 你把栈指针
esp传给sprint时,读取到的第一个字节是0xA(换行符),下一个字节刚好就是0x00终止符,所以刚好能正确计算长度。
注意:这同样是不可靠的行为,如果执行
mov eax, 0Ah之前eax的高24位有残留的非0值,就会导致字符串终止符位置错误,必须改为显式压入单字节换行加终止符,或者单独处理换行的打印逻辑,不要依赖寄存器高位默认清0的特性。
内容的提问来源于stack exchange,提问作者user4035
相关产品推荐
相关产品推荐

