Работа со строками ассемблер

Вот Вам исходник с комментами для изучения вопроса о строках. Консольная программа на masm32.

пример программы по заданию чтобы начать постепенно разбиратся..

Ну зачем столько лишних слов? Так и пишите уж: "чтобы сдать и забыть ассемблер как страшный сон". Хотите разбираться — разбирайтесь с моим исходником. Не самый плохой пример работы со строками, если что.

быстрее всего помогают разобраться в этом разделе.

Запрещено отсылать пользователей из тематических разделов в разделы фриланса, а также рекламировать свои услуги или просить/требовать оплату за помощь, кроме разделов для платных услуг.

Вычисление длины строки на ассемблере, как одна из наиболее часто возникающих задач, занимала умы разработчиков еще на заре компьютерной эпохи 🙂 Однако впоследствии, с появлением и развитием операционных систем, и, соответственно, доступностью многочисленных встроенных сервисных функций работы со строками (в числе которых предоставляется и функция вычисления длины строки), подобные помысли практически перестали волновать умы представителей сообщества. С развитием высокоуровневых языков все меньше людей задумываются о том, "а как же там на низком уровне всё это реализовано", редко кого волнует оптимизация кода по быстродействию. Даже разработчики, что-либо пишущие на ассемблере, охотнее обращаются к встроенному функционалу, предоставляемому программным интерфейсом, нежели собственными наработкам, и их можно понять, поскольку производительности предоставляемых системой функций, да и языка в целом вполне хватает для того, что бы в большинстве задач не отвлекаться на пару сотен лишних тактов.
К вычислению/заданию длины строки в исходном коде применимы две основных стратегии:

  • Статическая — когда длины строк известны заранее и задаются в исходном коде в виде констант;
  • Динамическая — когда длины строк заранее неизвестны (данные, полученные в процессе работы) и вычисляются в ходе выполнения кода;

Со статическим определением длины строки всё довольно-таки просто, чаще всего подход реализуется следующим образом:

и впоследствии используется в коде как-то вот так:

А вот с динамическим определением длины строки не все так однозначно. Основная, доступная разработчикам системная функция, это lstrlen , экспортируемая (предоставляемая) библиотекой kernel32.dll . Исключительно из любопытства хотелось бы оценить качество кода встроенных функции Windows и посмотреть, так ли они хороши, как должны быть. Попробуем поизучать код функции lstrlen , так сказать, "под микроскопом", то есть в отладчике, отладив код любой типовой программы, использующей данную функцию. После передачи управления на библиотечную функцию я просто протрассировал её до блока вычисления длины строки и скопировал найденный код, вот что у меня получилось:

Вы знаете, результатом я был приятно удивлен, потому как, честно говоря рассчитывал на худшее. Оказывается, сам вложенный цикл прохода по строке (строки 9 — 12 ), на который должно тратиться основное процессорное время, достаточно хорошо оптимизирован как по байт-коду, так и по скорости выполнения. Он состоит из четырех "быстрых" команд (минимальное количество микроопераций (μops) и задержек (latency)): mov , inc , test , jne . Однако тут существует другая проблема, в той или иной мере свойственная всем системным функциям современных операционных систем — это "обвес" функции и "вложенные" вызовы. Все дело в том, что от момента, кода ваш код вызывает функцию lstrlen и до выполнения непосредственно блока сравнения, происходит N-ое количество операций: вызовы сторонних функций, выполняющих дополнительную работу, сохранение/восстановление многочисленных стековых фреймов, проверки различных локальных и глобальных переменных и далее по списку. Отсюда можно сделать вывод, что при однократном вызове функции lstrlen существенной "просадки" скорости выполнения не будет, однако при многочисленных циклических вызовах на этот "лишний" с точки зрения вашей программы код будет уходить уже существенное процессорное время. Тем не менее, с этим уже ничего не поделаешь, это реалии всех операционных систем, код системных библиотек которых взаимосвязан, и тем самым привязан к различным дополнительным алгоритмам.

Читайте также  Поменять цвет placeholder css

Собственная реализация для ASCIIZ-строк

Откровенно говоря, поскольку идея собственной реализации вычисления длины строки на ассемблере является одной из базовых в творчестве каждого кодера, у меня она родилась достаточно давно, еще в те далекие времена, когда на нашем информационном пространстве свирепствовал MSDOS версии 3.30, а железо было представлено отечественными машинками ЕС-1840 и ЕС-1841. Причина была достаточно прозаична, требовались функции для реализации тех или иных частей приложений/загрузчиков/осей. К сожалению (а может и к счастью), вся эта масса кривого кода давно уже переместилась в информационный ад (при условии, что он существует), а те дискеты, на которых она когда-то размещалось, скорее всего догнивают под многометровым слоем цивилизационных отходов где-то на региональной мусорной свалке. Но кое-что память человеческая сумела сохранить.

16-битный код

Для тех, кто глубокими ночами, в зашторенной комнате с приглушенным светом и закрытой на ключ дверью, балуется 16-битным кодом реального режима, могу предложить такую вот реализацию функции:

Язык программирования ассемблер

Язык программирования ассемблер сейчас редко используется для решения прикладных задач, однако его изучение позволяет лучше понять принципы работы ЭВМ, операционных систем и трансляторов с языков высокого уровня. В разное время в большинстве ПЭВМ использовались и используются процессоры фирмы Intel (8086/8088, 80186, 80286, i386, i486, Celeron, Pentium и т.д., см. с. 23-25). Эти процессоры поддерживают преемственность на уровне машинных команд: программы, написанные для младших моделей процессоров, без всяких изменений могут быть выполнены на более старших моделях. При этом базовой является система команд процессора 8086. Язык ассемблера — это символьная форма записи машинного языка, его использование существенно упрощает написание машинных программ. Приведем перевод английских слов:

assemble:1. собирать, монтировать, 2. компоновать с помощью ассемблера, ассемблировать, транслировать с помощью ассемблера, транслировать программу с помощью ассемблера

assembling:1. сборка, монтаж, 2. компоновка, ассемблирование, трансляция программы с помощью ассемблера

Для ПЭВМ разработаны разные языки ассемблера. Наиболее распространены язык фирмы Microsoft, названный языком макроассемблера (сокращенно MASM) и язык Turbo Assembler фирмы Borland (сокращенно TASM). Для того, чтобы программы на ассемблере случайно не нанесли вред операционной системе и программному обеспечению, последующие задания рекомендуется выполнять в виртуальной машине.

Рассмотрим пример простейшей программы, выводящей на экран надпись Hello world (Здравствуй, мир, англ., greet — приветствие).

Программа Выполняемые действия
Data SEGMENT Greet DB ‘Hello world’,13,10, ‘$’ Data ENDS Assume CS: Code, DS:Data Code SEGMENT Start: mov ax, Data mov ds,ax; mov dx, OFFSET Greet mov ah,9 int 21h mov al,0 mov ah, 4ch int 21h Code ENDS Stack1 SEGMENT Stack DB 100h DUP(?) Stack1 ENDS END Start Начало сегмента данных Конец сегмента данных Объявление, что регистры процессора CS и DS будут содержать номера сегментов с именами Code и Data Начало сегмента команд Метка Поместить в регистр АХ номер сегмента Data Переслать АХ в регистр DS (команды непосредственной загрузки регистра DS нет) В регистр dx помещается смещение надписи относительно DS В регистр ah помещается номер 9 функции DOS “выведи надпись” Прерывание (вывод надписи) Возвращение в систему: в регистр ah помещается номер функции “возврат в систему” Прерывание (окончание выполнения программы) Конец сегмента команд Начало сегмента стека Конец сегмента стека Директива END заканчивает текст программы и предписывает начинать ее с команды, снабженной меткой Start
Читайте также  Сколько цветов в палитре rgb

Программа на ассемблере – это последовательность предложений, каждое из которых записывается в отдельной строке. Комментарии начинаются с символа “;”. Общий синтаксис предложений-команд:

В квадратных скобках указаны необязательные части команды. Метка нужна для ссылок на команду из других мест программы. Разрешается указывать в строке только одну метку с двоеточием (например, Start: ) и больше ничего, тогда она метит следующую команду программы. Мнемокод (мнемонический код) – это служебное слово, указывающее в символьной форме операцию, которую должна выполнить команда. Примерами операндов являются числа и имена переменных. Если операндов несколько, они отделяются друг от друга запятыми. Операндами могут быть и выражения, составляемые из чисел, имен переменных и операторов. Основные операторы ассемблера приведены в табл. 2.1.

Категория Operator What it is (or does)
() [ ] Подвыражение (Subexpression) Ссылка на ячейку памяти (Memory reference)
. Селектор структурных элементов (Structure member selector)
Унарные + — Унарный плюс (Unary plus) Унарный минус (Unary minus)
: Переопределение сегмента (Segment override)
OFFSET SEG TYPE PTR Возвращает смещение (Returns offset part) Возвращает сегментную часть Returns segment part Возвращает тип (байтовый размер) Returns type (byte size) Приведение типа (Typecast)
* / MOD SHL SHR Умножение (Multiplication) Целое деление (Integer division) Integer modulus (remainder) Логический сдвиг влево (Logical shift left) Логический сдвиг вправо (Logical shift right)
Аддитивные + — Двоичное сложение (Binary addition) Двоичное вычитание (Binary subtraction)
Битовые NOT AND OR XOR Битовое НЕ Битовое И Битовое ИЛИ Битовое Исключающее ИЛИ

В программе на ассемблере для описания переменных и их имен должны присутствовать предложения-директивы с общим синтаксисом:

Имя (например, Greet) – это, как правило, имя константы или переменной, описываемой данной директивой. Название директивы – это служебные слова. Директива DB (define byte – определить байт) определяет данные размером в байт. При ее выполнении ассемблер вычисляет операнды и записывает их значения в последовательные байты памяти, начиная с первого незанятого. Первому из байтов дается указанное имя, по которому на этот байт можно ссылаться из других мест программы. Когда ассемблер встретит в программе имя переменной, он заменит его на адрес, который принято называть значением имени. По описанию переменной запоминается также ее размер (тип). Например, директива Greet DB ‘Hello world’,13,10, ‘$’ записывает последовательные байты памяти коды символов, помещенных в кавычки, код 10 (перевод строки), код 13 (возврат каретки) устанавливающий курсор на начало текущей строки, код символа конца строки ‘$’. Директивы определения помещаются в начале программы до команд.

Читайте также  Принтер hp laserjet p1200 series

Задания:

1. Найдите в тексте программы директиву определения данных и команды. В командах найдите и выпишите мнемокоды и операции, которые им соответствуют.

2. Выполните в программе-оболочке Far следующие действия (рис. 3.42):

1) Создайте в Far файл Greet.ASM и наберите программу.

2) Cкомпилируйте с помощью команды tasm greet.

3) Скомпонуйте с помощью команды tlink greet.

Получив исполняемый файл Greet.EXE выполните программу, например, введя имя Greet в командную строку.

Рис. 2.12. Команды и результаты компиляции и компоновки программы

3. Выполните то же самое задание с помощью интегрированной среды TASM. Скопируйте папку ТА из папки Student_MUPK_NW:COMMONLANGV в папку C:Student, запустите файл ta.exe. Нажмите клавишу F10 для перехода в главное меню, выполните команду File-Load (Файл-Загрузить), нажмите Enter, выберите из списка нужный файл. Выполните настройку — отключите опцию создания com-файла (рис. 2.13) и сохраните ее командой Options-Save options.

Рис. 2.13. Изменение опций компоновщика с отключением опции создания
com-файла

Затем выполните команды Compile to OBJ (компиляция), Make EXE file(компоновка) (рис. 2.14). В случае успеха выполните команду Run-Run program, затем Run-User screen.

Рис. 2.14. Создание exe-файла

В рассмотренных здесь и ниже примерах использованы вывод и ввод символов, реализуемых при выполнении одной из группы команд прерывания с шестнадцатиричным номером 21h дисковой операционной системы MS DOS. Перед выполнением команды прерывания INT в регистр AH записывают номер нужной функции. Функции с номерами 4Сh, 2 и 9 выполняют возврат управления операционной системе для продолжения выполнения программы, вывод одного символа на экран и вывод строки. Символ с кодами 10 (перевод строки) перемещает курсор в следующую строку экрана, оставляя его в той же колонке. Символ 13 (возврат каретки) устанавливает курсор на начало текущей строки. Функция 0Ch прерывания 21h вводит с клавиатуры символы (с эхо-печатью их на экране) до тех пор, пока не будет нажата клавиша Enter, и записывает их в буфер размером 15 позиций. Пока не нажата клавиша Enter, набираемый текст можно редактировать клавишами Backspace (отмена последнего символа) и Esc (отмена всего набранного текста). Функции ввода 0Ah, 0Ch и другие считывают символы из начала буфера.

Изучение работы микропроцессора с помощью Турбо Отладчика (Borland Turbo Debugger)

Турбо Отладчик (входящий в состав среды Borland C++) позволяет прослеживать выполнение инструкций ассемблера, содержимое ячеек оперативной памяти и регистров процессора и математического сопроцессора [58]. Он также позволяет отлаживать программы на языках Си и Паскаль. Общий вид команды запуска отладчика

TD opt name args

где opt – опции, name – имя запускаемой программы, args – ее аргументы.

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Сдача сессии и защита диплома — страшная бессонница, которая потом кажется страшным сном. 8913 — | 7222 — или читать все.

91.146.8.87 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Ссылка на основную публикацию
Adblock
detector