#assembly #x86 #x86-64 #gnu-assembler
#сборка #x86 #x86-64 #gnu-ассемблер
Вопрос:
Я пишу программу на ассемблере (с icc в качестве ассемблера). Мне нужно записать некоторые константы в раздел данных для относительной загрузки rip в основной программе, например, для следующей инструкции:
vmovdqu msg(%rip),%ymm0
Теперь я пишу раздел данных следующим образом:
.data
msg: 0x00000000 0x01000000 0x02000000 0x03000000 0x04000000 0x05000000 0x06000000 0x07000000
Однако ассемблер выдает ошибку: test1.s: 140725: Ошибка: мусор в конце строки, первый нераспознанный символ равен `0′.
Кто-нибудь может привести мне пример того, как правильно отформатировать этот раздел данных?
Комментарии:
1. У icc действительно есть встроенный ассемблер или он просто вызывает GNU as? Синтаксис для сборки 32-разрядных значений в GNU как бы выглядит
.data ; msg: .int 0x00000000, 0x01000000, ...
.2. Это отвечает на вопрос, ха-ха. Спасибо
3. @NateEldredge: Вывод ICC asm — это синтаксис GAS, если вы запросите его с помощью
-S
(или GNU .intel_syntax). Если у него есть встроенный ассемблер, подобный clang, он использует совместимый синтаксис.4. Если вам не нужно изменять эти константы, то они не должны находиться в
.data
сегменте. Вы можете поместить их в.rodata
раздел, там же, где это сделал бы компилятор. Относительная адресация RIP может использоваться для доступа к.text
,.data
. and.rodata
и большинству других сегментов в программе.
Ответ №1:
Это похоже на синтаксис, используемый ассемблером GNU (GAS). В x86-64 директива для сборки 32-разрядных целочисленных данных является любой из .int
, .long
или .4byte
(они являются синонимами). (Примечание .long
означает 4 байта, даже если тип C long int
составляет 8 байт на этой платформе.)
Несколько значений могут быть разделены запятыми.
Чтобы вы могли написать
.data
msg: .int 0x00000000, 0x01000000, 0x02000000, 0x03000000 # and so on
Также доступны .byte
, .word / .2byte
и .quad / .8byte
для 8-, 16- и 64-разрядных целых чисел.
Смотрите руководство GAS для получения более подробной информации.
Дополнительные комментарии, предложенные Питером Кордесом (спасибо!):
Поскольку это будет загружено как вектор, вы, вероятно, захотите убедиться, что оно выровнено по 32-байтовой границе, что можно сделать, поместив .balign 32
директиву непосредственно перед msg:
меткой.
Если это действительно константа и ее не нужно записывать в другое место вашей программы, то лучше всего поместить ее в раздел данных, доступный только для чтения, используя .section .rodata
вместо .data
. Это позволит поместить его в общую память, если несколько процессов одновременно запускают вашу программу, а также гарантирует, что вы получите исключение, если попытаетесь записать его по ошибке.
Комментарии:
1. Если вы собираетесь написать ответ, я бы предложил использовать
.balign 32
перед меткой, чтобы векторная загрузка определенно не была разделением строки кэша или страницы. Также эти константы должны входить.rodata
, как указал @Ross в вопросе.