Запись строки в память
Учусь работать с отладчиком GDB - разбираю пример простой программы на языке C. Пример из учебника, так что не ругайтесь за код. Тем более что вопрос по компиляции/ассемблеру.
#include <stdio.h>
#include <string.h>
int main( )
{
char str_a[20];
strcpy(str_a, "Hello, world!\n");
printf(str_a);
}
Компилировал gcc 11.1.0 с флагами -g -no-pie .
Дизассемблированный код в интересующем меня месте выглядит так:
...
<main+27>: lea rax , [rbp-0x20]
<main+31>: movabs rcx , 0x77202c6f6c6c6548
<main+41>: mov QWORD PTR [rax] , rcx
<main+44>: mov DWORD PTR [rax+0x8] , 0x646c726f
<main+51>: mov WORD PTR [rax+0xc] , 0xa21
<main+57>: mov BYTE PTR [rax+0xe] , 0x0
...
Пример полного дизассемблера можно посмотреть на godbolt здесь. Он чуть отличается от того, что у меня gdb выдает, но приведенная часть аналогичная.
Вопрос такой: почему первые 8 байт записываются в память в две инструкции <main+31>, <main+41> через использование регистра rcx , а оставшиеся 7 байт записываются напрямую? Могу понять, почему, к примеру, ради 1 байта нуль-терминатора нецелесообразно целый регистр какой-нибудь задействовать. Но почему в таком случае и первые 8 байт тоже не записываются напрямую по подобию других?
***** UPDATE *****
Спасибо @Fat-Zer за ответ. Действительно, нет такой инструкции, которая бы напрямую пересылала 64-битный константный аргумент в память. Сверился по мануалу Intel (для инструкции mov можно посмотреть Vol. 2B 4-35)
Также благодарность за комментарий @Илья К, который указал на существующее ограничения максимальной длины инструкции в 15 байт.
Ответы (1 шт):
Но почему в таком случае и первые 8 байт тоже не записываются напрямую по подобию других?
В наборе команд amd64 банально нет инструкции, пересылающей 64-х-битный константный аргумент команды (в отличии от 32-х-битных и меньше) напрямую в память. Поэтому приходится помещать его сначала в регистр, и только потом сохранить в память.
А две инструкции записывающие по 4 байта сразу в память, как подметил @avp, занимали бы, как минимум, просто больше места: 14 байт против 13, хотя, возможно, у компилятора были и какие-то другие причины так сделать.
Почему именно такой инструкции нет — стоит спросить у инженеров AMD. Как подсказывает @ИльяК, одна из причин, почему такой команды нет, вероятно, в том, что для некоторых типов адресации она получилось бы слишком большой: 8 байт на адрес и 8 байт на аргумент + собственно опкод, что не поместилось бы, в частности, в 128-ми битную шину предекодера инструкций на K8.