x86汇编中len1 equ $-msg1为何包含msg2?单次系统调用打印两条消息原因
问题原因
核心问题出在对汇编位置计数器$和equ伪指令的理解有误,另外代码的段声明也存在语法错误。
- 先明确两个基础汇编规则:
$代表汇编过程中当前位置计数器的值,对应正在汇编内容的内存偏移,每分配1字节的指令或数据,位置计数器就加1。equ是纯汇编期的常量定义,本身不会生成任何指令或数据,也不会推动位置计数器移动,它的值完全由书写这行代码时的位置计数器即时计算得到。
- 你的代码把
len1: equ $-msg1写在了msg2的定义之后:
数据段内的分配顺序是先为msg1分配12字节("Hello world"加换行符共12个字符),再为msg2分配13字节("Hello world!"加换行符共13个字符),等汇编到len1的equ定义时,位置计数器已经走到了msg2的末尾,此时$-msg1的计算结果是msg1长度 + msg2长度 = 25,根本不是msg1单独的长度。 - 调用
write系统调用时传入的输出长度是25,系统会从msg1起始地址开始连续读取25个字节输出,自然把紧随其后的msg2内容也一起打印了。
额外提一下代码里的段声明语法错误:section.text:和section.data:的写法非法,section伪指令和段名之间必须加空格,段名以.开头,且段声明后不需要加冒号,正确写法是section .text和section .data。这个问题不会直接导致本次输出异常,但会让汇编器无法正确识别段切换,所有代码和数据都会被汇编到默认段中,造成程序段布局不符合预期。
修复方法
把每个字符串对应的长度equ定义,紧跟在对应字符串的定义之后,保证计算长度时位置计数器刚好走到当前字符串的末尾即可,修正后的data段写法如下:
section .data msg1: db "Hello world", 10 len1: equ $-msg1 ; 此时位置计数器刚好在msg1末尾,计算得到长度12 msg2: db "Hello world!", 10 len2: equ $-msg2 ; 此时位置计数器刚好在msg2末尾,计算得到长度13
修正后len1的值为12,write调用只会输出msg1的内容,不会连带打印msg2。
内容的提问来源于stack exchange,提问作者Alex Quchuloria
相关产品推荐
相关产品推荐

