Как мне получить доступ к значению последнего параметра функции, учитывая, что первые два параметра являются динамическими c массивами? - PullRequest
0 голосов
/ 27 марта 2020

Функция в C равна

void f(int* out, int* in, int nbElements){
    // do stuff
}

Поскольку int nbElements является первым, который помещается в стек, а in и out имеют переменные размеры, как я могу получить доступ к значению nbElements? Насколько я понимаю, стек выглядит примерно так:

          esp
          ebp
     return address         # -4(%ebp) 
1st element of int* out     # -8(%ebp)
1st element of int* in      # (%ebp - 8 - 4*nbElements)
      nbElements            # not sure how I can access the value of this

Так как мне получить доступ к значению nbElements, не зная его адреса?

Ответы [ 2 ]

5 голосов
/ 27 марта 2020

Нет, содержимое массива не копируется, только их адреса, поэтому вместо этого стек будет выглядеть (при условии соглашения о вызовах справа налево и адреса представлены от высокого к низкому):

nbElements
in
out
return-address
(locals...)

Каждый из параметров имеет фиксированный адрес по сравнению друг с другом (для подтверждения этого проверьте код из C вызова такой функции). Последний параметр будет иметь значение ebp + 12 (при условии, что вы выполнили pu sh ebp как часть стандартного пролога.

Посмотрите на функции и стеки фреймов , хотя вы Вам нужно будет преобразовать в синтаксис at & t.

3 голосов
/ 27 марта 2020

Кадр стека несколько отличается.

абонент не не настроил %ebp. Это до функции , называемой , , если она вообще решит использовать %ebp.

Обратите внимание, что в вашей функции ниже не использовать %ebp вообще. Все ссылки на аргументы относятся к указателю стека (%esp).

Это дает кадр стека:

1000: nbElements
0FFE: in
0FFC: out
0FFA: return address
0FF6: <---------------------- %esp points here

Итак, как показано ниже для доступа к nbElements, вы хотите 12(%esp)

Если ваша функция настроит %ebp, смещения изменятся прибл. 4:

    .text
    .globl  f
f:
    pushl   %ebp
    movl    %esp,%ebp

    movl    8(%ebp), %eax
    movl    %eax, outsave

    movl    12(%ebp), %eax
    movl    %eax, insave

    movl    16(%ebp), %eax
    movl    %eax, cntsave

    pop     %ebp
    ret

Вот что-то похожее на вашу функцию:

int *outsave;
int *insave;
int cntsave;

void
f(int *out, int *in, int nbElements)
{

    // do stuff
    outsave = out;
    insave = in;
    cntsave = nbElements;
}

Это вывод сборки:

    .text
    .globl  f
f:
    movl    4(%esp), %eax
    movl    %eax, outsave

    movl    8(%esp), %eax
    movl    %eax, insave

    movl    12(%esp), %eax
    movl    %eax, cntsave

    ret

This пример звонящего по номеру f:

void
f(int *out, int *in, int nbElements);

int outbuf[100];
int inbuf[100];
int bufcnt;

void
g(void)
{

    f(outbuf,inbuf,bufcnt);
}

Это сборка для этого:

    .text
    .globl  g
g:
    subl    $16, %esp

    pushl   bufcnt
    pushl   $inbuf
    pushl   $outbuf

    call    f
    addl    $28, %esp

    ret
...