манипулирование стеком gcc x64 - PullRequest
1 голос
/ 16 июня 2011

Я пытаюсь понять, как gcc x64 организует стек, небольшая программа генерирует этот ассм

(gdb) disassemble *main
Dump of assembler code for function main:
0x0000000000400534 <main+0>:    push   rbp
0x0000000000400535 <main+1>:    mov    rbp,rsp
0x0000000000400538 <main+4>:    sub    rsp,0x30
0x000000000040053c <main+8>:    mov    DWORD PTR [rbp-0x14],edi
0x000000000040053f <main+11>:   mov    QWORD PTR [rbp-0x20],rsi
0x0000000000400543 <main+15>:   mov    DWORD PTR [rsp],0x7
0x000000000040054a <main+22>:   mov    r9d,0x6
0x0000000000400550 <main+28>:   mov    r8d,0x5
0x0000000000400556 <main+34>:   mov    ecx,0x4
0x000000000040055b <main+39>:   mov    edx,0x3
0x0000000000400560 <main+44>:   mov    esi,0x2
0x0000000000400565 <main+49>:   mov    edi,0x1
0x000000000040056a <main+54>:   call   0x4004c7 <addAll>
0x000000000040056f <main+59>:   mov    DWORD PTR [rbp-0x4],eax
0x0000000000400572 <main+62>:   mov    esi,DWORD PTR [rbp-0x4]
0x0000000000400575 <main+65>:   mov    edi,0x400688
0x000000000040057a <main+70>:   mov    eax,0x0
0x000000000040057f <main+75>:   call   0x400398 <printf@plt>
0x0000000000400584 <main+80>:   mov    eax,0x0
0x0000000000400589 <main+85>:   leave
0x000000000040058a <main+86>:   ret
  1. Почему резервируется до 0x30 байт только для сохранения edi и rsi
  2. Я не вижу где-либо восстановить значения edi и rsi, как требуется ABI
  3. edi и rsi сохранить в позиции с дельтой 0x20 - 0x14 = 0xC, а не с непрерывной областью, имеет ли смысл?

следующий исходный код

int mix(int a,int b,int c,int d,int e,int f, int g){
    return a | b | c | d | e | f |g;
}
int addAll(int a,int b,int c,int d,int e,int f, int g){
    return a+b+c+d+e+f+g+mix(a,b,c,d,e,f,g);
}
int main(int argc,char **argv){
    int total;
    total = addAll(1,2,3,4,5,6,7);
    printf("result is %d\n",total);
    return 0;
}

Редактировать Похоже, что в стеке хранятся вызовы параметров esi, rdi, 7th addAll и total, он должен занимать 4x8 = 32 (0x20) байтов, по некоторым причинам округляется до 0x30.

Ответы [ 2 ]

2 голосов
/ 16 июня 2011
  1. Я не знаю ваш исходный код, но локальные данные также хранятся в стеке, и когда у вас есть некоторые локальные переменные, это пространство также «выделяется». Также по причине выравнивания может быть так, что он «округлил» до следующего кратного 16. Я думаю, у вас есть локальная переменная для передачи результата из вашего addAll в printf, который хранится в rbp-04.

  2. Я только что посмотрел в вашем связанном ABI - где он говорит, что вызываемый должен восстановить rdi и rsi? Уже написано на странице 15, сноска:

    Обратите внимание, что в отличие от Intel386 ABI,% rdi и% rsi относятся к вызываемой функции, а не звонящий.

    Afaik они используются для передачи первых аргументов вызываемой стороне.

  3. 0xC равны 12. Это также происходит от выравнивания, как вы можете видеть, ему просто нужно хранить edi, а не rdi, для цели выравнивания я предполагаю, что он выравнивает его по 4-байтовой границе, в то время как si is rsi, 64-битный и выровненный по 8-байтовой границе.

1 голос
/ 16 июня 2011

2: ABI явно говорит, что rdi / rsi НЕ нужно сохранять вызываемой функцией;см. стр. 15 и сноску 5.

1 и 3: не уверены;возможно проблемы с выравниванием стека.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...