и посмотреть медиа
S0ER - architecture and coding
и посмотреть медиа
Materials on software architecture, programming and career growth in IT.
Materials on software architecture, programming and career growth in IT.
S0ER focuses on software architecture, programming and professional development. The channel offers in-depth analyses, code examples and strategies for advancement in the IT field.
Низкий уровень: как выглядят вызовы функций по указателю на ASM В языках высокого уровня, таких как C или C++, часто используются указатели на функции. Это позволяет динамически выбирать, какую функцию вызвать в runtime. Но как это выглядит на уровне ассемблера? Давайте разберемся. Для начала рассмотрим простой пример на C, где используется указатель на функцию: int callme() { return 1; } void main() { int (*func_ptr)() = callme; func_ptr(); } Здесь мы создаем указатель на функцию func_ptr, который указывает на функцию callme, и затем вызываем функцию через этот указатель. Как это выглядит в ассемблере? Используем Compiler Explorer, чтобы преобразовать этот код в ассемблер. Вот что получилось: callme: push rbp mov rbp, rsp mov eax, 1 pop rbp ret main: push rbp mov rbp, rsp sub rsp, 16 mov QWORD PTR [rbp-8], OFFSET FLAT:callme mov rax, QWORD PTR [rbp-8] call rax nop leave ret Что здесь происходит? Создание указателя на функцию: В функции main мы видим, что адрес функции callme сохраняется в памяти по адресу [rbp-8]: mov QWORD PTR [rbp-8], OFFSET FLAT:callme Здесь OFFSET FLAT:callme — это адрес функции callme в памяти. Загрузка указателя в регистр: Затем этот адрес загружается в регистр rax: mov rax, QWORD PTR [rbp-8] Вызов функции по указателю: После этого происходит вызов функции через регистр rax: call rax Инструкция call использует значение в регистре rax как адрес функции, на которую нужно перейти. Пролог и эпилог Как и в случае с обычным вызовом функции, здесь также присутствуют пролог и эпилог: Пролог: push rbp mov rbp, rsp sub rsp, 16 Здесь сохраняется значение rbp, устанавливается новый кадр стека и выделяется место для локальных переменных. Эпилог: leave ret Здесь восстанавливается значение rbp и выполняется возврат из функции. Пример с массивом в функции Давайте добавим массив в функцию callme и посмотрим, как это повлияет на ассемблерный код: int callme() { char a[128]; return 1; } В ассемблере это будет выглядеть так: callme: push rbp mov rbp, rsp sub rsp, 8 ;
Открыть канал и посмотреть медиаOnly registered users can share their opinion.
Be the first to share your impression of this resource!