Чем dw и d d отличаются от директив db для строк?
Допустим, я хочу определить инициализированную переменную строку перед запуском моей программы сборки (в section .data
). Переменная, которую я выбрал для создания, называется Digits
и это строка, которая содержит все шестнадцатеричные символы.
Digits: db "0123456789ABCDEF"
Я определил переменную с db
это означает определение байта. Значит ли это, что Digits
переменная длиной 8 бит? Это не имеет смысла для меня, потому что:
Каждый символ в строке является символом ASCII, поэтому мне потребуется 2 байта для каждого символа. В общей сложности мне понадобится 32 байта для всей строки!
Так что это значит, когда я определяю переменную как байт? Слово? Двойное слово? Я не вижу разницы. Из-за моего недопонимания кажется излишним указывать тип данных, которые вам нужны для строки.
П.Д.: Этот вопрос не помог мне понять.
2 ответа
Один из ответов на связанный вопрос содержит цитату из примеров руководства NASM, которая действительно отвечает на ваш вопрос. В соответствии с просьбой, я расширю его для всех трех случаев (и исправлю ошибку кодирования ASCII в нижнем и верхнем регистре!):
db 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 (5 bytes)
dw 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 (6 bytes, 3 words)
dd 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 0x00 0x00 (8 bytes, 2 doublewords)
dq 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 0x00 0x00 (8 bytes, 1 quadword)
Таким образом, разница заключается в том, что при использовании он увеличивается в несколько раз по размеру элемента с нулями dd
или же dw
вместо db
,
Согласно комментарию @Jose, некоторые ассемблеры могут использовать другой порядок байтов для dd
или же dw
строковые константы. В синтаксисе NASM строка всегда сохраняется в памяти в том же порядке, в котором она указана в константе в кавычках.
Вы можете собрать это с NASM (например, в плоский двоичный вывод по умолчанию) и использовать hexdump -C
или что-то, чтобы подтвердить порядок байтов и количество заполнения.
Обратите внимание, что это дополнение к размеру элемента применяется к каждому элементу, разделенному запятыми. Так что, казалось бы, невинный dd '%lf', 10, 0
на самом деле собирается так:
;dd '%lf', 10, 0
db '%lf',0, 10,0,0,0, 0,0,0,0 ;; equivalent with db
Обратите внимание 0
до новой строки; если вы передадите указатель на это printf
, строка C просто "%lf"
, прекращено первым 0
байт.
(write
системный вызов или fwrite
функция с явной длиной напечатает все это, включая 0
байты, потому что эти функции работают с двоичными данными, а не со строками C неявной длины.)
Хочу кое-что уточнить:
example: db 'ABCDE';
Всего резервируется 5 байтов, каждый из которых содержит букву.
ex2: db 1 ;
резервирует байт, содержащий 1
ex3: db "cool;
резервирует 4 байта, и каждый байт содержит букву
ex4: db "cool", 1, 3;
резервирует 3 байта?
ответы: ex4 - 6 байт
Для каждого символа в строке "0123456789ABCDEF" вам нужен всего один байт. Итак, строка будет занимать 16 байт в памяти.
В случае этой декларации:
Vark DB 1
Вы можете сделать это:
мов [vark],128
и не может:
мов [vark],1024
но в этом случае:
vark dw 1
вы можете.