Привіт і ласкаво просимо назад.
У цьому уроці ми попрактикуємось у створенні стекових фреймів.
Тож давайте почнемо.
Я вже створив нову програму, 74-Default-Stack-Frame-X, тож вам також слід це зробити.
Я зробив це, просто ввівши цей код.
Отже, п'ята кнопка тут.
Третя кнопка тут.
Зателефонувати і додати номери можна тут.
Тож зателефонуйте за цією адресою.
Це, до речі, в печері коду.
Отже, якщо ви двічі клацнете на цьому, я використовую цю адресу
для дочірньої функції: 40272705.
Ваш випадок може бути іншим, тому просто зробіть те, що є на вашому комп'ютері.
Тож цей, 40275, посилається на цей.
Додати цифри - це фактично адреса, і тут вона посилається на цю адресу.
Тож для мене це ця адреса.
Отже, у функції, яка знаходиться всередині кодової печери, я просто ввів все це: PUSH
-, MOV -, SUB - 4, MOV - плюс вісім, ADD, і так далі.
Отже, все це знаходиться всередині печери коду.
Отже, зараз я збираюся запустити його, а перед цим я поставив точку зупинки.
Тож я вже поставив тут брейк-поінт і збираюся бігти.
Тож слідкуйте за тим, що відбувається зі стеком.
Отже, на початку цієї програми "-" і "-" знаходяться в початковому положенні, ось тут, внизу.
Подивіться, що відбувається, коли я натискаю п'ять, що відбувається зі стеком,
а також ви можете подивитися це тут.
Тож для цього ви повинні змінити це.
За замовчуванням це виглядає так.
Змініть його на STDCALL - стек, щоб ви могли бачити аргументи функції тут.
Спершу я маю його запустити.
Гаразд.
Тож він потрапляє в брейк-пойнт.
Зараз буде п'ять.
П'ятірка на стопці, і, до речі, - вказує на основу попередньої стопки, яка знаходиться
тут: 644D4, яка знаходиться тут, 6448, яка знаходиться тут.
Отже, це був стек - перед запуском основної функції.
Отже, ми поклали п'ять у стопку, тепер ми збираємося покласти три, і тепер ви бачите, що три вже
у стопці.
Тепер ви збираєтеся викликати функцію.
Отже, коли ви викликаєте функцію,
гаразд, дозвольте мені оновити це.
Так - зараз тут, а тут - вказує на перший аргумент.
Отже, зараз ми входимо в дзвінок.
Отже, коли ви вводите виклик, він просуває зворотну адресу на вершину
стека, а зворотна адреса - це ця адреса, ось ця.
Тож давайте зробимо крок назустріч.
І тепер зворотна адреса виштовхується в стек.
Тож тепер твоє - з'явилося
ще одне СЛОВО тут, нагорі.
Тепер ви повинні зробити все це: PUSH -.
Тож ви врятуєте подарунок - штовхнувши його на стопку.
Це необхідно для того, щоб згодом ви могли повернутися на початкове місце - всередину стека.
Отже, це поточне місцезнаходження - вказую сюди.
Тепер ви натиснете на нього і збережете його тут, зверху.
Тож давай переступимо.
А тепер ви бачите, що поточне місцезнаходження - вже в стопці для зберігання, щоб ми могли повернутися
до нього пізніше, а ваше - переміститься на інше СЛОВО.
Отже, тепер "-" вказує сюди, а нижче ви бачите всю зворотну адресу.
У вас є перший аргумент, другий аргумент і так далі.
Отже, наступне, що вам потрібно зробити, це перемістити свій - на -.
Так що - тепер займе свою нову позицію в новоствореному фреймі стека.
Тож ви переступите через це, і зараз ви побачите, що станеться.
- тепер дорівнює -.
Обидва покажчики тепер вказують на одне і те ж місце, яке знаходиться на вершині стека.
Отже, ця штука піднімається ось так, так?
Поглянь.
Тримай.
Зараз - наразі налаштований.
Стек створено, каркас стека створено.
А тепер - вказує на основу нового
стека.
Гаразд, тепер ми віднімемо чотири від - оскільки ми хочемо створити одну локальну змінну, то віднімемо
чотири.
Якщо ви хочете створити дві локальні змінні, то ви повинні використовувати SUB - 8.
А якщо ви хочете створити три локальні змінні, ви повинні використовувати SUB - 12.
Отже, 12 буде C у гексі.
Отже, у цьому випадку нам потрібна лише одна локальна змінна.
Тож ти заміниш четвертого.
Зверніть увагу, що відбувається, коли ви це робите.
Перейдіть, і тепер ви бачите - знову збільшився на чотири байти.
І значення за замовчуванням для нього - нуль,
нічого.
Там всі нулі.
Отже, створено нову змінну.
Ви щойно створили його, зробивши це.
Тож зараз - вказує на вершину, але - залишається незмінною.
Це не зміниться.
І саме тому він корисний, оскільки його можна використовувати для посилання на аргументи функції,
а також на локальні змінні.
Тепер ми будемо посилатися на перший аргумент аргументу функції.
Отже, перший аргумент такий. Для посилання на нього потрібно зробити - плюс вісім.
Запам'ятайте, що раніше у мене було так: - плюс вісім відноситься до першого аргументу, - плюс
12 відноситься до другого аргументу.
Гаразд, ось що ми тут робимо.
Тож ми будемо посилатися на - плюс вісім.
Ви також можете подивитися тут: - плюс 8, плюс 12.
Отже, це перший аргумент -
плюс вісім.
Другий аргумент - плюс С і так далі.
Отже, тепер ми перемістимо його до -, переступимо, і тепер значення три переміщено до -, три знаходиться всередині першого
аргументу.
Далі ми додамо другий аргумент до -.
Тож - тут.
- плюс C - це другий аргумент, і ми візьмемо цей другий аргумент, тобто п'ять, і додамо його
до -, переступимо через -, і тепер - стане вісьмома.
Потім ми перемістимо цей результат, вісім, у нашу локальну змінну
- мінус чотири.
Пам'ятайте, що коли ви звертаєтеся до аргументів функції, це плюс. Коли ви звертаєтеся до локальних змінних,
це мінус.
Поглянь ще раз.
- плюс означає, що ви звертаєтеся до аргументу функції.
Це ті аргументи, які були відкладені в стопку ось тут, відкладені в стопку до того,
як ви зателефонували. Це аргументи
функції.
Щоб отримати до них доступ, ви повинні плюсувати.
Але коли ви робите мінус, це означає, що ви отримуєте доступ до локальних змінних, тобто змінних, які
тимчасово створюються всередині функції. Тоді ти мінус. Це конвенція.
Отже, тут ви отримуєте доступ до локальної змінної, тому що це мінус.
А тут не показує,
не показує.
Тут показано лише параметри функції, аргумент функції.
Він не показує локальні змінні. Локальні змінні можна
знайти тут.
Гаразд.
Це локальна змінна.
Так.
- вказує сюди.
- вказує на FFC.
- вказує сюди.
Гаразд.
Отже, якщо ви хочете отримати доступ до аргументу функції, ви повинні додати вісім до першого аргументу і 12 до другого
аргументу.
Якщо ви хочете отримати доступ до локальної змінної, ви повинні відняти чотири для першої локальної
змінної і відняти вісім для другої локальної змінної.
Отже, у цьому випадку ми отримуємо доступ до першої локальної змінної.
Отже, мінус чотири, а потім ви привласнюєте вісім, яка знаходиться всередині -.
Отже, ми привласнюємо вісім до - мінус чотири.
Подивіться, що відбувається, коли я переступаю через цей код, і вісімка з'являється там, тому що
вона прийшла з -.
Тепер ми перенесемо результат в -, хоча це просто зайве.
Але вам потрібно це знати, тому що в багатьох програмах, які ви розбираєте і переглядаєте,
вона завжди буде
робити це: зберігати результат з - в місце в пам'яті.
Він завжди збереже його назад у -, хоча це і надлишково.
Отже, у цьому випадку вам потрібно перемістити значення, що зберігається у - мінус чотири, назад у -, оскільки за домовленістю,
кожен виклик функції повертає результат у регістр -.
Це умовність.
Тому ми повинні зробити це і тут, хоча це і зайве.
Тож давайте переступимо через це зараз.
І - тепер маємо результат виклику функції. А тепер ви знищите
або скасуєте стопку. Щоб скасувати стек, ви просто робите
все навпаки, як ми робимо тут.
Тож тепер ви переїжджаєте з - в -.
Отже, переміщення в - означає, що ви знищуєте локальні змінні, і ви зробите
- вказує на нову вершину стека, яка знаходиться тут.
Тож тепер давайте переступимо через це і подивимося, що станеться з цим -. Переступив, і ось - зменшився
на чотири байти. Раніше був тут.
А тепер йди сюди.
Це означає, що таким чином ви знищуєте локальні змінні.
Хоча насправді він не знищений, він все ще є в пам'яті, але до нього більше немає доступу,
тому що ви вже перемістили його на чотири байти вниз.
Отже, тепер ми вказуємо сюди, на нову вершину стека, ось так.
Отже, тепер і - і - вказують на вершину стека, і тепер ми готові витягнути його, тому що - вказує
на вершину стека. Коли ви показуєте те, що зверху,
ми вступаємо в суперечку.
У цьому випадку аргумент -.
Тож ти вискочив... Це означає, що ви берете старе значення - і повертаєте його до -. Це має ефект
переміщення - вниз до початкового місця.
Тож давайте подивимось на -.
- зараз знаходиться десь тут, на вершині.
- це FEC.
ФЕК тут.
Отже, коли ви робите це, ви натискаєте "-".
Тепер - переїхав звідти, тож - повертається
сюди.
FD4.
FD4 тут внизу.
Бачиш?
Отже, тепер він вказує на початкове місце, на яке вказував до того, як були зроблені всі ці дзвінки.
Тому зараз - зміститься вниз на чотири байти через поп.
Вибач.
- буде вже тут.
Потім - підемо сюди.
Негайно.
Гаразд.
Тож тепер ми йдемо до РЕТ.
Отже, RET, пам'ятайте, що коли ви викликаєте
повернення, воно покаже все, що знаходиться тут.
І це буде зворотна адреса.
Він виведе це, щоб можна було повернутися до основного коду.
Цей рядок, давай зробимо це зараз.
Отже, ми переступаємо через ВДЕ, і помічаємо, що тепер
ми повертаємося до основної функції, чи не так?
І останнє, що вам потрібно зробити - це очистити стопку.
Тож тепер, після того, як ви вже зателефонували до RET, - будете тут.
- тепер вказує на перший
аргумент, третій. Тепер потрібно почистити стопку.
Отже, щоб очистити
стек, ви повинні додати вісім до - тому що є два аргументи функції, один, два.
Отже, ви повинні додати вісім, щоб воно опустилося ось сюди.
Тож давайте переступимо, а тепер - йде вниз на два DWORD, чотири байти тут і чотири байти, два DWORD.
І ви можете бачити, що третій і п'ятий були зруйновані, тому
що ви переїхали на те місце, де вони були до дзвінка.
Ось таким був стан - і - до того, як пролунав дзвінок.
Отже, ви відновили все до стеку. Ви зруйнували каркас стека.
Ось як створюються, використовуються та видаляються стекові фрейми в асемблерному коді.
Переконайтеся, що ви зберегли цей файл як 74-Stack-Frame-STDCALL.
А тепер, перш ніж ми завершимо, я хотів би розповісти вам коротеньку історію.
Тепер замість того, щоб писати код таким чином,
замість написання MOV - to - і POP -, ви можете використовувати один єдиний рядок ось так: LEAVE.
Тому замініть ці два рядки однією єдиною інструкцією - LEAVE.
І він робить те саме.
Тож іноді в цьому асемблерному коді ви побачите ось це, іноді - ось це.
Тож обидва варіанти правильні, насправді.
Наприклад, якщо ви прокрутите до нашого - тут, ви побачите наш оригінальний код, -.
Ми дивимося на дно, і бачимо тут LEAVE, LEAVE, бачите.
Отже, коли ви створюєте кадр стека, ви ШТОВХАЄТЕ -, переміщуєте - до -.
А потім, коли ви демонтуєте стековий фрейм, ви робите зворотну дію, викликаючи LEAVE.
І одна-єдина інструкція LEAVE може замінити ці два рядки.
Тож це ще одна річ, про яку ви повинні знати.
Іноді ви будете бачити ЛИСТ, а іноді - цих двох.
Тож вам потрібно знати обидва, щоб розуміти, що відбувається в коді.
На цьому відео все.
Дякуємо за перегляд.