Я скомпилировал эту функцию:
void print_ints(int len, ...){
va_list args;
va_start(args, len);
for(int i =0; i<len ; i++)
{
int val = va_arg(args,int);
printf("i:%i\tval:%i\n",i,val);
}
va_end(args);
}
в эту сборку:
print_ints:
pushq %rbp #
movq %rsp, %rbp #,
subq $224, %rsp #,
movl %edi, -212(%rbp) # len, len
movq %rsi, -168(%rbp) #,
movq %rdx, -160(%rbp) #,
movq %rcx, -152(%rbp) #,
movq %r8, -144(%rbp) #,
movq %r9, -136(%rbp) #,
testb %al, %al #
je .L7 #,
movaps %xmm0, -128(%rbp) #,
...
.L7:
# a.c:7: va_start(args, len);
movl $8, -208(%rbp) #, MEM[(struct [1] *)&args].gp_offset
movl $48, -204(%rbp) #, MEM[(struct [1] *)&args].fp_offset
leaq 16(%rbp), %rax #, tmp100
movq %rax, -200(%rbp) # tmp100, MEM[(struct [1] *)&args].overflow_arg_area
leaq -176(%rbp), %rax #, tmp101
movq %rax, -192(%rbp) # tmp101, MEM[(struct [1] *)&args].reg_save_area
# a.c:9: for(int i =0; i<len ; i++)
movl $0, -180(%rbp) #, i
# a.c:9: for(int i =0; i<len ; i++)
jmp .L3 #
.L6:
# a.c:11: int val = va_arg(args,int);
movl -208(%rbp), %eax # MEM[(struct *)&args].gp_offset, D.2882
cmpl $47, %eax #, D.2882
ja .L4 #,
# a.c:11: int val = va_arg(args,int);
...
Я знаю, что это похоже на беспорядок, но есть некоторая часть вывода, которая меня интересует . Специально такие строки:
movl $8, -208(%rbp) #, MEM[(struct [1] *)&args].gp_offset
Я бы попытался проанализировать это:
MEM[...]
-> может представлять всю память в виде массива (адреса в виде индекса ) MEM[(struct[1]*)...]
-> может представлять тип, который сам этот тип является членом некоторой неизвестной структуры struct[1]*
, а затем дает указатель на тип второго члена этой структуры MEM[(struct[1]*)&args]
-> как только тип данных (длина) указан (struct[1]*
), он находится по адресу переменной args
, поэтому мы знаем, с чего начать MEM[(struct[1]*)&args].gp_offset
-> Итак у нас есть тип, начальный адрес, который вместе дает нам индекс в глобальной таблице памяти, которая получает «некоторое значение», к которому мы хотим получить доступ, чтобы получить gp_offset
?
Мои предположения верный? Какие члены или функции (или что это такое) получают члены ->
gp_offset, fp_offset, overflow_arg_area, reg_save_area, ...
Могу ли я найти их реализацию, чтобы увидеть, что они делают? или они задокументированы во внутренней части компилятора?