и посмотреть медиа
S0ER - arquitectura y codificación
и посмотреть медиа
Materiales sobre arquitectura de software, programación y crecimiento profesional en TI.
Materiales sobre arquitectura de software, programación y crecimiento profesional en TI.
S0ER se centra en la arquitectura de software, programación y desarrollo profesional. El canal ofrece análisis en profundidad, ejemplos de código y estrategias para el avance en el campo de la TI.
Низкий уровень: как выглядят вызовы функций по указателю на 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 ;
Открыть канал и посмотреть медиаSolo los usuarios registrados pueden compartir su opinión.
¡Sé el primero en compartir tu experiencia con este recurso!