Сводка
NASM 2.10.09 Выход ELF:
db
не имеет магических эффектов: он просто выводит байты напрямуюв выходной объектный файл.
Если эти байты оказываются перед символом, символ будет указывать на это значение при запуске программы.
Если вы находитесь в текстовом разделе,Ваши байты будут выполнены.
Погода, которую вы используете db
или dw
и т. д., которая не определяет размер символа: поле st_size
записи таблицы символов не затрагивается.
equ
заставляет символ в текущей строке иметь st_shndx == SHN_ABS
магическое значение в своей записи таблицы символов.
Вместо вывода байта в текущее местоположение объектного файлаон выводит его в поле st_value
записи таблицы символов.
Все остальное следует из этого.
Чтобы понять, что это на самом деле означает, вам следует сначалапонять основы стандарта ELF и перемещение .
Теория SHN_ABS
SHN_ABS
сообщает компоновщику, что:
- перемещение не должно выполняться для этого символа
- поле
st_value
для ввода символа должно использоваться как значение непосредственно
Сравните это с "обычными" символами, в которых значение символа вместо адреса памяти,и поэтому должен пройти через перемещение.
Так как он не указывает на память, символы SHN_ABS
могут быть эффективно удалены из исполняемого файла компоновщиком, вставив их.
Но они все еще обычныесимволы в объектных файлах и do занимают там память и могут быть распределены между несколькими файлами, если они глобальные.
Пример использования
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
равно 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 состоит в том, чтобы определить данное имя метки для значения его (единственного) операнда.Это определение является абсолютным и не может измениться позже.Так, например,
message db 'hello, world'
msglen equ $-message
определяет msglen как постоянную 12. msglen не может быть затем переопределен позже.Это также не определение препроцессора: значение msglen оценивается один раз, используя значение $ (объяснение $ см. В разделе 3.5) в точке определения, а не вычисляется там, где на него ссылаются, и используя значение$ в точке отсчета.
См. также
Аналогичный вопрос для GAS: Разница между .equ и .word в ARM Assembly? .equiv
похоже на закрытый эквивалент ГАЗА.