Как вывести строку в ассемблере

Ассемблер. Строки

На предыдущих уроках мы уже использовали строки разной длины.

Строки в Ассемблере

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

явное содержание длины строки;

использование сигнального символа.

В качестве альтернативы мы можем хранить строки с завершающим сигнальным символом. Сигнальным символом является специальный символ, который не должен находиться внутри строки. Например:

Строковые инструкции

Каждая строковая инструкция может требовать исходного операнда и операнда назначения. Для 32-битных сегментов строковые инструкции используют регистры ESI и EDI, чтобы указать на операнды источника и назначения, соответственно.

Однако для 16-битных сегментов, чтобы указать на источник и место назначения, используются другие регистры: SI и DI.

Существует 5 основных инструкций для работы со строками в Ассемблере:

MOVS — эта инструкция перемещает 1 byte, word или doubleword данных из одной ячейки памяти в другую;

LODS — эта инструкция загружается из памяти. Если операндом является значение типа byte, то оно загружается в регистр AL, если типа word — загружается в регистр AX, если типа doubleword — загружается в регистр EAX;

STOS — эта инструкция сохраняет данные из регистра (AL, AX или EAX) в память;

CMPS — эта инструкция сравнивает два элемента данных в памяти. Данные могут быть размера byte, word или doubleword;

SCAS — эта инструкция сравнивает содержимое регистра (AL, AX или EAX) с содержимым элемента, находящегося в памяти.

Каждая из вышеприведенных инструкций имеет версии byte, word или doubleword, а строковые инструкции могут повторяться с использованием префикса повторения.

Регистры DS:SI (или ESI) и ES:DI (или EDI) указывают на операнды источника и назначения, соответственно. Предполагается, что операндом-источником является DS:SI (или ESI), а операндом назначения — место в памяти, на которое указывает пара ES:DI (или EDI).

Для 16-битных адресов используются регистры SI и DI, а для 32-битных адресов используются регистры ESI и EDI.

В следующей таблице представлены различные версии строковых инструкций и предполагаемое место операндов:

Основная инструкция Операнды в: Операция byte Операция word Операция doubleword
MOVSES:DI, DS:SIMOVSBMOVSWMOVSD
LODSAX, DS:SILODSBLODSWLODSD
STOSES:DI, AXSTOSBSTOSWSTOSD
CMPSDS:SI, ES:DICMPSBCMPSWCMPSD
SCASES:DI, AXSCASBSCASWSCASD

Инструкция MOVS

Источник

Как вывести строку на экран в Ассемблере

Что бы ни делала ваша программа, в большинстве случаев она должна выводить какие-то данные на экран. И если в языках высокого уровня это делается “лёгким движением руки”, то в ассемблере для этого приходится как следует помучиться.

Правда, в современных воплощениях языка Ассемблера могут быть стандартные макросы или подпрограммы для вывода строк на экран. Однако начинающим будет полезно разобраться с тем, как это можно сделать только с помощью инструкций, без применения каких-либо облегчающих жизнь библиотек.

Итак, выводить строки на экран можно двумя путями:

Кроме того, в текстовом режиме вывод на экран можно выполнить одним из трёх способов:

Третий способ хорош тем, что он сразу записывает данные в видеопамять, что позволяет выполнять вывод более быстро. Однако в наше время он применим, разве что, в учебных целях. Потому что современные операционные системы не позволяют напрямую обращаться к “железу”.

Поэтому, если ваша программа является чуть более, чем учебной, то придётся применять один из первых двух способов. Ну а если вам интересно, как выполнить вывод непосредственно в видеопамять, то посмотреть примеры вы можете здесь или здесь.

Функции вывода DOS

Итак, начнём с функций вывода DOS. Эти функции являются функциями операционной системы DOS, но поддерживаются и операционными системами Windows.

Как я уже говорил, можно напечатать на экране строку в цикле, отдельно выводя каждый символ. Для этих целей можно использовать функции 02h, 06h или недокуметированное прерывание 29h.

Если требуется вывести на экран строку целиком, то можно применить функции 09h и 40h.

Для использования функций DOS надо сначала подготовить необходимые данные, записать номер функции в регистр AH, а затем вызвать прерывание 21h.

Как вывести строку в ассемблере. Смотреть фото Как вывести строку в ассемблере. Смотреть картинку Как вывести строку в ассемблере. Картинка про Как вывести строку в ассемблере. Фото Как вывести строку в ассемблере

При правильном использовании на экран будет выведено примерно следующее:

Как вывести строку в ассемблере. Смотреть фото Как вывести строку в ассемблере. Смотреть картинку Как вывести строку в ассемблере. Картинка про Как вывести строку в ассемблере. Фото Как вывести строку в ассемблере

Функции вывода BIOS

Функции BIOS также могут выводить как отдельные символы (функции 09h, 0Ah, 0Eh), так и строки целиком (функция 13h).

Кроме того с помощью функций BIOS можно установить видеорежим, установить или считать положение курсора, а также считать символ и его атрибуты.

Хотя функции DOS тоже могут считывать символы, но всё-таки возможности BIOS более широки.

Для работы с функциями BIOS также сначала надо подготовить данные, записать номер функции в регистр AH, а затем вызвать прерывание 10h.

Для примера рассмотрим функцию 13h. Перед вызовом функции надо:

Как вывести строку в ассемблере. Смотреть фото Как вывести строку в ассемблере. Смотреть картинку Как вывести строку в ассемблере. Картинка про Как вывести строку в ассемблере. Фото Как вывести строку в ассемблере

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

Источник

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

Рассмотрим пример простейшей программы, выводящей на экран надпись 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

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

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

КатегорияOperatorWhat 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 (возврат каретки) устанавливающий курсор на начало текущей строки, код символа конца строки ‘$’. Директивы определения помещаются в начале программы до команд.

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

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

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

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

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

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

Как вывести строку в ассемблере. Смотреть фото Как вывести строку в ассемблере. Смотреть картинку Как вывести строку в ассемблере. Картинка про Как вывести строку в ассемблере. Фото Как вывести строку в ассемблере

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

Как вывести строку на экран в Ассемблере

Источник

Уроки по программированию

C, C++, Java, Assembler

Управление

2. Этапы создания программы на языке Ассемблер. Вывод строки на экран

2. Этапы создания программы на языке Ассемблер. Вывод строки на экран

Цель работы: получение знаний об основных правилах записи и структуре программ на языке Ассемблер для ПЭВМ типа IBM PC; приобретение практических навыков по составлению простейших программ на языке Ассемблер.

Этапы создания программы

Разработка программы на Ассемблере включает несколько шагов:

Текст программы записывается в один или несколько файлов. Имена файлов и их расширения могут быть произвольными, однако принято использовать для файлов, содержащих основную программу, расширение .asm, а для вспомогательных файлов, содержащих описание констант, новых типов, библиотеки функций, – расширение .inc.

Подготовленный текст программы необходимо преобразовать в машинные команды, которые могут быть выполнены микропроцессором. Это можно осуществить с помощью программ, называемых ассемблерами. После ассемблирования получают объектные модули с расширением .obj. Ассемблирование можно выполнить с помощью компиляторов masm фирмы Microsoft или tasm фирмы Borland.

Процесс подготовки программы включает и процесс компоновки (редактирования связей). Работа компоновщика заключается в том, чтобы в каждом модуле определить и связать ссылки на неопределённые имена и обеспечить переместимость программы. Когда программа включает несколько модулей, компоновщик объединяет их в один файл. В итоге будет получен выполняемый файл с расширением .exe или .com. Для этих целей можно использовать программу–компоновщик link фирмы Microsoft или tlink фирмы Borland.

Например, пусть файлы с исходными кодами называются prog1.asm и myLib.inc. В этом случае ассемблирование и компоновку можно выполнить следующими командами:

Таблица команд ассемблирования и компоновки

MicrosoftBorland
Этап ассемблированияmasm prog1.asm
masm myLib.inc
tasm prog1.asm
tasm myLib.inc
Этап компоновкиlink prog1.obj
link myLib.obj
tlink prog1.obj
tlink myLib.obj

Общая схема программы на языке Ассемблер

Строка в программе на Ассемблере может состоять из 4–х полей:

[метка:] команда [поле операндов] [;комментарий]

Метка используется для указания относительного адреса команды и служит для присвоения символического имени первому байту области памяти, в котором будет записан машинный эквивалент команды. Метки могут содержать:

Первым символом в метке должна быть буква или специальный символ. Максимальная длина метки – 31 символ.

Поле команды содержит её имя. Операнды определяют данные, регистры, символические имена (относительные адреса).

Например, команда mov ax, 4 заносит в регистр ax значение 4.

Комментарий начинается с символа ‘;‘. Все символы справа от символа ‘;’ до конца строки воспринимаются Ассемблером как комментарий.

Так как строчные и прописные символы в Ассемблере не различаются, то записи вида mov ah, 9 и MOV AH, 9 воспринимаются Ассемблером одинаково.

Ниже представлены примеры оформления программ для компиляторов masm и tasm.

Директивы определения сегмента делят исходную программу на сегменты. В программе на языке Ассемблер возможны четыре вида сегментов:

По крайней мере, один сегмент – сегмент команд должен присутствовать в каждой программе.

Сегментный регистр ds должен содержать адрес сегмента, в котором описаны данные. Занести адрес в регистр можно, например, следующим образом:

mov ax, @data ; для masm mov ds, ax или mov ax, sdata ; для tasm mov ds, ax

Задание

1. Изучить структуру программы на Ассемблере и основные требования к ней.

2. Разработать программу вывода строки “Hello World” на экран в стилях masm и tasm:

mov ah, 9 ;номер функции всегда помещается в регистр ah mov dx, offset Hi ;регистр dx содержит начальный адрес ;выводимой строки int 21h ;вызов прерывания

mov ah, 4Ch int 21h

3. С помощью текстового редактора набрать программу и записать ее на диск. Оттранслировать программу и получить объектный файл, листинг программы и исполняемый файл. Например, если исходный файл называется myLab1.asm, то с помощью команд

Источник

Вывод текста в окно на ассемблере

По описанным выше причинам, экран в Windows это уже среда, разделенная между разнообразными «одновременно» функционирующими графическими приложениями. Логично предположить, что в многозадачных операционных системах должны действовать более строгие правила, дабы исключить ситуации, когда приложения используют для вывода своей информации чужую область экрана (окно/часть окна стороннего приложения). Поэтому, вывод текста в окно графического интерфейса Windows далеко не такая тривиальная задача, как её аналог для текстового режима в MSDOS, и тут нам необходимо усвоить ряд правил:

Области (регионы)

Фактически объектами любого современного графического интерфейса являются окна, представляющие собой прямоугольные области произвольного размера. Пользовательское приложение, как и система, оперирует понятием окна как некой прямоугольной областью, ограничивающей вывод информации. Окно в Windows разделено на несколько областей:

Клиентская область это фактически регион окна приложения, за обслуживание которого отвечает само приложение. За неклиентский регион (non-client area), бордюры, заголовок, ползунок, окна, отвечает ядро системы.

Как вывести строку в ассемблере. Смотреть фото Как вывести строку в ассемблере. Смотреть картинку Как вывести строку в ассемблере. Картинка про Как вывести строку в ассемблере. Фото Как вывести строку в ассемблере

Дабы приложения не «портили» окна чужих приложений, по умолчанию Windows обеспечивает контроль за выводом посредством ограничения области отрисовки каждого окна только его собственной клиентской областью.

Надо учитывать, что размер этой клиентской области окна не постоянен, поскольку пользовательская активность является причиной постоянных изменений атрибутов окна (размер, видимость и прч.). Вот именно это обстоятельство и является ключевым в понимании природы графического интерфейса. Теперь давайте поговорим о действительных и недействительных областях.

(Не)действительные области

В какой-то момент времени изображение (содержимое) окон всех приложений переносится системой в память видеоадаптера (видеопамять) для непосредственного отображения на экране. Начиная с этого момента подразумевается, что системе известно содержимое части экрана, соответствующее всем окнам, контекст которых был только что перенесен. Ядро постоянно отслеживает объекты графического интерфейса, расположенные на экране: изменения размеров окон, их перемещение. Если никаких изменений в окнах приложений не происходит, то видеоадаптер обновляет содержимое экрана, периодически выбирая его из собственной видеопамяти. Если окна приложений начинают открываться/закрываться/перемещаться, то на экране появляются области, информация об изображении которых теряет актуальность, иными словами потеряна (неизвестна) для операционной системы. В этом случае система извещает окна, области (части, фрагменты) которых стали недействительными, о необходимости восстановить (перерисовать) собственное содержимое. Ведь на рабочем столе зачастую возникают ситуации, когда пользователь перетаскивает существующее стороннее окно либо поверх содержимого нашего окна, затем закрывает/вновь перемещает его, или просто сворачивает и разворачивает окно приложения. Поскольку часть окна (или окно целиком) перекрыта содержимым находящегося выше окна, оригинальная часть замещена (скрыта) частью содержимого перекрывающего окна, поэтому часть клиентская области перекрытого окна становится недействительной. Давайте перечислим виды областей:

Если честно, перед начинающим программистом встают не такие уж и тривиальные задачи. Тут, как говорится, пока не пощупаешь все эти подходы на практике, принципа не поймешь. К примеру, если мы пишем эдакий простенький графический редактор, который предназначен для рисования мышью (абстрактная кривая) в основном окне, мы должны хранить все точки данной фигуры, потому как в случае перемещения окна нам потребуется отрисовать (восстановить) её всю целиком. Та же ситуация и с текстом, приложение должно хранить всю ту информацию, которая использовалась во всех элементах окна и на основании которой оно может в любое время окно обновить. При работе с текстовой информацией (выводе/вводе), код приложения должен сохранять данные в памяти, чтобы их можно было «по требованию» системы вывести на экран, тем самым обновив (перерисовав) актуальное содержимое окна. Таким образом, принимая во внимание всё вышеизложенное, можно сделать следующий вывод:

Контекст устройства [отображения]

Очевидно, что отрисовку можно производить как внутри кода обработки любого входящего сообщения (чаще всего WM_PAINT ), так и вне процедуры обработки сообщений окна, например в процедуре обработки сообщений потока. Но, не все так просто как хотелось бы, и для этого, что бы начать «рисовать», требуется еще поизвести ряд подготовительных действий. В коде процедуры обработки сообщения, непосредственно перед началом рисования чего-либо в клиентской области «собственного» окна, приложению необходимо запросить у системы так называемое «разрешение» на подобные действия. Под разрешением подразумевается системная структура под названием контекст устройства отображения (контекст отображения). Советую перейти по приведенной ссылке и ознакомиться с материалом. После этого, пожалуй, продолжим.

Методы получения контекста устройства

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *