Как записать константы в сегмент данных в сборке x86

#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 в вопросе.