2016-09-03 5 views
0

Сегодня делал упражнение с вызовом fgets со сборки. Для передачи файла FILE * в файл я написал mov rdx, [stdin].В сборке Intel x64 почему нужно размещать квадратные скобки вокруг stdin

Но почему это должно быть в квадратных скобках? Потому что мне не нужно значение этого указателя как раз самого указателя. Следует отметить, что lea rdx, [stdin] также не работает. Как я помню, это приводит к тому, что SIGSEGV отправляется в программу.

Как я понимаю, квадратные скобки в операнде mov команда такая же, как и указатель разыменования в C. Также я знаю, что libc динамически связан с моим исполняемым файлом во время выполнения и отображается где-то между стеком и кучей адресного пространства виртуальной памяти программы.

YASM, glibc, Linux x64.

+0

@EmployedRussian: Я оставил тег glibc при редактировании, так как это был вопрос о 'FILE * stdin'. (Разумеется, ответ был не связан с этим, но я мог представить другого человека, который искал ту же проблему, думая, что это связано с glibc.) Также есть тег 'libc'; было бы более целесообразным? –

+0

@PeterCordes Но 'FILE * stdin' не имеет ничего общего с GLIBC: каждый другой libc предоставляет его. И я не думаю, что для тега 'libc' вызывается: вопрос не о библиотеке, а о глобальной переменной типа указателя. –

ответ

2

FILE *stdin; - глобальная переменная типа указателя. Это означает, что значение, хранящееся в статическом местоположении, - это нужный указатель. Поскольку значение значение, которое мы хотим передать, является указателем, хранящимся в месте, помеченном stdin, нам нужно загрузить с [stdin] вместо передачи адреса символа stdin.

Переходя адрес stdinlea 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 может быть на самом деле в ПБС, и данные, которые он указывает на вполне могут быть динамически распределяемой функциями Glibc инициализации.

stdin - непрозрачный указатель. Вам не нужно заботиться о том, на что он указывает, только что он содержит указатель на фактический объект FILE, и это то, что вам нужно передать в fgets.

+0

В c это легко понять, но почему в сборке мы используем скобки вокруг [stdin]. Почему мы разыскиваем указатель, когда нам нужен только указатель? Да, я понимаю разницу между mov rdx, stdin и mov rdx, [stdin]. И я не понимаю, почему работает второй вариант. –

+0

@BulatM. Это вопрос, на который я отвечаю. Я добавил еще одно предложение, чтобы сделать его еще более ясным. –

+0

Но если он объявлен как FILE * stdin (man 3 stdio on my box) в заголовках libc? Как использовать его в сборке? –