Методические указания к выполнению лабораторной работы
1) ознакомиться с теоретическим материалом;
2) разобрать реализацию приведенных задач;
3) дописать необходимые команды, создать исполняемые файлы и выполнить программы, реализующие решение задач 1, 2.
4) проверить правильность работы программ на тестах.
Для самопроверки и для контроля преподавателем необходимо выполнить все задачи.
Анализ таблицы кодов ASCII показывает следующее.
В системе кодировки ASCII для любой цифры от 0 до 9 справедливо соотношение
код (цифра) — код (‘0’) = цифра
Так как код символа 0 (‘0’) равен 30 h , то ASCII -код любой цифры от 0 до 9 отличается от соответствующего двоичного представления числа на 30 h .
Поэтому для преобразования ASCII -кода символа (‘0’..’9’) в число, следует из кода символа вычесть 30 h .
При вводе с клавиатуры, например, цифры 5 недостаточно воспользоваться функцией 1 h прерывания 21 h , так как в регистре al в результате будет находиться код символа ’5’, а не число 5.
Для получения числа 5 необходимо еще вычесть 30 h из полученного кода:
mov 21 h ; в al код символа ‘5’
sub al ,30 h ; теперь в al число 5
ЗАДАЧА 1
Пусть в сегменте данных под символическим именем N хранится беззнаковое десятичное число (от 0 до 255). Необходимо записать по адресу KOD цифры (как символы) из десятичной записи числа.
РЕШЕНИЕ
Пусть N = abc , где a , b , c — десятичные цифры числа N .
Для получения правой цифры c надо взять остаток от деления N на 10. Неполное частное от деления — это число ab , ели его разделить на 10, то неполное частное даст цифру а, а остаток — цифру b .
Чтобы получить эти цифры как символы (их затем можно будет вывести на экран), следует к цифре прибавить код ‘0’ (30 h ).
mov ah ,0 ; расширение N в ax до слова (беззнаковое)
div bl ; ah=c, al=ab
mov KOD +2, ah ; записали последнюю цифру
mov ah ,0 ; al = ab , расширение ab до слова (беззнаковое)
div bl ; ah=b, al=a
add ax,’00’ ; ah=b+’0’, al=a+’0’
mov KOD +1, ah ; записали среднюю цифру
mov KOD , al ; записали первую цифру
ЗАДАЧА 2
Ввести десятичное число и записать его в сегмент данных под символическим именем N (размером в один байт).
РЕШЕНИЕ
По очереди вводим цифры и формируем число по схеме Горнера.
Пусть уже введены первые цифры числа, например, 2 и 1, и по ним сформировано число 21. Пусть следующей введена цифра 3. Тогда умножаем предыдущее число на 10 и прибавляем к нему новую цифру: 21*10+3=213. И так для каждой новой цифры.
Замечание. Будем предполагать, что пользователь вводит число в диапазоне 0-255 корректно и ввод завершается нажатием клавиши Enter .
int 21 h ; в al — первый символ
sub al ,30 h ; теперь первая цифра
mov ah ,0 ; расширение до слова
mov cx , ax ; в cx — первая цифра
int 21 h ; в al следующий символ
cmp al ,0 dh ; сравнение с символом Enter
je End ; конец ввода
sub al ,30 h ; в al — следующая цифра
cbw ; расширение до слова
xchg ax , cx ; теперь в ax — предыдущее число, в cx — следующая
Сегодня мы рассмотрим тему «Вывод на экран Assembler» и разберем программу, которая сможет выводить на экран нашей консоли числа. Для этого нам потребуется изучить несколько новых процедур, а также познакомится с подключаемыми библиотеками и системными файлами.
Вспомним о процедурах
Для начала, я напомню вам, что когда мы изучали с вами процедуры Assembler, то я, подводя итоги, написал, что для процедур с параметрами необходим прототип. Да, это так, но есть одно но: если эта процедура не является стандартной, и не описана где нибудь в подключаемой библиотеки.
Так вот, ранее изученная процедура ExitProcess, а также те процедуры, которые мы сегодня с вами изучим(WriteConsoleA, wsprintf) являются стандартными(на самом деле такого термина нет, но думаю так понятнее), и для них не нужно писать прототип.
Вывод на экран
А теперь перейдем к коду:
Как вы заметили, у нас увеличилось число подключаемых файлов. И как я уже выше написал, все они понадобятся для того, чтобы работали процедуры, которые мы будем использовать далее в этой программе.
Далее будет не очень понятно пока не увидим в действии, но все же попробую объяснить. Первое, что мы делаем, объявляем константу BSIZE со значением 15. Затем в разделе .data , там где объявляются переменные, задаем несколько переменных, которые потребуются как параметры для наших дальнейших процедур.
Стоит отметить переменную buf: запись dup(duplication) говорит о подряд идущих байт, которые выделяются под переменную buf размерностью BSIZE(15). А знак вопроса говорит, что значения байт заранее не определено.
Итак, пока не все понятно, поэтому идем дальше, тут у вас должен сложиться пазл:
Для того, чтобы вывести что нибудь на экран нужно знать дескриптор вывода. Процедура GetStdHandle считывает адрес дескриптора экрана, и по умолчанию записывает его в регистр eax. После, мы записываем это значение из регистра в переменную stdout.
Дальше мы используем процедуру wsprintf. Она нужна для того, чтобы вывести наше сообщение(именно число) в понятном для нас формате, то есть эта процедура преобразования машинного языка в человеческий формат. Для этого используется переменная ifmt.
Ну и за сам вывод отвечает процедура WriteConsoleA. Она принимает 5 параметров, и последним всегда должен идти 0.
Мой совет: лучше запомнить эти процедуры в таком виде, каком они представлены здесь, в наших дальнейших статьях мы практически всегда будем их использовать.
Запуск программы
А сейчас я покажу вам как все это реализовать на практике, после написания кода.
Я создал файл fifth.asm и поместил его в папку BIN. Затем я открываю командную строку, и перехожу в папку BIN с помощью команды cd C:UsersНикитаBIN (у вас будет другой путь, скорее всего)
Далее компилирую наш файл, прописывая команду amake.bat fifth, если код правильный, то будет как на фото:
Как мы видим, все скомпилировалось без ошибок, но ничего не вывелось на экран. Для того, чтобы наша программа выполнилась, нужно после компиляции запустить файл с расширением .exe(он создается автоматически после правильной компиляции). Прописываем в командной строке fifth.exe, у вас должно получится нечто подобное:
Все прошло успешно! На сегодня на этом закончим c выводом на экран, но в следующих примерах Assembler мы еще будем возвращаться к этой теме, если у вас остались вопросы, то пишите их в комментариях, не забывайте просматривать исходники и предыдущие статьи.
Как выучить английский |
В наше время любой человек должен знать английский язык. А тем более программист. Потому что довольно большая часть документации существует только на английском. А профессионал не может ждать, пока кто-то переведёт ему документацию. Он должен уметь быстро получать нужную инфорамцию и использовать её, независимо от того, на каком она языке — на английском или на русском. Ссылки на курсы по английскому.
Что бы ни делала ваша программа, в большинстве случаев она должна выводить какие-то данные на экран. И если в языках высокого уровня это делается “лёгким движением руки”, то в ассемблере для этого приходится как следует помучиться.
Правда, в современных воплощениях языка Ассемблера могут быть стандартные макросы или подпрограммы для вывода строк на экран. Однако начинающим будет полезно разобраться с тем, как это можно сделать только с помощью инструкций, без применения каких-либо облегчающих жизнь библиотек.
Итак, выводить строки на экран можно двумя путями:
- Посимвольно (то есть в цикле выводить каждый символ строки).
- Строку целиком.
Кроме того, в текстовом режиме вывод на экран можно выполнить одним из трёх способов:
- С помощью функций DOS.
- С помощью функций BIOS.
- Путём прямой записи в видеопамять.
Третий способ хорош тем, что он сразу записывает данные в видеопамять, что позволяет выполнять вывод более быстро. Однако в наше время он применим, разве что, в учебных целях. Потому что современные операционные системы не позволяют напрямую обращаться к “железу”.
Поэтому, если ваша программа является чуть более, чем учебной, то придётся применять один из первых двух способов. Ну а если вам интересно, как выполнить вывод непосредственно в видеопамять, то посмотреть примеры вы можете здесь или здесь.
Функции вывода DOS
Итак, начнём с функций вывода DOS. Эти функции являются функциями операционной системы DOS, но поддерживаются и операционными системами Windows.
Как я уже говорил, можно напечатать на экране строку в цикле, отдельно выводя каждый символ. Для этих целей можно использовать функции 02h, 06h или недокуметированное прерывание 29h.
Если требуется вывести на экран строку целиком, то можно применить функции 09h и 40h.
Для использования функций DOS надо сначала подготовить необходимые данные, записать номер функции в регистр AH, а затем вызвать прерывание 21h.
Все функции рассматривать здесь не будем. Для примера используем одну из самых простых функций DOS — функцию 09h, которая выводит в стандартное устройство вывода (в нашем случае — на экран) строку, адрес которой находится в DS:DX. Строка должна заканчиваться символом $, иначе функция не поймёт, где конец строки, и программа будет выводить много-много символов из памяти, начиная с указанного адреса. Примерно так, как показано на рисунке:
При правильном использовании на экран будет выведено примерно следующее:
Функции вывода BIOS
Функции BIOS также могут выводить как отдельные символы (функции 09h, 0Ah, 0Eh), так и строки целиком (функция 13h).
Кроме того с помощью функций BIOS можно установить видеорежим, установить или считать положение курсора, а также считать символ и его атрибуты.
Хотя функции DOS тоже могут считывать символы, но всё-таки возможности BIOS более широки.
Для работы с функциями BIOS также сначала надо подготовить данные, записать номер функции в регистр AH, а затем вызвать прерывание 10h.
Для примера рассмотрим функцию 13h. Перед вызовом функции надо:
- Записать номер функции в регистр АН.
- Записать режим вывода в регистр AL:
- бит 0: переместить курсор в конец строки после вывода.
- бит 1: строка содержит не только символы, но и атрибуты. Так что каждый символ описывается двумя байтами — ASCII-код и атрибут. Это можно использовать, если в строке символы должны иметь, например, разный цвет. Если атрибуты одинаковы для всей строки, то этот бит лучше сбросить (обнулить).
- биты 2-7: не используются.
Рассказывать об остальных функциях, а также об установке атрибутов и прочих вещах сегодня не буду. Если кому интересно, то всё это можно найти в справочных материалах.