【发布时间】:2019-10-27 16:20:31
【问题描述】:
所以我正在编写一个基于菜单的程序,它可以显示一条消息(以及我尚未实现的其他功能)。我有以下部分:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
无论出于何种原因,这都会输出存储在msg 中的字符串,以及我存储在.data 部分中的所有其他字符串。我已经用 gdb 运行了程序,并在系统调用之前打印了 rsi 和 rdx 的内容——它们包含我想要输出的字符串和该字符串的长度,正如预期的那样。但是在系统调用之后,rax 包含 2048。如果我理解正确,这意味着 2048 个字符被写入控制台 - 比我在系统调用之前指定的 30 个字符多得多。我猜我的其他字符串是在 msg 存储在内存中的位置之后存储的,这就是它们得到输出的原因,但为什么它忽略了 rdx?
不管怎样,如果msg_len 是不可变的,代码可以正常工作,但我需要它是可变的,因为msg 可以改变。
【问题讨论】:
-
不会
mov rdx, msg_len加载msg_len的地址而不是那里存储的值吗? -
不,它会加载存储在那里的值。我查过了。
-
当您说“可变”时,您的意思是
msg_len: dq msg-$标记一些静态存储吗?如果是这样,那么是的,mov rdx, msg_len将地址放入寄存器,sys_write一直到它到达未映射的内存(因为这比非常大的长度要快)。 IIRC,它确实返回写入的长度,而不是-EFAULT。否则你可能在错误的地方做了msg_len equ msg - $,就像你所有的数据一样。无论如何,这显然不是minimal reproducible example。 -
TL:DR:汇编时 EQU 常量与内存中的数据是完全不同的使用符号/标签的方式,而不是“可变”与“不可变”。我知道您说您打印了 RDX,但是您确定打印时没有取消引用它吗?系统调用不会。
-
你是在 Linux 下运行的,对吧?