использование параметра контейнера в начальной загрузке?

Сводка

NASM 2.10.09 Выход ELF:

  • db не имеет никаких магических эффектов: он просто выводит байты непосредственно в выходной файл объекта. Если эти байты находятся перед символом, символ будет указывать на это значение при запуске программы. Если вы находитесь в текстовом разделе, ваши байты будут выполнены. Погода, которую вы используете db или dw и т. Д., Которая не указывает размер символа: поле st_size в записи таблицы символов не влияет.
  • equ делает символ в текущей строке есть волшебное значение st_shndx == SHN_ABS в его записи в таблице символов. Вместо вывода байта в текущее местоположение объекта объекта он выводит его в поле st_value записи в таблице символов.

Все остальное следует из этого.

Чтобы понять, что это на самом деле означает, вы должны сначала понять основы стандарта ELF и relocation .

Теория SHN_ABS

SHN_ABS сообщает компоновщику, что:

  • перемещение не должно выполняться на этом символе
  • поле st_value записи символа должно использоваться как значение непосредственно

Контрастируйте это с «регулярными» символами, в которых значение символа является адресом памяти вместо этого, и поэтому необходимо переместить.

Поскольку это не указывает на память, символы SHN_ABS могут быть эффективно удалены из исполняемого файла компоновщиком, вставляя их.

Но они все еще являются регулярными символами в объектных файлах, а делают там, где есть глобальная память.

Пример использования

section .data
    x: equ 1
    y: db 2
section .text
global _start
_start:
    mov al, x
    ; al == 1
    mov al, [y]
    ; al == 2

Обратите внимание, что поскольку символ x содержит буквальное значение, для него не должно быть никакого разыменования [], как для y.

Если мы хотели использовать x из программы C нам понадобится что-то вроде:

extern char x;
printf("%d", &x);

и установить на asm:

global x

Эмпирическое наблюдение сгенерированного выхода

Мы можем наблюдать, что мы говорили ранее:

nasm -felf32 -o equ.o equ.asm
ld -melf_i386 -o equ equ.o

Теперь:

readelf -s equ.o

содержит:

Num:    Value  Size Type    Bind   Vis      Ndx Name
  4: 00000001     0 NOTYPE  LOCAL  DEFAULT  ABS x
  5: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 y

Ndx is st_shndx, поэтому мы видим, что x есть SHN_ABS, а y - нет.

Также см., что Size есть 0 для y: db никоим образом не сказано y, что он был шириной в один байт. Мы могли бы просто добавить две директивы db для размещения там 2 байтов.

И затем:

objdump -dr equ

дает:

08048080 <_start>:
 8048080:       b0 01                   mov    $0x1,%al
 8048082:       a0 88 90 04 08          mov    0x8049088,%al

Итак, мы видим что 0x1 был введен в инструкцию, а y получил значение адреса переадресации 0x8049088.

Проверено на Ubuntu 14.04 AMD64.

Документы

http://www.nasm.us/doc/nasmdoc3.html#section-3.2.4 :

EQU определяет символ для заданного значения постоянной : когда используется EQU, строка источника должна содержать метку. Действие EQU состоит в том, чтобы определить данное имя метки для значения его (только) операнда. Это определение является абсолютным и не может измениться позже. Так, например,

blockquote>
message         db      'hello, world' 
msglen          equ     $-message

определяет msglen как константу 12. msglen не может затем переопределяться позже. Это также не определение препроцессора: значение msglen оценивается один раз, используя значение $ (см. Раздел 3.5 для объяснения $) в точке определения, вместо того, чтобы оцениваться везде, где оно ссылается, и используя значение $ в точке отсчета.

blockquote>

См. также

Аналогичный вопрос для GAS: Разница между .equ и .word в ARM Assembly? .equiv, похоже, закрывает эквивалент GAS.

10
задан hlcfan 27 May 2014 в 08:05
поделиться