【问题标题】:In assembly Intel x64 why should place square brackets around stdin在汇编英特尔 x64 中,为什么要在标准输入周围放置方括号
【发布时间】:2016-09-03 19:47:54
【问题描述】:

今天正在练习从程序集中调用 fgets。 为了将 FILE* 传递给文件流,我写了mov rdx, [stdin]

但为什么要放在方括号中?因为我不需要该指针的值,只需要指针本身。应该提一下,那个 lea rdx, [stdin] 也不起作用。我记得,它会导致 SIGSEGV 被发送到程序。

据我所知,mov 指令操作数中的方括号与 C 中的取消引用指针相同。另外我知道 libc 在运行时动态链接到我的可执行文件,并映射到程序的虚拟内存地址空间的堆栈和堆之间的某个位置.

YASM、glibc、Linux x64。

【问题讨论】:

  • @EmployedRussian:我在编辑时留下了 glibc 标签,因为它是关于 FILE *stdin 的问题。 (当然,答案与此无关,但我可以想象另一个搜索相同问题的人认为这与 glibc 有关。)还有一个 libc 标签;那会更合适吗?
  • @PeterCordes 但FILE *stdin 也与 GLIBC 没有太大关系:所有其他 libc 都提供了它。而且我认为libc标签也不会被调用:问题不在于库,而在于指针类型的全局变量。

标签: assembly x86 gdb dereference


【解决方案1】:

FILE *stdin;是指针类型的全局变量。这意味着存储在静态位置的值是您想要的指针。由于我们要传递的 value 是一个存储在标记为stdin 的位置的指针,因此我们需要从[stdin] 加载,而不是传递stdin 符号的地址。

如果stdin 的地址(与lea rdx, [rel stdin])被声明为FILE stdin,并且在C 中使用为fgets(buf, size, &stdin),则传递地址将起作用。


libc 对FILE *stdin; 的定义等价于这个asm。

section .data
stdin: dq  stdin_FILE_struct           ; This is a pointer stored in memory

section .bss
...
stdin_FILE_struct:           ;; TOTALLY MADE UP, it's not actually like this
    resq 1                       ; something
    resd 1                       ; something_else
    resb 4096                    ; buffer

stdin 可能实际上在 BSS 中,它指向的数据很可能是由 glibc 的 init 函数动态分配的。

stdin 是一个不透明的指针。你不需要关心它指向什么,只需要它持有一个指向实际 FILE 对象的指针,这就是你需要传递给 fgets 的东西。

【讨论】:

  • 在 c 中很容易理解,但是为什么在汇编中我们在 [stdin] 周围使用括号。当我们只需要指针本身时,为什么要取消引用指针?是的,我了解 mov rdx, stdin 和 mov rdx, [stdin] 之间的区别。而且我不明白为什么第二种变体有效。
  • @BulatM。这就是我要回答的问题。为了更清楚,我又加了一句。
  • 但如果它在 libc 头文件中声明为 FILE *stdin(man 3 stdio on my box)?如何在汇编中使用它?
  • 查看编译器输出以使用普通的int 全局变量:godbolt.org/g/3TgRbd。仅仅因为全局持有一个指针值并不意味着当C通过值传递变量时你传递地址。
  • 与 NASM 中的 DEFAULT REL 相同:在编写 [stdin] 时使用 RIP 相对寻址而不是绝对地址。
猜你喜欢
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2021-02-06
  • 2018-06-24
  • 2016-07-13
  • 1970-01-01
  • 2015-11-01
  • 2015-06-23
相关资源
最近更新 更多