Практически любая программа кроме машинных команд содержит также какие-то данные. Например, числа, текстовые строчки, идентификаторы, различные ресурсы и т.д. Данные могут быть как константами, не меняющими своё значение во время выполнения программы, так и переменными, в которых хранятся всякие промежуточные результаты.
Прежде всего нужно научиться объявлять данные в программе. Для этого в ассемблере существуют директивы объявления данных.
Размер (в байтах) | Объявление | Резервирование |
---|---|---|
1 | db | rb |
2 | dw du | rw |
4 | dd | rd |
6 | dp df | rp rf |
8 | dq | rq |
10 | dt | rt |
N | file |
В учебном курсе для нас самыми полезными будут директивы db, dw и dd.
Синтаксис объявления данных
Объявлять данные очень просто — например, чтобы объявить байт cо значением 5 достаточно написать:
1 | x db 5 |
где x — название нашей переменной или константы, db — директива объявления байта, а 5 — значение. С помощью названия в программе можно будет обращаться к ячейке памяти, содержащей наш байт. Вообще, название не обязательно и можно его не писать, если оно не требуется:
1 | db 5 |
Если запустить программу в отладчике Turbo Debugger, то в окне дампа можно увидеть результат работы директивы db:

Объявление последовательностей (массивов)
Иногда в программе требуется объявить массив, то есть несколько переменных одинакового размера, расположенных в памяти друг за другом. Например, чтобы объявить массив из 5 двухбайтных чисел можно написать:
1 | array1 dw 1,2,3,4,5 |
где array1 — название массива, 1,2,3,4,5 — значения элементов. Вместо array1 компилятор FASM будет подставлять в программу адрес начала массива, то есть адрес первого элемента.
Дамп памяти будет выглядеть следующим образом (обратите внимание, младший байт каждого слова расположен перед старшим):

Для объявления повторяющихся элементов можно использовать такую запись (объявляем массив из 5 байтов, равных 1):
1 | array2 db 5 dup(1) |

А ещё можно вот так объявить массив (догадайтесь сами, что тут получается):
1 | array3 dd 4 dup(3,7,0) |
Объявление строк
Строка представляет собой массив байтов-символов и записывается в одинарных кавычках:
1 | str1 db 'Hello' |

Для обозначения конца строки используется специальный символ. Обычно это нулевой байт, но для функций DOS используется символ ’$’.
1 2 | str2 db 'Hello',0 ;Обычно так str3 db 'Hello$' ;Для DOS |

Резервирование данных (точнее памяти для них)
Можно объявлять переменные, не имеющие определённого начального значения. Такие переменные называются неинициализированными. Например, их можно использовать в программе для хранения временного или промежуточного значения. Фактически под переменную просто резервируется место в памяти. Объявлять такие переменные можно с помощью директив db, dw, dd, … и знака вопроса вместо значения.
1 2 3 | x1 db ? x2 dw ?,?,? x3 dd 10 dup(?) |
Кроме того, FASM поддерживает специальные директивы резервирования данных. Число после директивы обозначает количество резервируемых элементов. То же самое можно объявить вот так:
1 2 3 | x1 rb 1 x2 rw 3 x3 rd 10 |
С неинициализированными переменными следует быть внимательным. Не надо рассчитывать, что по умолчанию значение будет нулевым или ещё каким-то, иначе это может привести к ошибке.
Директива file
file — это особая директива объявления данных, которая позволяет добавить в исполняемый файл последовательность байтов из внешнего файла. Иногда это может быть очень удобно. Например, если вы хотите добавить изображение в исполняемый файл (в виде данных), или большой кусок текста, или даже код из другого файла. Директива используется следующим образом:
1 2 3 | data1 file 'data.bin' ;Добавить файл data.bin целиком. data2 file 'data.bin':20 ;Добавить байты из файла data.bin, начиная со смещения 20. data3 file 'data.bin':20,5 ;Добавить 5 байтов из файла data.bin, начиная со смещения 20. |
4 ответа к “Учебный курс. Урок 5. Директивы объявления данных”
что-то я не понимаю =( В таблице директив db идёт за два байта, вместо одного, а dw за четрые, вместу двух
Посмотрите еще раз!
Дериктива db — declare byte (объявить байт)
Дериктива dw — declare word (объявить слово или 2 байта)
Вот такой моментик из примера вызвал вопрос:
array3 dd 4 dup(3,7,0)
В первом байте число 3, во втором 7, в третьем 0, а потом все по новой (4-й = 3, 5-й = 7, 3-й = 0).
Но ведь в моей логике размышлений какая-то ошибка?
Ошибка :)
Если мы используем директиву объявления dd, то мы объявляем двойное слово (dd = Define Dword).
На пальцах: в первое двойное слово в памяти записывается число 3, во второе двойное слово 7, в третье 0.
Ну и 4 раза по аналогии.