Привіт і ласкаво просимо назад.
Тепер ми розглянемо інструкції SCAS.
SCAS розшифровується як Scan String,
і є три варіанти.
У вас є SCAS
B, SCAS W і
SCAS D.
SCAS B, SCAS W та SCAS D. SCAS B порівнює - з - з даними, які зберігаються за адресою,
на яку вказує регістр -.
Він сканує байт або символ.
Це має той самий ефект, що й порівняння -, -.
Він встановлює прапор.
Наприклад, якщо у порівнянні - і -, ми беремо - мінус - мінус дані в -, а потім дивимося,
чи це нуль або ненуль, і встановлюємо прапорець відповідним чином.
Якщо - дорівнює символу, що зберігається в -, то буде встановлено нульовий прапорець, оскільки - мінус це стає
нулем.
- адреса збільшиться на один байт.
SCAS W. SCAS W порівнює - з -адресою з даними в -адресі, а також має той самий
ефект, що й порівняння -, -.
Аналогічно встановлюється
прапор, а - адреса збільшується на два байти.
Нарешті, ми маємо SCAS D. SCAS D порівнює - зі значенням, що зберігається за адресою -, і має
той самий ефект, що й порівняння -, -.
Він також встановлює прапори відповідно.
- після кожної операції збільшується на чотири байти.
Регістр - автоматично інкрементується або декрементується залежно від прапорця напрямку у регістрі
прапорів.
Давайте розглянемо практичний приклад SCAS. У цьому прикладі ми будемо шукати
нульовий термінатор.
Отже, ми повинні завантажити нульовий термінатор у регістр -.
Але тут потрібно встановити максимальну довжину рядка, який ви хочете шукати,
інакше ви продовжите цикл до нескінченності.
Отже, ми повинні встановити максимальну довжину рядка, а потім тут ми переміщуємо рядок в регістр -.
Це адреса, за якою знаходиться рядок, а потім ми завантажуємо цільовий символ, який шукаємо.
У цьому випадку ми шукаємо нульовий термінатор.
Тоді ми викликаємо REP NZ SCAS B. REP NZ - це спосіб повторити SCAS B на основі -.
Отже, поки - не дорівнює нулю, ви продовжуєте повторювати.
У цьому полягає сенс REP NZ.
І так до тих пір, поки довжина рядка не стане максимальною.
Тому максимальна довжина рядка зберігається в -.
Зауважте, що REP NZ повторюватиме SCAS B до максимальної довжини рядка, і зупиниться, якщо цільовий
символ не буде знайдено.
SCAS B має такий самий ефект, як і CMP, як і інструкція CMP.
Зверніть увагу, що якщо цільовий символ не знайдено, нульовий прапорець скидається.
Тобто, ZF, що дорівнює нулю, присвоюється нуль.
Однак, якщо цільовий символ знайдено, встановлюється нульовий прапорець.
Наприклад, ZF дорівнює одиниці.
Так само, як і в CMP, наприклад, якщо ви порівнюєте - зі значенням в -адресі, ми візьмемо
- мінус значення в -адресі.
Якщо - дорівнює -, то незалежно від того, що знаходиться за адресою -, ми отримаємо нуль.
Це означає, що ми беремо це мінус це.
Якщо ми отримаємо нуль, буде встановлено нульовий прапорець.
Отже, нульовий прапорець
встановлено, це означає, що ZF дорівнює одиниці.
Ось як ми можемо використовувати SCAS B для сканування символів.
Давайте спробуємо це зробити у x64dbg, тому відкрийте x64dbg і введіть всі ці інструкції. Таким чином, ми перемістили
8 на -.
Чому?
Тому що у нас буде максимальна довжина рядка, який ми будемо шукати.
Тому ми не будемо шукати далі восьми символів.
Отже, рядок, який ми шукаємо, знаходиться за цією адресою пам'яті.
Отже, ми переходимо до карти пам'яті, переходимо до сегменту даних, а потім вводимо цей рядок, APPLE.
А ззаду - нульовий термінатор.
Далі ми перемістимо цю адресу всередину регістра -, а потім ми перемістимо нуль,
цільовий символ, який ми шукаємо, в регістр -.
Тоді ми викликаємо REP-REP NZ SCAS B. Отже, давайте поставимо тут точку зупинки.
Переконайтеся, що ви зберегли його як 64_scas. exe, поставте тут точку зупинки і запустіть його.
Влучає в брейк-пойнт.
Переступаємо, переступаємо, переступаємо.
Він перемістився з 8 на -. Відійди. Тепер вона перемістила цю адресу у -, і ця адреса
містить рядок APPLE, ось тут.
Далі ми перемістимо нульовий термінатор у регістр -.
Переступайте,
і тепер -, реєстр, отримав нульовий термінатор.
Тоді ми називаємо REP NZ, REP NZ SCAS B.
Зверніть увагу, що прапорець ZF дорівнює нулю.
Тож давайте подивимося, що станеться, коли ми переступимо через це і запустимо його.
Тепер ми бачимо, що нульовий прапорець дорівнює одиниці. Це означає, що він знайшов нульового термінатора, яким є цей.
Ми шукаємо це.
Гаразд, тепер давайте повторимо це ще раз.
Цього разу ми шукатимемо іншого персонажа.
Тож давайте повторимо це, перезапустимо, а потім повернемося
сюди, і тепер шукатимемо інший символ, якого немає у вашому-вашому рядку.
Тепер ваш рядок - ЯБЛУКО.
Знайдемо символ
R. "Р" тут немає,
ясно? Тож давайте перемістимо R в -.
Отже, який ASCII
код для R? Якщо ви не впевнені, ви завжди можете відкрити браузер і знайти ASCII-код.
Ви можете відкрити Google Chrome і знайти ASCII-код, а потім використати будь-який з них, який знайдете.
Отже, ось тут ми шукаємо
- тож шукайте символ R. Ми шукаємо шістнадцятковий
код символу R. Таким чином, символ R, шістнадцятковий код буде рядковим R, вибачте, рядковим r. Малі літери r, шістнадцятковий
код буде 72, ось тут, тому ми
бачимо тут 72. Натисніть Enter, натисніть клавішу пробіл і змініть значення на
72, натисніть кнопку "ОК", і тепер
ви побачите, що це - тепер ви бачите, що коментар тут оновлюється, щоб вказати, що це символ R.
Отже, зараз ми поставимо точку зупинки, як зазвичай, і побіжимо, щоб натиснути на нашу точку зупинки.
Переступаємо, переступаємо, переступаємо.
Він пересувається з 8 на -, а потім знову переступає.
Тепер він переміщує рядок APPLE на -, а потім ми переміщуємо символ R на -, і тепер ми переступимо через
це і подивимося, що станеться з прапором ZF.
І зверніть увагу, що прапорець ZF дорівнює нулю, не встановлений.
Це означає, що він не знайшов символ R у рядку.
Ось як можна використовувати SCAS B, а також префікс REP NZ для циклічного перегляду рядка і пошуку
певного символу.
На цьому відео все.
Дякуємо за перегляд.