String DB “NULL-TERMINATED STRING”,0
У мові асемблера не існує якихось стандартів для ідентифікації рядків. Розмір рядка можна вказати, використовуючи нехитрий трюк. Найкраще показати це на прикладі: str1 DB “STRING” len $-s1 (fasm) або len equ $-s1 (masm) Тут визначений рядок символів s1, а її розмір len дорівнює різниці початкової і кінцевої адрес елементів. Такий варіант дуже зручний, оскільки константу len можна використовувати для циклічної обробки елементів рядка. При цьому 1en міститься в лічильник символів (звичайно регістр СХ або ЕСХ, хоча можуть бути й інші регістри). Ніщо не заважає використовувати і рядка з завершальним нулем, при цьому в процесі обробки прийдеться відслідковувати кінець рядка. От фрагмент програмного коду, що демонструє цю можливість: Str1 DB “TEST STRING”,0 … lea esi, [str1]; адреса першого елемента рядка cmp byte ptr [ESI],0; перевірка на кінець рядка Якщо використовувати формат коротких рядків (стиль Pascal), то обробку елементів можна організувати так, як показано в наступному прикладі: str1 db 7,“string1” … Lea esi, str1 mov cl, byte ptr [ESI] Inc esi У цьому випадку обробка рядка починається з елемента з індексом 1, тобто находящегося по адресі [esi+1]. У регістр CL міститься розмір рядка str1, рівний 7 (команда mov cl, byte ptr [esi]). Визначеним недоліком такого методу є необхідність заздалегідь знати розмір рядка. Дотепер ми розглядали рядки, що складаються із символів, але наші міркування застосовні і до послідовності довільних байтів, слів і подвійних слів. У цьому випадку таку сукупність елементів називають масивом. Для байтових масивів дійсні ті ж прийоми роботи, що і для символьних рядків, а от при роботі з елементами розміром у слово або подвійне слово варто враховувати деякі особливості, зв'язані з розмірністю елементів. Крім корекції лічильника необхідно правильно вказувати адреса наступного елемента масиву. Для подвійного слова наступний елемент відстоїть від попередніх на 4 байти, для слова — на 2 байти.
Для роботи з рядками і масивами в систему команд процесорів Intel включені спеціальні команди обробки рядків. Цю групу команд у термінології Intel називають командами строкових примітивів, або ланцюжковими командами. Розглянемо принципи роботи ланцюжкових команд. Ланцюжкова команда може бути використана для багаторазової обробки одного байта, одного слова або подвійного слова. Для цього вказується префікс повторення rер. Далі приведені модифікації префікса rep для команд строкових примітивів: • rер – повторювати операцію, поки СХ не стане рівним 0; • repz, rере – повторювати операцію, поки елементи рівні, тобто до першої нерівності (прапор ZF встановлений у 0). Операція припиняється, якщо прапор ZF встановлюється в 1 або лічильник у регістрі есх (сх) досягає нуля; • repne, repnz – повторювати операцію, поки елементи не рівні, тобто до першої рівності (прапор ZF встановлений у 1). Операція припиняється при установці прапора ZF у 0 або при досягненні значення 0 у регістрі есх (сх). Для процесорів Intel, що обробляють слово за одну операцію, використання ланцюжкових команд там, де це можливо, підвищує ефективність програми. У строкових командах не застосовуються способи адресації, характерні для інших команд обробки рядків. Строкові команди адресують операнди комбінаціями регістрів ESI (SI) або EDI (DI). Операнди джерела використовують регістр ESI (SI), а операнди приймача (результату) — регістр EDI (DI). Усі строкові команди коректують адреса після виконання операції. Рядок може складатися з декількох елементів, але команди обробки рядків можуть обробляти тільки один елемент у кожен момент часу. Автоматичний інкремент (збільшення) або декремент (зменшення) адреси операнда дозволяє швидко обробляти строкові дані. Прапор напрямку DF у регістрі стану визначає напрямок обробки рядків. Якщо він дорівнює 1, то адреса зменшується, а якщо він скинутий у 0, то адреса збільшується. Сама величина інкременту або декременту адреси визначається розміром операнда. Наприклад, для символьних рядків, у яких розмір операндів дорівнює 1 байт, команди обробки рядків змінюють адресу на 1 послу кожної операції. Якщо обробляється масив цілих чисел, у якому кожен операнд займає 4 байти, то строкові команди змінюють адреса на 4. Після виконання операції покажчик адреси в регістрах ESI (SI) або EDI (DI) посилається на наступний елемент рядка.
Ми буде розглядати в основному рядки з завершальним нулем. Кожна команда обробки рядків має три припустимих формати. Суфікси b, w і d визначають крок інкременту і декременту для індексних регістрів ESI (SI) і EDI (DI). Якщо команда використовується в загальному форматі, то розмірність операндів повинна бути визначена явно. Перед виконанням команд строкових примітивів необхідно завантажити в регістри ESI (SI) і/або EDI (DI) адреси оброблюваних комірок пам'яті. Обробку рядків і масивів не обов'язково виконувати за допомогою команд строкових примітивів, але використовувати такі команди в багатьох випадках зручніше. Найбільш продуктивний код можна написати, якщо дотримувати кілька умов: • дані в джерелі і приймачі повинні бути вирівняні по 8-байтовой границі; • прапор напрямку повинний бути встановлений убік збільшення адрес; • лічильник у регістрі ЕСХ повинний мати значення, більше або, принаймні, рівне 64; • різниця між умістом регістрів ESI і EDI повинна бути більше або дорівнює 32. При розробці високоефективного коду бажано все-таки уникати ланцюжкових команд, використовуючи замість них комбінацію mov/inc або mov/dec. Таблиця 1. Строкові операції (ланцюжкові команди).
Читайте также: Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|