In assembly Intel x64 why should place square brackets around stdin
今天正在做练习,从集会上打电话给妇女权利委员会。为了将文件*传递到文件流,我编写了mov rdx, [stdin]。
但为什么要用方括号括起来呢?因为我不需要指针的值,只需要指针本身。应该提到,lea rdx,[stdin]也不起作用。我记得,它会使sigsegv被发送到程序。
据我所知,mov指令操作数中的方括号与C中的解引用指针的含义相同。此外,我还知道libc在运行时动态链接到我的可执行文件,并映射到程序虚拟内存地址空间的堆栈和堆之间的某个位置。
Yasm、Glibc、Linux x64。
- @受雇的俄罗斯人:我在编辑时留下了glibc标签,因为它是关于FILE *stdin的问题。(当然,答案与此无关,但我可以想象,另一个搜索同一问题的人认为这与glibc有关。)还有一个libc标签;这是否更合适?
- @彼得命令,但FILE *stdin也与glibc没有太多关系:其他所有libc都提供它。我也不认为需要libc标记:问题不是关于库,而是关于指针类型的全局变量。
FILE *stdin;是指针类型的全局变量。这意味着存储在静态位置的值就是所需的指针。由于要传递的值是存储在标有stdin的位置的指针,因此需要从[stdin]加载,而不是传递stdin符号的地址。
如果把stdin的地址(带lea rdx, [rel stdin]的地址)声明为FILE stdin并在c中用作fgets(buf, size, &stdin)的地址,则通过该地址是有效的。
libc对FILE *stdin;的定义等同于这个asm。
1 2 3 4 5 6 7 8 9
| 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 in it函数动态分配。
stdin是一个不透明指针。你不需要关心它指向什么,只要它包含一个指向实际FILE对象的指针,这就是你需要传递给fgets的内容。
- 在C语言中很容易理解,但是为什么在汇编中我们在[stdin]周围使用括号。当我们只需要指针插入时,为什么要取消对指针的引用?是的,我理解mov rdx、stdin和mov rdx,[stdin]之间的区别。我不明白为什么第二种变体会起作用。
- @布拉姆。这就是我要回答的问题。我又加了一个句子,让它更清楚。
- 但如果它像libc头文件中的file*stdin(我的框中的man 3 stdio)一样声明?如何在组装中使用它?
- 查看编译器输出以使用普通的int全局变量:godbolt.org/g/3tgrbd。仅仅因为全局包含一个指针值,并不意味着当C按值传递一个变量时就传递地址。
- 实际上,lea rdx中的rel,[rel stdin]是什么意思?
- 与NASM中的DEFAULT REL相同:在编写[stdin]时,使用rip相对地址而不是绝对地址。
- 与绝对寻址相比,RIP相对寻址的好处是什么?哪一个是首选的?