Что делают инструкции mov %edi и mov %rsi?
Я написал базовую программу C, которая определяет целочисленную переменную x, устанавливает ее в ноль и возвращает значение этой переменной:
#include <stdio.h>
int main(int argc, char **argv) {
int x;
x = 0;
return x;
}
когда я сбрасываю объектный код с помощью objdump (скомпилированный на Linux X86-64 с gcc):
0x0000000000400474 <main+0>: push %rbp
0x0000000000400475 <main+1>: mov %rsp,%rbp
0x0000000000400478 <main+4>: mov %edi,-0x14(%rbp)
0x000000000040047b <main+7>: mov %rsi,-0x20(%rbp)
0x000000000040047f <main+11>: movl x0,-0x4(%rbp)
0x0000000000400486 <main+18>: mov -0x4(%rbp),%eax
0x0000000000400489 <main+21>: leaveq
0x000000000040048a <main+22>: retq
Я вижу пролог функции, но прежде чем мы установим x в 0 по адресу 0x000000000040047f
есть две инструкции, которые перемещают %edi и %rsi в стек. Для чего это?
кроме того, в отличие от того, где мы установили x в 0, mov инструкция, как показано в синтаксисе GAS, не имеет суффикса.
если суффикс не указан, и для инструкции нет операндов памяти, GAS выводит размер операнда из размера операнда регистра назначения.
в этом случае -0x14(%rsbp)
и -0x20(%rbp)
оба операнда памяти и каковы их размеры? Поскольку %edi является 32-битным регистром, 32 бита перемещаются в -0x14(%rsbp)
в то время как %rsi является 64-битным регистром, 64 бита перемещаются в %rsi,-0x20(%rbp)
?
2 ответов
в этом простом случае, почему бы вам не задать ваш компилятор напрямую? Для GCC, clang и ICC есть .
main:
pushq %rbp #
movq %rsp, %rbp #,
movl %edi, -20(%rbp) # argc, argc
movq %rsi, -32(%rbp) # argv, argv
movl , -4(%rbp) #, x
movl -4(%rbp), %eax # x, D.2607
popq %rbp #
ret
Итак, да, они спасают argv
и argv
в стек, используя" старый " метод указателя кадра, так как новые архитектуры позволяют вычитать/добавить из / в указатель стека напрямую, таким образом, опуская указатель кадра (-fomit-frame-pointer
).
основываясь на этом и контексте, я не эксперт, но я предполагаю, что они захватывают main()
параметры ввода. EDI принимает стандартную ширину, которая будет соответствовать int argc
, тогда как RSI занимает много времени, что соответствует char **argv
указатель.