Рассмотрим следующую простую программу:
int main(int argc, char **argv)
{
char buffer[256];
buffer[0] = 0x41;
buffer[128] = 0x41;
buffer[255] = 0x41;
return 0;
}
Скомпилирован с GCC 4.7.0 на машине x86-64. Разборка main() с помощью GDB дает:
0x00000000004004cc <+0>: push rbp
0x00000000004004cd <+1>: mov rbp,rsp
0x00000000004004d0 <+4>: sub rsp,0x98
0x00000000004004d7 <+11>: mov DWORD PTR [rbp-0x104],edi
0x00000000004004dd <+17>: mov QWORD PTR [rbp-0x110],rsi
0x00000000004004e4 <+24>: mov BYTE PTR [rbp-0x100],0x41
0x00000000004004eb <+31>: mov BYTE PTR [rbp-0x80],0x41
0x00000000004004ef <+35>: mov BYTE PTR [rbp-0x1],0x41
0x00000000004004f3 <+39>: mov eax,0x0
0x00000000004004f8 <+44>: leave
0x00000000004004f9 <+45>: ret
Почему это sub rsp только с 0x98 = 152d, когда буфер составляет 256 байт? Когда я перемещаю данные в буфер [0], он просто использует данные за пределами выделенного фрейма стека и использует rbp для ссылки, так что даже точка sub rsp, 0x98?
Другой вопрос, что делают эти строки?
0x00000000004004d7 <+11>: mov DWORD PTR [rbp-0x104],edi
0x00000000004004dd <+17>: mov QWORD PTR [rbp-0x110],rsi
Почему EDI, а не RDI необходимо сохранить? Я вижу, что он перемещает это вне максимального диапазона выделенного буфера в коде C. Интересно также, почему дельта между двумя переменными настолько велика. Поскольку EDI составляет всего 4 байта, для чего требуется разделение по 12 байт для двух переменных?