Какой адрес возвращает функция из стека?

У меня есть следующий код

int isBST(struct node* node) 
{ 
  return(isBSTUtil(node, INT_MIN, INT_MAX)); 
} 

int isBSTUtil(struct node* node, int min, int max) 
{
  if (node==NULL) 
     return 1;      

  if (node->data <= min || node->data > max) 
     return 0; 

  return
    isBSTUtil(node->left, min, node->data) &&  // Allow only distinct values
    isBSTUtil(node->right, node->data, max);  // Allow only distinct values
}

Когда делаю отладку кода в GDB, то вижу, что второй параметр задан по адресу ebp+0xc (0xbffff188+0xc), третий параметр установлен в ebp+0x10 и первый параметр непонятно откуда, по идее, мы известно, что адрес возврата функции находится EBP+4, первый параметр находится EBP+8 и ....откуда у меня так?


person Community    schedule 15.11.2013    source источник
comment
+1 хороший вопрос, но пожалуйста, не публикуйте скриншоты.   -  person    schedule 15.11.2013
comment
хорошо, я удалил скриншот   -  person    schedule 15.11.2013


Ответы (1)


Теоретически мы ничего не знаем о том, где находятся аргументы или адрес возврата. В конкретной архитектуре мы можем (обычно) выяснить, что делает конкретный компилятор, исследуя часть сгенерированного ассемблера. Первое нужно проверить функцию preable. На 32-разрядном процессоре Intel указатель фрейма будет находиться в EBP и будет установлен после определенного количества нажатий для сохранения регистров. (В частности, перед настройкой EBP для локального фрейма должен быть push EBP.) Типичная преабула для Intel может быть такой:

function:
        PUSH EBP
        MOV  EBP, ESP
        SUB  ESP, n         ;   allocate space for local variables

Кроме того: стек Intel растет вниз, а компиляторы для Intel почти повсеместно толкают аргументы справа налево, поэтому в вашем случае max будет иметь самый высокий адрес, min будет прямо под ним, а node ниже этого. Таким образом, ваше изображение рамки будет:

[EBP - ...]     local variables
[EBP + 0]       the pushed old EBP
[EBP + 4]       the return address
[EBP + 8]       the first argument (node)
[EBP + 12]      the second argument (min)
[EBP + 16]      the third argument (max)

(Предполагается, что все аргументы являются 32-битными значениями.) Конечно, компилятор может поместить дополнительные регистры перед отправкой EBP, в результате чего смещения будут соответственно выше. Это только один из возможных макетов.

person James Kanze    schedule 15.11.2013