问题
Today was doing exercise with calling fgets from assembly.
For passing FILE* to file stream I wrote mov rdx, [stdin]
.
But why it should be in square brackets? Because I do not need value of that pointer just the pointer itself. Should mention, that lea rdx, [stdin] also does not work. As I remember, it causes SIGSEGV to be sent to program.
As I understand square brackets in operand of mov
instruction mean same as dereferencing pointer in C. Also I know that libc is dynamically linked to my executable at runtime and mapped somewhere between the stack and heap of program's virtual memory address space.
YASM, glibc, Linux x64.
回答1:
FILE *stdin;
is a global variable of pointer type. That means the value stored at the static location is the pointer you want. Since the value we want to pass is a pointer stored at the location labelled with stdin
, we need to load from [stdin]
instead of passing the address of the stdin
symbol.
Passing the address of stdin
(with lea rdx, [rel stdin]
) would work if it was declared as FILE stdin
, and used in C as fgets(buf, size, &stdin)
.
libc's definition of FILE *stdin;
is equivalent to this 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
might actually be in the BSS, and the data it points to may well be dynamically allocated by glibc init functions.
stdin
is an opaque pointer. You don't need to care what it points to, just that it holds a pointer to the actual FILE
object, and that's what you need to pass to fgets.
来源:https://stackoverflow.com/questions/39310748/in-assembly-intel-x64-why-should-place-square-brackets-around-stdin