В настоящее время я занимаюсь чтением сборок, разборки программ на С и попытки понять, что они делают.Сборка - Передача параметров вызову функции
Я застрял с тривиальным: простая программа мира привет.
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello, world!");
return(0);
}
Когда я разобрать главный:
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400526 <+0>: push rbp
0x0000000000400527 <+1>: mov rbp,rsp
0x000000000040052a <+4>: mov edi,0x4005c4
0x000000000040052f <+9>: mov eax,0x0
0x0000000000400534 <+14>: call 0x400400 <[email protected]>
0x0000000000400539 <+19>: mov eax,0x0
0x000000000040053e <+24>: pop rbp
0x000000000040053f <+25>: ret
Я понимаю, первые две строки: базовый указатель сохраняется в стеке (выталкивания ПОР, что приводит к тому, значение указателя стека, чтобы быть уменьшено на 8, потому что оно «выросло»), а значение указателя стека сохраняется в базовом указателе (так что параметры и локальная переменная могут быть легко достигнуты с помощью положительных и отрицательных смещений соответственно, тогда как стек может продолжать «расти» «).
В третьей строке представлена первая проблема: почему 0x4005c4 (адрес строки «Hello, World!») Перемещен в регистре edi вместо того, чтобы перемещать его в стек? Должна ли функция printf принимать адрес этой строки в качестве параметра? Для того, что я знаю, функции берут параметры из стека (но здесь похоже, что параметр помещается в этот регистр: edi)
В другом посте здесь, в StackOverflow, я читал, что «printf @ ptl» как заглушка которая вызывает реальную функцию printf. Я попытался разобрать эту функцию, но она становится еще более запутанной:
(gdb) disassemble printf
Dump of assembler code for function __printf:
0x00007ffff7a637b0 <+0>: sub rsp,0xd8
0x00007ffff7a637b7 <+7>: test al,al
0x00007ffff7a637b9 <+9>: mov QWORD PTR [rsp+0x28],rsi
0x00007ffff7a637be <+14>: mov QWORD PTR [rsp+0x30],rdx
0x00007ffff7a637c3 <+19>: mov QWORD PTR [rsp+0x38],rcx
0x00007ffff7a637c8 <+24>: mov QWORD PTR [rsp+0x40],r8
0x00007ffff7a637cd <+29>: mov QWORD PTR [rsp+0x48],r9
0x00007ffff7a637d2 <+34>: je 0x7ffff7a6380b <__printf+91>
0x00007ffff7a637d4 <+36>: movaps XMMWORD PTR [rsp+0x50],xmm0
0x00007ffff7a637d9 <+41>: movaps XMMWORD PTR [rsp+0x60],xmm1
0x00007ffff7a637de <+46>: movaps XMMWORD PTR [rsp+0x70],xmm2
0x00007ffff7a637e3 <+51>: movaps XMMWORD PTR [rsp+0x80],xmm3
0x00007ffff7a637eb <+59>: movaps XMMWORD PTR [rsp+0x90],xmm4
0x00007ffff7a637f3 <+67>: movaps XMMWORD PTR [rsp+0xa0],xmm5
0x00007ffff7a637fb <+75>: movaps XMMWORD PTR [rsp+0xb0],xmm6
0x00007ffff7a63803 <+83>: movaps XMMWORD PTR [rsp+0xc0],xmm7
0x00007ffff7a6380b <+91>: lea rax,[rsp+0xe0]
0x00007ffff7a63813 <+99>: mov rsi,rdi
0x00007ffff7a63816 <+102>: lea rdx,[rsp+0x8]
0x00007ffff7a6381b <+107>: mov QWORD PTR [rsp+0x10],rax
0x00007ffff7a63820 <+112>: lea rax,[rsp+0x20]
0x00007ffff7a63825 <+117>: mov DWORD PTR [rsp+0x8],0x8
0x00007ffff7a6382d <+125>: mov DWORD PTR [rsp+0xc],0x30
0x00007ffff7a63835 <+133>: mov QWORD PTR [rsp+0x18],rax
0x00007ffff7a6383a <+138>: mov rax,QWORD PTR [rip+0x36d70f] # 0x7ffff7dd0f50
0x00007ffff7a63841 <+145>: mov rdi,QWORD PTR [rax]
0x00007ffff7a63844 <+148>: call 0x7ffff7a5b130 <_IO_vfprintf_internal>
0x00007ffff7a63849 <+153>: add rsp,0xd8
0x00007ffff7a63850 <+160>: ret
End of assembler dump.
Две МОВ операции по EAX (MOV EAX, 0x0) беспокоит меня немного, как хорошо, так как я не получаю они роль здесь (но меня больше беспокоит то, что я только что описал). Спасибо заранее.
Поиск [x86-64 function args stack] (http://stackoverflow.com/search?q=x86-64+function+args+stack) находит тонны связанных вопросов. Ни один из тех, на которые я смотрел, не похож на точный дубликат, но в следующий раз, когда вы озадачены, попробуйте найти некоторые из релевантных ключевых слов. –
В качестве предложения, разборки с основного могут иногда быть сложными. Почти всегда легче начать с вызова функции от основной и разборки, чтобы начать с. –