Dos fn 06h консольный ввод вывод


Содержание

Функция 0ah: Ввод строки с клавиатуры в буфер

DS:DX = адрес входного буфера (смотри ниже)

Выход Буфер содержит ввод, заканчивающийся символом CR (ASCII 0dh)

Описание: При обращении буфер по адресу DS:DX должен содержать значение максимально допустимой длины ввода. На выходе функции в следующем байте содержится действительная длина ввода, затем введенный текст, завершающийся символом возврата каретки (0dh). Символы считываются с устройства стандартного ввода вплоть до CR (ASCII 0dh) или до достижения длины MAX-1. Если достигнут MAX-1, включается консольный звонок для каждого очередного символа, пока не будет введен возврат каретки CR (нажатие Enter). Второй байт буфера заполняется действительной длиной введенной строки, не считая завершающего CR. Последний символ в буфере — всегда CR (не засчитан в байте длины). Символы в буфере (включая LEN) в момент вызова используются как «шаблон». В процессе ввода действительны обычные клавиши редактирования: Esc выдает «\» и начинает с начала, F3 выдает буфер до конца шаблона, F5 выдает «@» и сохраняет текущую строку как шаблон, и т. д. Большинство расширенных кодов ASCII игнорируются. При распознавании Ctrl-Break выполняется прерывание int 23h (буфер остается неизменным).

Завершение программы

Функция 4ch: Завершить программу (EXIT)

Вход AH = 4ch

AL = код возврата

Описание: Возвращает управление от порожденного процесса его родителю, устанавливая код возврата, который можно опросить функцией 4dh WAIT. Управление передается по адресу завершения в PSP завершаемой программы. В векторах Ctrl-Break и Critical Error восстанавливаются старые значения, сохраненные в родительском PSP.

Замечание: Значение ERRORLEVEL (используемое в пакетных файлах DOS) можно использовать для проверки кода возврата самой последней программы.

Функция 4dh: Дать код возврата программы (WAIT)

Вход AH = 4dh

Выход AL = код возврата последнего завершившегося процесса

AH = 0 — нормальное завершение

АН = 1 — завершение через Ctrl-Break int 23h

АН = 2 — завершение по критической ошибке устройства int 24h

АН = 3 — завершение через функцию 31h KEEP

Описание: Возвращает код возврата последнего из завершившихся процессов. Эта функция возвращает правильную информацию только однажды для каждого завершившегося процесса.

Функция 4dh: Дать код возврата программы (WAIT)

Вход AH = 4dh

Выход AL = код возврата последнего завершившегося процесса

AH = 0 — нормальное завершение

АН = 1 — завершение через Ctrl-Break int 23h

АН = 2 — завершение по критической ошибке устройства int 24h

АН = 3 — завершение через функцию 31h KEEP

Описание: Возвращает код возврата последнего из завершившихся процессов. Эта функция возвращает правильную информацию только однажды для каждого завершившегося процесса.

Работа с файлами

Функция 3ch: Создать файл через дескриптор

Вход AH = 3ch

DS:DX = адрес строки ASCIIZ с именем файла

CX = атрибут файла

Выход AX = код ошибки, если CF установлен

АХ = дескриптор файла, если ошибки нет

Описание: DS:DX указывает на строку ASCIIZ в формате: «d:\путь\имяфайла»,0. Если диск и/или путь опущены, они принимаются по умолчанию. файл создается в указанном (или текущем) каталоге файл открывается в режиме доступа чтение/запись вы должны сохранить дескриптор (handle) для последующих операций, если файл уже существует:

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

· если атрибут файла — только чтение, открытие отвергается (атрибут можно изменить функцией 43h Изменить Атрибут)

CONFIG.SYS определяет число доступных дескрипторов в системе

Используйте функцию 5bh Создать Новый Файл, если вы не хотите

испортить существующий файл.

Функция 5bh: Создать новый файл

Вход AH = 5bh DOS 3.0+

DS:DX = адрес строки ASCIIZ с именем файла

CX = атрибут файла

Выход AX = код ошибки, если CF установлен

АХ = дескриптор файла, если ошибок нет

Описание: DS:DX указывает на строку ASCIIZ в форме: «d:\путь\имя_файла»,0. Если диск и/или путь опущены, они принимаются по умолчанию. Этот вызов идентичен функции DOS 3ch CREATE, с тем исключением, что он вернет ошибку, если файл с заданным именем уже существует. Файл открывается для чтения/записи в совместимом Режиме Доступа.

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций.

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

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ — конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой.

Ассемблер

Прерывание 21h: функции DOS для работы с буфером клавиатуры

Различные служебные функции DOS для работы с буфером клавиатуры (функции 01h, 06h, 07h, 08h, 0Ah, 0Bh и 0Ch) классифицируются прежде всего по трем критериям: ожидают ли они ввода или же, когда символ не получен, сообщают, что ввода нет; выдают ли они на экран дисплея эхо (введенный символ); и реагирует ли функция на ввод стандартного символа прерывания во время ее исполнения. (Напомним, что нажатие комбинации клавиш Ctrl-Break или Ctrl-C рассматривается как прерывание ограниченным числом стандартных функций DOS. Однако, начиная с версии 2.00, в DOS введена команда BREAK ON, которая дает указание DOS реагировать на ввод символа прерывания при всех обстоятельствах.)

Все функции ввода с клавиатуры получают введенный символ из буфера клавиатуры, размещенного в памяти компьютера, а не непосредственно из порта 60h интерфейса клавиатуры (из порта 60h скан-коды считываются прерыванием 09h, переводятся в коды символов и помещаются в буфер клавиатуры).

Функция 1 прерывания 21h: ввод символа с эхопечатью

Функция 01h ждет появления символа в буфере клавиатуры со стандартного устройства ввода и после приема символа помещает его в регистр AL. Другие функции, относящиеся к вводу символов с клавиатуры: 06h, 07h и 08h.

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

Работа функции 01h происходит следующим образом. Нажатие клавиши, соответствующей одному из символов кода ASCII, приводит к записи соответствующего байта в регистр AL и немедленной выдаче символа данной функцией на экран (в позицию курсора). Нажатие клавиши, формирующей сигнал, не относящийся к оду ASCII, приводит к формированию двух байтов, которые могут быть получены путем двух последовательных обращений к данной функции.

Обычно функция 01h применяется для проверки принадлежности символа, соответствующего нажатой клавише, коду ASCII. Для этого производится проверка регистра AL. Если AL не равно 00h, то это символ кода ASCII. Если же AL=00h, то вы имеете дело с символом, не относящимся к коду ASCII; в этом случае следует повторить обращение к данной функции для получения псевдокода, соответствующего специальному действию клавиши. Как и в случае применения других средств DOS, предназначенных для ввода символов с клавиатуры, при использовании данной функции развернутый код символов набора ASCII оказывается недоступным, даже если соответствующие средства обслуживания клавиатуры системы ROM BIOS позволяют осуществить доступ к нему.

Функция 6 прерывания 21h: непосредственный ввод

и вывод с консоли

Функция 06h — это универсальная функция, объединяющая операции ввода с клавиатуры и вывода на дисплей. В версиях DOS, начиная со второй и выше, эта функция, как и другие, действует по отношению уже не к клавиатуре и дисплею, а к стандартным устройствам ввода и вывода (в качестве которых по умолчанию принимаются клавиатура и дисплей).

При реализации данной функции регистр AL используется для ввода, а регистр DL — для вывода. Если при вызове функции 06h в регистре DL находится значение FFh (в десятичной нотации 255), то при нажатии какой-либо клавиши эта функция поместит соответствующий ASCII-код в регистр AL и сбросит нулевой флаг; при отсутствии нажатия клавиши она установит нулевой флаг.

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

Функция 06h не ожидает ввода символа с клавиатуры и не осуществляет его эхопечати на экране. Кроме того, функция 06h не воспринимает сочетание клавиш Ctrl-C как прерывание программы (при использовании данного сочетания она помещает в регистр AL значение 03h, т.е. соответствующий данному значению ASCII-код).

Функция 7 прерывания 21h: непосредственный ввод

с консоли без эхопечати

Функция 07h ожидает ввода символа со стандартного устройства ввода и после ввода символа помещает его в регистр AL. Она не осуществляет эхопечати символа на экране и не воспринимает сочетание клавиш Ctrl-C как прерывание программы.

Функция 07h действует точно так же, как функция 01h: нажатие клавиши, относящейся к коду ASCII, приводит к немедленному занесению в регистр AL соответствующего байта; нажатие клавиши, не относящейся к коду ASCII, приводит к формированию двух байтов, которые могут быть получены двумя последовательными обращениями к функции 07h.

Функция 8 прерывания 21h:

ввод с консоли без эхопечати

Функция 08h ожидает ввода символа, не осуществляя эхопечати и прерывает программу при нажатии Ctrl-C.


Эта функция идентична функции 01h, за исключением того, что она не выводит введенный символ на экран дисплея (или стандартное устройство вывода).

Для более полного понимания особенностей данной функции обратитесь к описанию функции 01h. Сравните данную функцию с функциями 01h, 06h и 07h. Если вы хотите использовать функцию 08h, но не желаете ждать ввода символа, изучите функцию 0Bh, которая сообщает о готовности ввода. Изучите также функцию 0Ch, которая является модификацией данной функции.

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

Дата добавления: 2014-11-27 ; просмотров: 834 ; Нарушение авторских прав

Все функции DOS вызываются прерыванием 21h, при этом в AH содержится номер функции. Ниже везде, где есть слова «стандартный ввод», под ними подразумевается клавиатура, однако ввод может быть переопределен (например, из файла). Аналогично, «стандартный вывод» – экран, но вывод также может быть переопределен (например, в файл). ASCIIZ-строка (нуль-терминированная строка) – это строка символов, заканчивающаяся нулевым символом (код 00h).

1. Ввод символа с отображением. Прерывание 21h функция 01h. Вызов: AH=01h. Возвращает: AL=введенный символ. Действие: читает символ (возвращаемый в AL) со стандартного ввода (клавиатуры) и выводит его на стандартный вывод (экран). Если ввод был перенаправлен, то невозможно обнаружить EOF.

— если при вводе нажата Ctrl+C и BREAK=ON, то вызывается прерывание 23h;

— чтобы прочитать расширенные коды (например, клавиш F1-F12), надо вызвать функцию дважды. Первый раз возвращается 00h, затем – код клавиши.

2. Вывод символа. Прерывание 21h функция 02h. Вызов: AH=02h; DL=выводимый символ. Возвращает: ничего. Действие: выводит символ на стандартный вывод. Если вывод был перенаправлен, то невозможно обнаружить, что нет места на диске.

— если Ctrl+C после вывода символа, то вызавается прерывание 23h;

— если стандартный вывод не был перенаправлен, то символ Backspace (08h) перемещает курсор влево на одну позицию.

3. Прямой консольный ввод/вывод. Прерывание 21h функция 06h. Вызов: AH=06h; DL=действие: если DL=00h-FEh, то вывод; если DL=FFh, то ввод. Возвращает:

если вызов с DL=00h-FEh, то ничего;

если вызов с DL=FFh, то: если есть символ – ZF=0, AL=введенный символ

если нет символа – ZF=1.

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

— Никакой реакции на Ctrl+C;

— чтобы прочитать расширенные коды (например, клавиш F1-F12), надо вызвать функцию дважды. Первый раз возвращается 00h, затем – код клавиши.

4. Ввод символа без отображения. Прерывание 21h функция 07h. Вызов: AH=07h. Возвращает: AL=введенный символ. Действие: читает символ (возвращаемый в AL) со стандартного ввода (клавиатуры) без отображения на стандартном выводе (экране). Если нет символа, то ждет его появления. Если ввод был перенаправлен, то невозможно обнаружить EOF.

— Никакой реакции на Ctrl+C. Нужно использовать функцию 08h, если реакция требуется;

— чтобы прочитать расширенные коды (например, клавиш F1-F12), надо вызвать функцию дважды. Первый раз возвращается 00h, затем – код клавиши.

5. Ввод символа без отображения. Прерывание 21h функция 08h. Вызов: AH=08h. Возвращает: AL=введенный символ. Действие: читает символ (возвращаемый в AL) со стандартного ввода (клавиатуры) без отображения на стандартном выводе (экране). Если нет символа, то ждет его появления. Если ввод был перенаправлен, то невозможно обнаружить EOF.

— если при вводе нажата Ctrl+C и BREAK=ON, то вызывается прерывание 23h. Нужно использовать функцию 08h, если реакции не требуется;

— чтобы прочитать расширенные коды (например, клавиш F1-F12), надо вызвать функцию дважды. Первый раз возвращается 00h, затем – код клавиши.

6. Вывод строки. Прерывание 21h функция 09h. Вызов: AH=09h, DS:DX=сегмент:смещение строки. Возвращает: ничего. Действие: посылает строку символов на стандартный вывод. Если вывод был перенаправлен, то невозможно обнаружить, что нет места на диске.

— Строка должна заканчиваться на символ $(код 24h), который не выводится. Любые другие символы ASCII, включая управляющие, могут содержаться в строке. Для перевода курсора на начало новой строки нужно вывести строку, содержащую символы «перевод строки»/»возврат каретки»:

string DB 10,13,’$’

или использовать прерывание 10h функцию 02h (см. 6.8.2.).

— Если Ctrl+C нажата на клавиатуре, то вызывается прерывание 23h.

7. Буферизованный ввод с клавиатуры. Прерывание 21h функция 0Ah. Вызов: AH=0Ah, DS:DX=сегмент:смещение буфера. Возвращает: ничего. Действие: читает строку символов со стандарного ввода, до появления символа возврата каретки (0Dh) и помещает в буфер (включая завершающий 0Dh). Символы отображаются на стандартном выводе. Если ввод был перенаправлен, то невозможно обнаружить EOF.

— Буфер, используемый этой функцией, имеет формат(см. табл. 6.4.):

Байт Описание
Максимальное количество символов (устанавливается перед вызовом)
Количество реально прочитанных символов (устанавливается функцией после ее вызова)
2 и след. Прочитанная строка, заканчивающаяся 0Dh

— Если буфер заполнился (больше символов, чем максимум), последующий ввод игнорируется и подается сигнал до тех пор, пока не нажата клавиша ENTER;

— Если при вводе нажата Ctrl+C и BREAK=ON, то вызывается прерывание 23h.

8. Проверка состояния ввода.Прерывание 21h функция 0Bh. Вызов: AH=0Bh. Возвращает: AL=00h, если нет символа; AL=FFh, если есть один или более символовhр. Действие: проверяет, есть ли в буфере стандартного ввода символ.

— Если при вводе нажата Ctrl+C и BREAK=ON, то вызывается прерывание 23h.

— Если есть символ, эта функция будет возвращать FFh, пока символ не считан функциями ввода (01h, 07h, и т.д.).

9. Очистка буфера и ввод. Прерывание 21h функция 0Ch. Вызов: AH=0Ch; AL=номер фунции, которая вызывается после очистки буфера; для AL=0Ah –DS:DX=сегмент:смещение буфера. Возвращает: если вызов с AL=01h, 07h, 08h то AL=прочитанный символ; если вызов с AL=0Ah, то ничего. Действие: очищает буфер стандартного ввода, затем вызывает одну из функций ввода (заданную в AL).

— Реакция на Ctrl+C (игнорирует или нет) зависит от вызываемой функции;

— Вызов с AL отличным от 01h, 06h, 07h, 08h, 0Ah просто очищает буфер.

10. Запись в файл или устройство. Прерывание 21h функция 40h. Действие: берет корректный дескриптор файла (от предыдущей операции создания или открытия файла), адрес буфера, длину в байтах, передает данные из буфера в файл и затем обновляет положение указателя в файле. Вызов: AH=40h; BX=дескриптор файла; CX=количество байт, которое надо записать; DS:DX=сегмент:смещение буфера. Возвращает: если нет ошибки: CF=0, AX=количество реально переданных байт; иначе – CF=1, AX=код ошибки.

Ввод-вывод в Си

Основной задачей программирования является обработка информации, поэтому любой язык программирования имеет средства для ввода и вывода информации. В языке Си нет операторов ввода-вывода.

Ввод и вывод информации осуществляется через функции стандартной библиотеки. Прототипы рассматриваемых функций находятся в файле stdio.h . Эта библиотека содержит функции

  • printf() — для вывода информации
  • scanf() — для ввода информации.

Вывод информации

Функция printf() предназначена для форматированного вывода. Она переводит данные в символьное представление и выводит полученные изображения символов на экран. При этом у программиста имеется возможность форматировать данные, то есть влиять на их представление
на экране.

Общая форма записи функции printf() :

СтрокаФорматов состоит из следующих элементов:

  • управляющих символов;
  • текста, представленного для непосредственного вывода;
  • форматов, предназначенных для вывода значений переменных различных типов.

Объекты могут отсутствовать.

Управляющие символы не выводятся на экран, а управляют расположением выводимых символов. Отличительной чертой управляющего символа является наличие обратного слэша ‘\’ перед ним.

Основные управляющие символы:

  • ‘\n’ — перевод строки;
  • ‘\t’ — горизонтальная табуляция;
  • ‘\v’ — вертикальная табуляция;
  • ‘\b’ — возврат на символ;
  • ‘\r’ — возврат на начало строки;
  • ‘\a’ — звуковой сигнал.

Форматы нужны для того, чтобы указывать вид, в котором информация будет выведена на экран. Отличительной чертой формата является наличие символа процент ‘%’ перед ним:

  • %d — целое число типа int со знаком в десятичной системе счисления;
  • %u — целое число типа unsigned int ;
  • %x — целое число типа int со знаком в шестнадцатеричной системе счисления;
  • %o — целое число типа int со знаком в восьмеричной системе счисления;
  • %hd — целое число типа short со знаком в десятичной системе счисления;
  • %hu — целое число типа unsigned short ;
  • %hx — целое число типа short со знаком в шестнадцатеричной системе счисления;
  • %ld — целое число типа long int со знаком в десятичной системе счисления;
  • %lu — целое число типа unsigned long int ;
  • %lx — целое число типа long int со знаком в шестнадцатеричной системе счисления;
  • %f — вещественный формат (числа с плавающей точкой типа float );
  • %lf — вещественный формат двойной точности (числа с плавающей точкой типа double );
  • %e — вещественный формат в экспоненциальной форме (числа с плавающей точкой типа float в экспоненциальной форме);
  • %c — символьный формат;
  • %s — строковый формат.

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

Результат работы программы

Тот же самый код может быть представлен с использованием одного вызова printf :

Иллюстрированный самоучитель по задачам и примерам Assembler

Функции MS DOS для вывода данных на экран

Для вывода данных на экран можно использовать два вида функций: универсальную функцию 40h (вывод в файл) и группу специализированных функций MS DOS вывода на экран.

Использование функции 40h уже рассматривалось в разделе, посвященном работе с файлами. Материал, представленный ниже, посвящен второй группе функций – функциям MS DOS для вывода символов на экран. В группу входят три функции. Рассмотрим их.

Вывод символа на экран (02h int 21h)

Функция 02h позволяет вывести один символ на экран.

Вход: АН >> 02h – вывод символа;

Функция 02h проверяет наличие в клавиатурном буфере символов нажатия комбинации CTRL + C (CTRL + Break), при обнаружении которых производится вызов прерывания int 23h. В процессе вывода функция реагирует на управляющие символы, такие как 0dh (возврат каретки), 0ah (перевод строки), 08h (курсор назад на один символ), 07h (звуковой сигнал) и т. д.


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

Прямой вывод символа на экран (06h int 21h)

Функция 06h выводит один символ на экран. Эта функция универсальна, так как используется и для ввода (см. выше), и для вывода символа.

Вход: АН = 06h – вывод символа на экран;

  • DL = символ для вывода (за исключением 0ffn).

Функция 06h не проверяет наличие в буфере символов нажатия комбинации CTRL + C (CTRL + Break). Порядок использования данной функции аналогичен порядку использования функции 02h.

Вывод строки на экран (09h int 21h)

Функция 09h выводит строку символов на экран. Строка должна обязательно заканчиваться символом $. Данную функцию удобно использовать для вывода на экран различных диагностических сообщений. Если требуется организовать вывод строк, длина которых формируется динамически, то лучше либо использовать упомянутую выше функцию 40h, либо выводить их в цикле, тело которого содержит одну из функций 02h или 06h.

Вход: АН = 09h – вывод строки на экран;

  • DS: DX – адрес строки для вывода с завершающим символом $.

Функция 09h проверяет наличие в клавиатурном буфере символов нажатия комбинации CTRL + C (CTRL + Break), при обнаружении которых производится вызов прерывания int 23h. В процессе вывода функция реагирует на управляющие символы, такие как 0dh (возврат каретки), 0ah (перевод строки), 08h (курсор назад на один символ), 07h (звуковой сигнал) и т. д.

Приведенный ниже фрагмент показывает порядок применения функции 09h.

«Assembler IBM PC 7. Лабораторная работа № 2. Системные функции dos ввода-вывода информации. Обработка строковых переменных»

7.1. ЦЕЛЕВЫЕ УСТАНОВКИ

· Освоение стандартных способов ввода-вывода DOS.

· Разработка программ по обработке символьной информации с использованием строковых команд.

7.2. МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

7.2.1. ВЫЗОВЫ ФУНКЦИЙ MS-DOS ДЛЯ ВВОДА-ВЫВОДА СИМВОЛЬНОЙ ИНФОРМАЦИИ

Для того чтобы написать простую, но законченную программу, необходимо знать три вещи – как вводить данные, как выводить результат и как остановить выполнение программы. В языках высокого уровня имеются специальные операторы ввода/вывода, которые позволяют в удобной форме реализовать эти функции. В системе команд процессора ix86 также имеются команды ввода/вывода, но они реализуют эти операции на самом низком, физическом уровне, т.е. обеспечивают обращение к портам ввода/вывода по конкретным адресам. Для обеспечения ввода/вывода информации на этом уровне программист должен знать номера портов каждого устройства, а также протоколы или алгоритмы обслуживания этих устройств. Операционная система MS DOS реализует ряд сервисных функций ввода/вывода на логическом уровне, которые выступают как пронумерованные функции прерывания Int 21h. При этом прикладная программа пользователя должна сообщить необходимые для данной функции параметры и передать управление DOS, которая и осуществит все необходимые операции по управлению устройством на физическом уровне (где-то, возможно, обратится за помощью к BIOS), а затем вернёт управление прикладной задаче, сообщив, успешно ли завершилась операция или же была допущена ошибка.

Прерывания, в основном, можно разделить на два основных типа: аппаратные (hardware) и программные (software interrupt). Аппаратные прерывания вызываются сигналами от периферийных устройств, требующими обслуживания процессором, а программные, через посредство команды Int, вызывающей какую-либо сервисую функцию (процедуру) DOS или BIOS. Перечень функций, выполняемых операционной системой DOS, подробно изложен в п. 3.

Упрощенная схема обработки прерывания изображена на рис. 2.1. Процессор выполняет команду прерывания, используя таблицу векторов, где содержатся все адресные указатели обработчиков (аппаратных и программных) прерываний. Действия процессора при переходе на выполнение подпрограммы-обработчика (инициируемое командой Int n) и последующем возврате обратно (при встрече команды Iret) в точку выхода из основной программы показаны на рис. 2.1 цифрами в кружках. Одно и то же прерывание может выполнять несколько различных функций, код которых помещается в регистрah, а дополнительные параметры заносятся в другие регистры РОН. Возвращаемая обработчиком информация содержится в регистре al или ax, если флаг cf=0. Флаг cf устанавливается в 1, если произошла какая-либо ошибка, код которой заносится в регистр ax (так называемый код возврата ошибки). Возможные коды ошибок приводятся в руководствах по DOS [4, 10, 12].

Рис. 2.1. Упрощенная схема обработки программного прерывания Int n

Функции информационного обмена MS DOS в своём развитии изменялись от специализированных программ обмена для каждого типа устройства на основе блока управления файлами FCB (File ControlBlock) до унификации обмена на основе файловой системы через дескрипторы. Дескриптор или логический номер файла идентифицирует файл или устройство, с которым должна работать прикладная программа. Это упрощает программирование операций ввода/вывода, т.к. позволяет осуществлять обмен информации независимо от природы файла (устройства). Существует пять стандартных дескрипторов файлов, которые предоставляются прикладной программе:

· – стандартный ввод с консоли (обычно клавиатура);

· 1 – стандартный вывод на консоль (обычно экран дисплея);

· 2 – устройство вывода ошибок (всегда дисплей);

· 3 – внешнее устройство обмена AUX (асинхронный адаптер COM1);

· 4 – стандартный принтер (первый параллельный порт LPT1).

Стандартный ввод (как и стандартный вывод) можно перенаправить средствами DOS на любое устройство или в файл, а стандартная ошибка всегда связана с экраном (обычно дескриптор 2 используют для вывода диагностических сообщений). Перенаправление ввода или вывода программы осуществляет командный процессор Command.com. Если, допустим, в программе prog предусмотрен ввод данных через дескриптор стандартного ввода ²0², а вывод данных через дескриптор вывода ²1², то при обычном запуске программы командой prog.exe программа будет требовать входные данные с клавиатуры и выводить результаты своей работы на экран. Если, однако, при запуске программы использовать символ перенаправления

то система сама создаст файл file.txt, и весь вывод программы будет записан в этот файл. Ввод по-прежнему будет осуществляться с клавиатуры. Запуск программы командой

заставит программу выполняться в режиме ввода информации из файла file.dat и вывода в файл file.txt. Ни экран, ни клавиатура использоваться не будут. Сама программа ничего не знает об этих перенаправлениях – она во всех случаях обращается к стандартному устройству ввода данных и к стандартному устройству вывода данных. Просто DOS как бы подставляет ей на входе и выходе другие устройства.

7.2.2. ВВОД С КЛАВИАТУРЫ СИМВОЛЬНОЙ ИНФОРМАЦИИ

7.2.2.1. Буфер ввода данных с клавиатуры

Нажатие любой клавиши клавиатуры вызывает сигнал аппаратного прерывания (прерывания с типом 09h), заставляющий процессор прервать исполняемую программу и перейти на подпрограмму обработки прерывания от клавиатуры. Обработчик прерывания формирует двухбайтовый код с последующей засылкой его в кольцевой буфер ввода данных с клавиатуры, располагающийся по адресу 0040h:001Eh в системной области оперативной памяти. Для алфавитно-цифровых клавиш старший байт этого кода представляет scan-код клавиши (условный номер клавиши на клавиатуре), а младший – ASCII-код клавиши, т.е. 8-битовый код закреплённого за этой клавишей символа.

Заполнение буфера клавиатуры, рассчитанного на 15 слов или ударов по клавишам, происходит по мере нажатия клавиш и не связано с выполнением текущей программы. Если программе требуется ввести с клавиатуры определённый символ (или строку), она с помощью соответствующей системной функции DOS обращается к буферу ввода и, при наличии в нём данных, передаёт первый из поступивших в этот буфер символов в программу. Дело в том, что запись и считывание кодовых слов в буфер клавиатуры соответствует принципу FIFO (first in – first out, первым вошёл – первым вышел), поэтому считывание символа из буфера освобождает место для ввода последующих. Если к моменту вызова функции DOS буфер ввода оказывается пуст, DOS будет непрерывно опрашивать его состояние, ожидая появления в буфере очередного кода, а исполнение программы приостанавливается до нажатия клавиши.

Илон Маск рекомендует:  Asp отладка сценариев asp

7.2.2.2. Системные функции DOS ввода данных с клавиатуры

DOS предоставляет несколько способов ввода данных с клавиатуры [4, 5, 7, 11, 12, 13, 14]:

¨ использование группы функций Int 21h (01h, 06h, 07h, 08h, 0Ah¸0Ch), обеспечивающих посимвольный ввод с клавиатуры в разных режимах;

¨ обращение к клавиатуре, как к файлу, с помощью функции 3Fh.

Функции DOS, осуществляющие ввод с клавиатуры, различаются друг от друга некоторыми другими важными характеристиками, которые приведены в табл. 2.1.

Сравнительная характеристика функций DOS ввода с клавиатуры

Номер функции DOS

01h

06h

07h

08h

0Ah

0Bh

Ch

Реакция на Ctrl+C

Ожидание нажатия клавиши

Ввод расширенных кодов ASCII

Ввод кодов с помощью Alt/цифра

Эхо-символы. Отображение вводимого символа на экране.

Реакция на Ctrl+C. Аварийное завершение программы (ASCII-код 03h). Вызывается обработчик прерывания Int 23h, завершающий текущую программу с выходом в DOS.

Ожидание нажатия клавиши. Функция, при отсутствии символа в кольцевом буфере ожидает его ввода. Функции, обладающие этим свойством, являются синхронными, иначе – асинхронными.

Ввод расширенных кодов ASCII. Все функции DOS, считывающие данные с клавиатуры, передают в программу только ASCII-код (младший байт кодового слова клавиши), оставляя scan-код (старший байт) без внимания. Правда, это относится только к алфавитно-цифровым клавишам, т. е. клавишам, за которыми закреплены отображаемые на экране символы (94 символа со значениями ASCII-кода от 32 до 126). Особенности считывания информационных кодов с других, так называемых функциональных и управляющих клавиш, будут рассмотрены дальше в разделе ²Расширенные коды ASCII².

Очистка буфера. Процесс считывания кодов с буфера ввода может дать непредсказуемый эффект, если перед вызовом функции DOS этот буфер не был пуст. Программа, не желающая вводить набранные досрочно коды, должна очистить клавиатурный буфер с помощью специальной функции Ch прерывания 21h (при al = 0).

Ввод кодов с помощью комбинации Alt/цифра. Позволяет вводить в программу коды символов второй половины ASCII-таблицы, с использованием цифровой клавиатуры (правая часть консоли).

¨ Функция 01h. Ввод одиночного символа с эхом.

Вводит символ из стандартного устройства ввода и отображает его на устройстве стандартного вывода. Ввод каждого символа сопровождается перемещением курсора вправо на следующую позицию. При отсутствии символа ждёт ввода. При наборе строки обрабатываются управляющие клавиши: BS (шаг назад без удаления символа, AL = 08h), TAB (табуляция, AL = 09h), ENTER (переход на начало текущей строки, AL = 13h). Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет обработку . Для чтения расширенного кода ASCII требует повторного выполнения функции.

¨ Функция 06h. Ввод одиночных символов из стандартного устройства ввода и вывод одиночных символов на стандартное устройство вывода.

Режим работы определяется содержанием регистра DL в момент вызова функции: DL = FF – режим ввода, DL = <FFh – 00h > – режим вывода соответствующего этому коду символа. В режиме вывода коды ASCII: 07h – звонок, Dh – возврат каретки, Ah – перевод строки, рассматриваются как управляющие и выполняются соответствующие им действия.

Если вводимый символ в устройстве ввода присутствует, то он помещается в AL (без эха) с установкой флага ZF = 0, иначе ZF = 1. Отличительным качеством функции 06h является то обстоятельство, что она, просматривая устройство ввода, не останавливает программы (является асинхронной), если не обнаруживает в нём символа, а просто устанавливает флаг ZF = 1. Допускает перенаправление ввода-вывода. Для чтения расширенного кода ASCII требуется повторное выполнение функции.

Вызов: AH =06h, Int 21h.

ZF = 1 – устройство ввода пустое.

Вывод: DL = FE¸00. Код в регистре DL является одновременно и кодом выводимого символа.

¨ Функция 07h. Нефильтрованный ввод символа без эха.

Вводит символ из стандартного устройства ввода без его отображения на экране. При отсутствии символа ждёт его ввода. Допустимо перенаправление ввода. Не выполняет отработку . Для чтения расширенного кода ASCII требует повторное выполнение функции. Функция, как правило, используется для ввода пароля с целью защиты программы от несанкционированного запуска


¨ Функция 08h. Ввод символа без эха.

Вводит символ из стандартного устройства ввода. При отсутствии символа ждёт его ввода. Допустимо перенаправление ввода. Для чтения расширенного кода ASCII требует повторное выполнение функции. Если ввод не перенаправлен, чувствительна к (иначе надо предварительно включить режим Break). Как и функция 07h, используется для ввода пароля. Пример использования данной функции будет рассмотрен в одной из программ этой работы.

Вызов: AH = 08h, Int 21h.

Вывод: AL = код символа.

¨ Функция Ah. Буферизованный ввод с клавиатуры.

Вводит строку байт из устройства стандартного ввода в буфер пользователя по адресу DS:DX, с отображением на устройстве стандартного вывода. Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет отработку (иначе надо предварительно включить режим Break). Функция допускает редактирование данных при их вводе клавишами: Backspace (отмена последнего символа), Exc (отмена всего набранного текста), F5 (запоминает текущую строку как подсказку), F3 (восстанавливает подсказку для ввода). Ввод символов строки заканчивается нажатием клавиши , код которой (0Dh) вводится в качестве последнего символа в отведённый буфер.

Структура буфера (резервируется в сегменте данных): байт 0 – назначаемая пользователем максимальная длина строки (1-254) с учётом символа CR (код Dh), байт 1 – число реально введённых символов без учёта символа CR, байт 2 и далее – строка. В следующем примере приведена процедура In_string ввода строки в буфер, емкостью 50 символов. Она возвращает адрес первого символа строки в регистре DX, а число символов в регистре CX.

Buf DB 50. 50 DUP(?) ;Буфер пользователя

lea dx,[Buf] ;Адрес буфера пользователя

mov ah,0Ah ;Запрос функции 0Ah

int 21h ;Вызов DOS

mov cl,[Buf+1] ;Поместить счётчик символов в cx

add dx,2 ;Сделать dx указателем строки

¨ Функция 0Bh. Проверка состояния ввода.

Проверяет наличие символа в буфере клавиатуры. Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет отработку . Это даёт возможность организовать с её помощью аварийное завершение программы (нажатием комбинации ) с циклом, состоящим из чисто процессорных команд, включив предварительно в цикл вызов функции Bh.

Возврат: Если символа нет, то AL = 0, если символ ждет, то AL = FFH.

¨ Функция 0Ch. Вызов служебной функции DOS для ввода данных с предварительной очисткой буфера клавиатуры. Допускает переопределение ввода.

Вызов: AH = 0Ch, Int 21h,

AL = номер функции ввода: 01, 07, 08, 0Ah (если AL = 0, то только очистка), DS:DX = адрес буфера, если AL = 0Ah.

Выход: AL = байт входных данных (если при вызове Al = 0Ah, данные помещаются в буфер).

¨ Функция 3Fh. Ввод данных из файла или устройства.

Универсальная функция ввода данных в буфер с указателем DS:DX из источника, определённого дескриптором в регистре BX. Допускает переопределение ввода. В регистре CX указывается число байтов, которое необходимо ввести. Пример использования.

In_Area DB 20 DUP(?)

mov ah,3Fh ;Запрос функции 3Fh

mov bx,00h ;Дескриптор ввода (клавиатуры)

mov cx,20 ;Число пересылаемых байт

lea dx,[In_Area] ;Адрес буфера ввода

int 21h ;Вызов функции DOS

sub cx,2 ;Фактически введено

Команда Int 21h ожидает окончания ввода символов, которое фиксируется нажатием клавиши Enter. После ввода текста и нажатия клавиши Enter в буфер In_Aria автоматически вводятся два управляющих символа: CR (код 0Dh) и LF (код 0Ah). Вследствие данной особенности максимальное число символов и размер буфера ввода должны содержать место для двух дополнительных символов. При успешном завершении операции флаг CF = 0, а в регистре AX устанавливается число байтов, введённых с клавиатуры (плюс два дополнительных символа). Если CF = 1, то в регистре AX содержится возвратный код ошибки. Это либо 5 (отказ в доступе), либо 6 (неверный дескриптор).

К особенностям использования данной функции следует отнести автоматический переход на новую строку по окончании ввода данных.

7.2.3. ФУНКЦИИ DOS ВЫВОДА ДАННЫХ НА ЭКРАН

DOS предоставляет следующие способы вывода данных на экран:

использование функций Int 21h (02h, 06h, 09h), обеспечивающих посимвольный ввод с клавиатуры в разных режимах;

обращение к экрану, как к файлу, с помощью функции 40h.

¨ Функция 02h. Вывод одиночного символа.

Выводит символ, находящийся в регистре DL, на экран, после чего курсор сдвигается на одну позицию вправо. Для вывода строки функцию следует использовать в цикле. Допустимо перенаправление вывода. Выполняет обработку при вводе этой комбинации с клавиатуры перед выводом каждого 64-го символа. Эта функция выводит и управляющие ASCII-символы с кодами 07h, 08h, 09h, 0Ah, 0Dh. Символ с кодом 07h (bell, звонок) вызывает звуковой сигнал, с кодом 08h (backspace, забой) – возвращает курсор на одну позицию влево, с кодом 09h (tab, табуляция) – смещает курсор на одну позицию вправо, кратную 8. Действия управляющих клавиш с кодами Ah и Dh рассматривались ранее.

Вызов: AH = 02h, Int 21h.

Выход: DL = ASCII – код символа,

AL = код последнего записанного символа (кроме случая, когда DL = 09, тогда возвращается значение 20h).

Использование данной функции рассмотрим на примере процедуры перехода на новую строку.

mov ah,2 ;Запрос функции 02h

mov dl,13 ;Возврат каретки

int 21h ;Вызов DOS

mov dl,10 ;перевод строки

int 21h ;Второй вызов DOS

¨ Функция 09h. Вывод строки.

Выводит строку символов на устройство стандартного вывода (используется в системных программах для вывода на экран информационных сообщений). Строка должна заканчиваться символом $ (код24h), который служит признаком конца строки, и сам не выводится. Допустимо перенаправление вывода. В сообщение могут быть включены и управляющие коды (07h, 08h, 09h, 0Ah, 0Dh), которые вызывают соответствующие им действия (см. функцию 02h). Допустимо использование Exc-последовательностей. Функция выполняет обработку при вводе этой комбинации с клавиатуры перед выводом каждого 64-го символа.

lea dx,[Promt] ;Адрес строки Promt: DS:DX

mov ah,09h ;Запрос функции 09h

int 21h ;Вызов DOS

¨ Функция 40h. Вывод данных в файл или в устройство.

Универсальная функция вывода данных из буфера пользователя в сегменте данных в файл или на устройство, дескриптор которого указывается в регистре BX. Дескриптор 1, закреплённый за стандартным устройством вывода, обеспечивает перенаправление вывода. Значение регистра CX определяет число байтов, которые должны быть выведены, а пара регистров DS:DX указывает адрес выводимых данных. Управляющие коды 08h, 0Ah, 0Dh и некоторые другие приводят к выполнению соответствующих им действий. После завершения вывода при CF = 0 регистр AX содержит число действительно выведенных байтов, а при CF =1 – возвратный код ошибки. Как и при использовании функции 3Fh, это коды ошибок 5 или 6. Пример использования.

Out_Area DB 20 DUP(?)

mov ah,40h ;Запрос функции 40h

mov bx,01 ;Дескриптор дисплея

mov cx,20 ;Число пересылаемых байт

lea dx,[Out_Area] ;Адрес буфера для выводимого сообщения

int 21h ;Вызов DOS

7.2.4. РАСШИРЕННЫЕ КОДЫ ASCII И УПРАВЛЕНИЕ ПРОГРАММОЙ С КЛАВИАТУРЫ

Как уже отмечалось в п 7.2.2, рассмотренный процесс считывания ASCII-кодов клавиш клавиатуры с помощью системных функций DOS относится к алфавитно-цифровым клавишам, за которыми закреплены ASCII-таблицей отображаемые символы (буквы, цифры, знаки препинания и др.). Кроме них, на клавиатуре персонального компьютера имеется ряд клавиш, которым не назначены какие-либо отображаемые символы. Это, например, функциональные клавиши . , клавиши управления курсором , , . , , , специальные клавиши , , а также использующие на практике различные сочетания клавиш с , и . В этом случае, в качестве scan-кода клавиши или какой-либо комбинации из них выступает также старший байт кодового слова, но уже при нулевом младшем байте (нулевом коде ASCII). Например, при нажатии клавиши в кольцевой буфер ввода клавиатуры поступает код 3B00h, а клавиши – 4700h.

Двухбайтовые коды клавиш, содержащие на месте кода ASCII – ноль, называются расширенными кодами ASCII. Эти коды (и соответствующие им клавиши) широко используются для управления программами. Для доказательства этого утверждения достаточно указать на популярную оболочку DOS – Norton Commander. Широкое использование в компьютерах интерактивных средств требовало расширение возможностей ввода с клавиатуры управляющей информации, которую программа должна отличать от вводимого текста. Поэтому расширенные коды ASCII генерируются и всеми алфавитно-цифровыми клавишами, если они нажимаются совместно с клавишей . В табл. 2.2 приведены значения расширенных ASCII-кодов для одиночных клавиш.

Расширенные коды для функциональных клавиш

Клавиша

Код (hex)

Клавиша

Код (hex)

Клавиша

Код (hex)

Клавиша

Код (hex)


Правая часть клавиатуры.

«Num Lock-выкл»

В составе комбинации Alt+

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

Обратим здесь внимание на важный момент! Расширенный код ASCII можно считать, если программа будет настроена на проверку нулевого значения младшего байта для каждого нажатия клавиши. Пример использования функциональных клавиш для управления программой показан в листинге 2.1.

Листинг 2.1. Фрагмент программы, демонстрирующий выполнение альтернативных действий на основе анализа расширенных кодов ASCII

mes1 DB 13,10,’Сообщение $’

mes2 DB 13,10,’Сообщение $’

mes3 DB 13,10,’Сообщение $’

;Ожидаем нажатия клавиши

again: mov ah,08h ;Функция ввода одиночного символа без эха

int 21h ;Первый вызов DOS

cmp al,0 ;Расширенный ASCII код?

mov ah,08h ;Да, введём старший байт

int 21h ;Повторный вызов DOS

cmp al,3B ;Нажата F1?

cmp al,54h ;Нажата ?

cmp al,1Eh ;Нажата ?

jmp again ;Нажато незапланированное

F1: ;Вывод сообщения mes1

Shift_F1: ;Вывод сообщения mes2

Alt_A: ;Вывод сообщения mes3

Exit: ;Завершение программы

7.2.5. СТРОКОВЫЕ КОМАНДЫ. ОБЩАЯ ХАРАКТЕРИСТИКА

Строкой или литералом в языке ассемблера называется последовательность букв, цифр и других символов, заключённых в кавычки или апострофы (двойные кавычки). Следует отметить, что иногда понятие строки трактуется в расширительном смысле, а именно, как последовательность байтов, которые могут либо представлять, либо не представлять ASCII-символы.

Строковые команды, несмотря на синонимичное название со строковыми переменными, предназначены для обработки не только ASCII-строк, но и вообще блоков байтов, одинарных или двойных слов, каждое из которых хранится в памяти в двоичном коде.

Строковые команды представлены в табл. 3.1 и по своему назначению делятся на две группы:

— команды для поиска и сравнения данных (Scas, Cmps).

Любая строковая команда может оперировать как байтами, так и словами, что отражается в мнемокоде команды (например: movsb, movsw, movsd). Все строковые команды, в отличие от других команд процессора ix86, используют для выполнения своих функций одни и те же регистры:

Команды обработки строк

Название команды и её мнемокод

Действие

Тип исполь-зуемого префикса

Влияние на флаги

Lods src – Загрузка Acc из строки

src=byte ds:si Lodsb

src=word ds:si Lodsw

src=dword ds:si Lodsd

_

Stos dst – Сохранение Acc в строке

dst=byte es:di Stosb

dst=word es:di Stosw

dst=dword es:di Stosd

Movs dst,src Пересылка элемента строки

dst=byte es:di, src=byte ds:si Movsb

dst=word es:di, src=word ds:si Movsw

dst=dword es:di, src=dword ds:si Movsd

Scas dst – Поиск элемента в строке

dst=byte es:di Scasb

dst=word es:di Scasw

dst=dword es:di Scasd

Все флаги операции сравнения

Cmps dst, src Сравнение элементов строк

src=byte ds:si, dst=byte es:di Cmpsb

src=word ds:si, dst=word es:di Cmpsw

src=dword ds:si, dst=dword es:di Cmpsd

srcdst .

Все флаги операции сравнения

При этом индексные регистры si(esi) и di(edi) определяют смещения элементов строк в сегментах данных, определяемых регистрами ds и es соответственно. Установите es = ds, если это не противоречит другим условиям реализации программы, что позволит вам не беспокоиться о корректной адресации сегментов памяти. Необходимо помнить, что в строковых инструкциях приёмник – строка es:di(edi) не допускает переопределение, а источник – строка ds:si(esi), допускает переопределение на es:si(esi).

Каждая из строковых команд выполняет операцию только над парой элементов двух строк (или над одним для команд Lods, Stos, Scas) и автоматически настраивается на обработку соседних элементов, обеспечивая продвижение по строке в нужном направлении, а именно:

Здесь величина d определяется согласно правилу:

Тип операнда Флаг направления

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

rep (repeat) – повторять, пока cx ¹ 0;

Префиксы используют регистр CX как счётчик числа циклов (беззнаковое число), которое должно быть записано в CX до начала выполнения строковой команды. Счётчик CX декрементируется на 1 после выполнения строковой команды, но проверяется перед её выполнением. Если CX = 0, то строковая команда не выполняется ни разу. Префиксы repe и repne дополнительно выставляют флаг нуля ZF после выполнения строковой операции.

В листинге 2.2. рассматривается использование строковой команды сравнения cmpsb на примере программы с паролем. Идея простейшей защиты программы от несанкционированного запуска заключается в том, что где-то в программе записывается ключевое слово-пароль, и программа, начав работать, требует ввода этого слова с клавиатуры. Если пользователь ввёл пароль правильно, программа продолжит свою работу, иначе попросит ввести его заново или завершится. Ввод пароля обычно осуществляется функцией DOS, не отображающей вводимые символы на экране (обычно 07h или 08h) и заканчивается нажатием клавиши .

Листинг 2.2. Фрагмент программы с паролем.

password DB ‘camel’ ;Пароль

string DB 80 DUP(?)

promt DB 13,10,’Введите пароль: $’

OK DB 13,10,’Работаем!$’


start: mov ax,@data

begin: mov ah,09h ;Вывод запроса на ввод пароля

mov dx,offset promt ;Адрес запроса

mov bx,0 ;Инициализация индексирования ввода

pass: mov ah,08h ;Функция ввода символа в AL без эха

je compare ;Да, на сравнение

mov [string+bx],al ;Нет, сохраним символ

mov dl,’*’ ;Запишем на экран *

jmp pass ;Повторять

;Сравнение введённого пароля с действительным (сравнение строк)

compare: push ds ;Установить ES на сегмент данных

mov si,offset string ;DS:SI- начало string

mov di,jffset password ;ES:DI- начало password

cld ;DF=0- просмотр вперёд

mov cx,pass_len ;Установить счётчик сравнения

repe cmpsb ;Сравнивать, пока (или повторять

;пока символы двух строк совпадают, но не более CX раз)

jne err ;Строки не равны

Вывод сообщения ОК, подтверждающего правильность пароля

mov dx,offset OK

exit: mov ax,4C00h ;Ввод функции 4С для завершения программы

err: jmp begin ;Повторить ввод пароля

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

7.3. ЗАДАНИЯ К РАБОТЕ. ПОДГОТОВКА И ВЫПОЛНЕНИЕ

¨ Задания к работе

1) Ввести строку из произвольных ASCII-символов и произвести её сортировку под управлением функциональных клавиш: – по возрастанию; – по убыванию; – завершение программы. Работу программы отобразить на экране.

2) Ввести строку из произвольного числа символов и произвести в ней поиск подстроки SYMBOL. Если подстрока найдена, то её необходимо удалить. Вновь полученную строку вывести на экран. Если подстрока не найдена, вывести сообщение NOT_FOUND. Программу защитить паролем.

3) Ввести строку из произвольного числа символов. Выполнить преобразование символьной строки в её цифровой аналог на основе ASCII-кодов, после чего произвести поиск максимального кода. Работу программы отобразить на экране и защитить паролем.

4) Ввести строку из произвольных ASCII-символов и произвести её сортировку к виду, включающему четыре части разделённые пробелами: цифры, буквы прописные, буквы строчные, все другие символы. Работу программы отобразить на экране и защитить паролем.

5) Ввести строку из нескольких слов, разделённых пробелами. Слова включают в произвольном порядке цифры, строчные и прописные латинские буквы. Отредактированная строка включает слова, начинающиеся с прописной буквы (остальные строчные). Цифры из слов должны быть удалены. Программу защитить паролем.

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

7) Ввести строку из произвольного числа символов и произвести в ней поиск подстроки COMPUTER. Если такой подстроки нет, то данную подстроку ввести в начало исходной строки и вывести на экран. В противном случае дать сообщение There is. Программу защитить паролем.

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

9) Ввести строку из произвольного числа символов. Выполнить преобразование символьной строки в её цифровой аналог на основе ASCII-кодов, после чего произвести поиск минимального кода. Работу программы отобразить на экране и защитить паролем.

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

11) Ввод с клавиатуры на экран произвольного текста с одновременной записью в буфер. Программа демонстрирует переход на новую строку одним из двух способов:

– нажатие клавиши , если последнее введённое слово пересекло границу в 40 символов. В этом случае на новую строку автоматически переносится всё последнее слово. После перехода на новую строку вывод текста может быть продолжен в обычном порядке. Выход из программы с помощью клавиши .

12) Ввести строку из произвольного числа символов и произвести в ней поиск подстроки AUTOMATON. Если такой подстроки нет, то в начало исходной строки поместить символ @, а в её конец дописать подстроку и вывести на экран. В противном случае дать сообщение There is. Программу защитить паролем.

13) Программа проверки работоспособности ОЗУ для заданной области памяти данных с использованием шахматного теста. Тест предусматривает запись в ячейки с чётными адресами числа 0AAh, а в нечётные – 55h. В результате последующего считывания осуществляется проверка записанной информации. При обнаружении сбоя запоминается адрес данной ячейки (для проверки выполнения последнего требования использовать прогон программы в отладчике TD).

14) Программа проверки работоспособности ОЗУ для заданной области памяти с использованием сканирующего теста. Тест предусматривает запись байта 00h с последующим считыванием и проверкой, затем те же действия выполняются с числом 0FFh. По результатам теста формируется массив из адресов ячеек, в которых обнаружен сбой (для проверки выполнения последнего требования использовать прогон программы в отладчике TD). Программу оформить как com-файл.

15) Разработать программу, преобразующую все символы введённой строки (в строке представлены произвольные алфавитно-цифровые символы) из нижнего регистра клавиатуры в верхний.

¨ Подготовка и выполнение:

a) ознакомиться с методическими рекомендациями к лабораторной работе и соответствующими тематическими разделами в рекомендуемой литературе;

б) разработать и отладить программу в соответствии с индивидуальным заданием;

в) программа, по возможности, должна обеспечивать удобный экранный интерфейс с пользователем при её демонстрации;

г) отчёт о выплненной работе представляет собой:

– индивидуальное задание на разработку программы;

– листинг программы с подробными комментариями и описанием её работы.

7.4. КОНТРОЛЬНЫЕ ВОПРОСЫ

1. Что такое дескриптор? Сколько дескрипторов определено в DOS и как ими пользоваться?

2. Какие функции DOS можно использовать для ввода символов с клавиатуры в регистр AL процессора?

3. Назовите функции DOS, осуществляющие ввод строки символов с клавиатуры в память данных.

4. Какие функции DOS осуществляют операцию вывода на экран:

– одиночных символов из регистра DL процессора;

– строки символов из памяти данных?

5. Напишите процедуру перевода курсора на новую строку с помощью функции 02h DOS.

6. Что такое скан-код клавиши и чем он отличается от расширенного кода ASCII? Как нужно организовать вызовы соответствующей функции DOS для получения расширенного ASCII-кода?

7. Каким сегментным регистрам должен адресоваться сегмент данных, в котором располагается:

8. Какие строковые команды влияют на флаги, а какие нет?

9. Перечислите префиксы повторения строковых команд и их возможные сочетания друг с другом.

10. В какой фазе исполнения команды происходит проверка счётчика на равенство нулю при выполнении:

– строковой команды с префиксом повторения;

– команды управления циклом Loop ?

Что происходит с исполнением этих команд, если счётчик СХ инициализирован нулём?

Введение

Удобная компьютерная программа — это всегда программа, корректно взаимодействующая с пользователем, даже если пользователем является сам программист. Такая программа запрашивает все необходимые для ее работы данные, используя операции ввода, и выдает результаты работы с помощью операций вывода. Стандартным устройством ввода в ПК считается клавиатура, устройством вывода — экран монитора (точнее, окно приложения на экране). Совокупность клавиатуры и монитора часто называют консолью.

С/C++ дает пользователю различные возможности для программирования ввода-вывода. Эти возможности реализуются с помощью функций, входящих в состав различных библиотек. Далее мы рассмотрим две из них — консольный и потоковый ввод-ввод.

Консольный ввод-вывод

Консольный ввод-вывод организуется с помощью стандартных библиотек stdio.h и conio.h, что предполагает наличие директив #include и / или #include в заголовочной части программы.

Функция printf используется для вывода информации на экран. С ее помощью в окне приложения можно распечатать как строку простого текста, так и значения переменных различных типов. Общая форма записи соответствующего оператора

printf («форматная_строка» [, перем1] [, перем2] [,…]);


Здесь в круглых скобках указаны параметры (или аргументы) функции printf, причем первый из них, форматная строка в двойных кавычках, является обязательным. Остальные параметры, переменные различного типа, указываются по необходимости. Форматная строка может содержать:

· обычные текстовые символы, которые выводятся на экран в том же виде, как они записаны в форматной строке,

· управляющие символы, в частности символы перевода строки « », табуляции « », и некоторые другие (начинаются со знака обратной косой черты «»),

· символы форматного преобразования, которые используются для вывода значений переменных (начинаются со знака процента «%»).

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

К примеру, запись printf («Hello!») означает вывод на экран простой текстовой строки «Hello!». Запись printf («%d», x) выводит на экран значение целочисленной переменной x. Случай, когда на экран выводятся сразу две переменные, иллюстрируется следующим примером

Здесь верхние стрелки указывают позиции внутри форматной строки, куда будут выведены значения переменных i и x. Остальной текст форматной строки будет отображен без изменения. К примеру, если переменная i к моменту выполнения этого оператора имела значение 5, а переменная x была равна 1.5, на экран будет выведено: «Значение 5_й переменной равно 1.500000».

Илон Маск рекомендует:  Как убрать свечение вокруг текстового поля в Safari

Важным является соответствие символа форматного преобразования (%d, %f, и т.д.) действительному типу переменной (int, float, double и т.д.). Несоблюдение этого правила ведет к непредсказуемому результату на экране. Поэтому использованная в примере переменная i должна быть объявлена ранее как целочисленная (int), а x — как вещественная (float или double).

Функция printf также дает возможности управления выводом с помощью эскейп-последовательностей, начинающихся с символа ESC (обратный слэш «»). Некоторые из них приведены в таблице:

ht (horizontal tab)

vt (vertical tab)

bel (audible bell)

возврат на шаг (забой)

Консольный ввод может быть организован с помощью функции scanf. Вводимая при этом информация помещается в некоторую переменную. Общая форма записи этого оператора

Аргументы функции scanf во многом аналогичны соответствующим аргументам printf, за исключением того, что в качестве дополнительных параметров scanf принимает не имена переменных, а их адреса. В силу этого перед именем каждой переменной в scanf должен стоять знак операции взятия адреса «&» (амперсанд).

В момент передачи управления функции scanf выполнение программы приостанавливается в ожидании ввода от пользователя. Вся вводимая с клавиатуры информация отображается на экране (эхо-вывод). Во время ввода пользователю доступны простейшие возможности редактирования, в частности клавиша забоя Backspace. Выполнение оператора завершается, как только пользователь нажимает клавишу Enter. Введенная информация при этом будет приведена к соответствующему типу и записана в переменную.

Функция getch из библиотеки conio.h не имеет параметров и используется для ввода с клавиатуры отдельного символа нажатой клавиши. В отличие от scanf, эта функция не требует нажатия Enter для подтверждения конца ввода. Оператор завершает работу сразу после того, как нажата любая клавиша. Ваша программа может анализировать возвращаемое этой функцией значение с тем, чтобы немедленно на него реагировать. Мы будем также использовать эту функцию в конце программы для того, чтобы приостановить закрытие окна на время ознакомления с результатами работы.

Рассмотрим следующий пример работы с функциями консольного ввода-вывода.

Пример 1. Напишите программу, выводящую на экран символы звездочки «*» в форме ромба, как это показано на рисунке справа.

Решение. Задача может быть решена несколькими способами. Ниже приводится один из вариантов.

#include // Подключаем библиотеки

#include // консольного ввода-вывода

int main (int argc, char* argv[])

printf (» * »); // В программе используем несколько

printf (» * * »); // последовательных вызовов функции

printf (» * * »); // printf для вывода на экран

printf («* * »); // отдельных строк рисунка.

printf (» * * »); // Каждую строку заканчиваем

printf (» * * »); // управляющим символом ` ‘.

printf (» * »); //

getch(); // Задержка до нажатия любой клавиши

Ввод информации с клавиатуры средствами MS-DOS

Функции прерывания 21h MS-DOS для ввода информации с клавиатуры

MS-DOS имеет целую группу функций прерывания 21h для выполнения ввода информации с клавиатуры. Последователь­ность действий системы при вводе с клавиатуры такова. Функция MS-DOS вызывает драйвер клавиатуры, передавая ему запрос на ввод одного символа из буфера клавиатуры. Драйвер, выполняя запрос, обращается к нужной функции прерывания 16h BIOS. ISR BIOS прерывания 16h читает из буфера клавиатуры нужное слово и передает в драйвер. Драйвер возвращает байт (обычно младший) в MS-DOS. Та­ким образом, функции MS-DOS и опирающиеся на них функции библиотеки Turbo С слабо зависят от особенностей аппаратуры, поскольку система от нее изолирована двумя слоями программного обеспечения — драйверами и BIOSом.

Далее приводится характеристика функций MS-DOS, используемых для ввода с клавиатуры.

AH=01h — ввод с ожиданием со стандартного устройства ввода (клавиатуры). Выполняется «эхо» на экран вводимых символов. ASCII-код прочитанного символа помещается в AL. Если нажимается специаль­ная клавиша, в AL возвращается 0, а второе обращение к функции возвращает расширенный скэн-код клавиши.

AH=06h — ввод-вывод с консоли. Если DL = FFh, выполняется ввод со стандартного устройства ввода без ожидания. Если буфер пуст, функция сообщает об этом установленным в 1 флагом нуля (ZF). В противном случае в регистре AL возвращается ASCII-код прочитанного символа.

AH=07h — ввод с консоли с ожиданием без «эха» на экран. ASCII-код прочитанного символа возвращается в AL. Если нажимается специальная клавиша, передаваемое в AL значение равно нулю, а второе обращение к функции возвращает расширенный скэн-код клавиши. Функция не выполняет «фильтрацию» ввода с клавиатуры. Это значит, что нажатие клавиши Backspace не стирает символ на экране, а только сдвигает курсор. Нажатие ENTER не переводит строку, а только перемещает курсор на начало строки.

AH=08h — подобна АН=07h, за исключением того, что если обнаруживается нажатие комбинации клавиш Ctrl-Break, вы­зывается прерывание 23h.

AH=0Bh — проверка состояния стандартного ввода. Возвращает в регистре AL значение FFh, если буфер клавиатуры не пуст, и 0 в противном случае. Функцию следует использовать перед выполнением функций АН=01h, 07h и 08h для того, чтобы избежать ожидания ввода, если он отсутствует. Кроме того, функция используется как средство проверки того, нажата ли комбинация клавиш Ctrl-Break, если программа долгое время выполняет работу, не связанную с обращением к функциям MS-DOS. Периодическое выполнение функции позволяет аварийно завершить программу, например, в случае ее зацикливания.

AH=0Ch — ввод с клавиатуры с очисткой буфера. Значение в регистре AL содержит номер выполняемой функции: 01, 06, 07, 08 или 0Ah. Поведение функции и возвращаемые значения описаны ранее в спецификации функций АН=01, 06, 07,08 или 0Ah.

Рассмотренные функции MS-DOS для ввода с клавиатуры могут вызываться напрямую из программы через функции getinterrupt(), int86(), intr() и т.п., либо неявно другими функциями ввода.

4.3.2. Функции библиотеки С++

Выполняет ввод с клавиатуры через функцию MS-DOS АН=07h. Она не выполняет «эхо» вывода на экран. В этой связи полезна для организации интерфейса с пользователем, при котором нажатие той или иной клавиши вызывает немед­ленную реакцию программы без отображения введенного символа на экране.

int getche (void)

Выполняет небуферизуемый ввод с клавиатуры через функцию MS-DOS AH=07h, но в отличие от предыдущей функции обеспечивает вывод введенного символа на экран. Перевод строки происходит при достижении правой вертикальной границы текущего активного окна.

char *getpass(char * prompt)

Выводит на экран ASCII-строку, на начало которой указывает prompt, a затем принимает с клавиатуры без «эха» строку символов. Вводимые символы (не более 7) помещаются во внутреннюю статическую память. Функция возвращает указатель на внутреннюю статическую строку, переопределяемую каждым новым обращением к функции. Основное назначение данной функции — ввод паролей в программе без отображения их на экран.

Проверяет, пуст ли буфер клавиатуры. Если в буфере есть символы, функция возвращает ненулевое значение, в противном случае она возвращает 0. Использует функцию 0Bh MS-DOS. Является удобным средством предотвращения «зацикливания» при ожидании невозможного в данный момент события. Кроме того, при выполнении функции 0Bh осуществляется проверка нажатия комбинации клавиш Ctrl-Break, что позволяет выполнить аварийное завершение программы.

Ввод информации с клавиатуры средствами BIOS

Интерфейсом программ в персональном компьютере с клавиатурой является прерывание 16h BIOS. Далее приводится описание его функций.

АН = 00h — чтение с ожиданием двухбайтового кода из буфера клавиатуры. Прочитанный код возвращается в регистре АХ: младший байт — в регистре AL, старший — в АН. Если нажата ASCII-клавиша, в AL помещается ASCII-код символа, в АН — скэн-код. При нажатии специальных клавиш AL равен 0, а в АН возвращается расширенный скэн-код.

АН = 0lh — чтение без ожидания двухбайтового кода из буфера клавиатуры. Если буфер пуст, в 1 выставляется флаг нуля ZF. В противном случае в АХ возвращается двухбайтовый код из буфера клавиатуры, но продвижение указателя «головы» буфера не производится, т.е. код «остается» в буфере.

АН = 02h — определение состояния шифт- и триггерных клавиш. В регистре AL возвращается содержимое байта по ад­ресу 40:17h (см. табл. 4.1).

Функция АН = 05h не имеет аналогов в библиотеке Turbo С и может использоваться для имитации нажатии клавиш в демонстрационных программах, программах переноса текста и т.д.

Функции АН = 10 — 12h являются аналогами функций 00 — 02h, но предназначены для использования в компьютерах с клавиатурой 101 /102 клавиши.

Функции АН = 00 — 02h прерывания 16h BIOS положены в основу функции bioskey() библиотеки Turbo С. Далее следует описание этой функции.

int bioskey(int cmd)

Обращается в зависимости от значения в cmd к функциям АН = 00 — 02h прерывания 16h. Возвращаемое функцией значение повторяет значение регистра АХ при выходе из прерывания.

4.5. Предварительная подготовка к работе

1.Ознакомиться с аппаратными средствами компьютера для ввода информации с клавиатуры.

2. Ознакомиться с программными средствами для ввода информации с клавиатуры.

Порядок выполнения работы

1. Разработать, написать и отладить программу управления пе­ремещением символа (например, «*») в пределах заданного на экране окна. Для управления использовать клавиши из набора: «стрелка вверх» (СтВВ), «стрелка вниз» (СтВН), «стрелка вправо» (СтВП), «стрелка влево» (СтВЛ) или функциональные клавиши Fl — F12 (вари­анты см. в таблице 4.2). Для ввода использовать стандартные функции языка C++. Сохранить отлаженную программу.

2. Изменить программу, заменив стандартные функции библиотеки C++ своими. Для написания функций используйте заданное прерывание (см. таблицу), если его возможностей достаточно. Если его возможностей не достаточно, то замените его по своему усмотрению. Сохраните отлаженную программу.

3. Отлаженные программы предъявить преподавателю.

№ варианта X1 Y1 X2 Y2 Вид движения Клавиши управления Номер прерывания
Постоянное СтВВ, СтВН INT 21h
Пошаговое СтВП, СтВЛ INT 21h
Постоянное F1, F2 INT 21h
Пошаговое Все направления INT 21h
Постоянное F5, F6 INT 16h
Пошаговое F1-F4 INT 16h
Постоянное F9-F12 INT 16h
Пошаговое СтВВ, СтВН INT 16h
Постоянное СтВП, СтВЛ INT 21h
Пошаговое Все направления INT 21h
Постоянное F3, F4 INT 21h
Пошаговое F7, F8 INT 21h
Постоянное СтВВ, СтВН INT 16h
Пошаговое СтВП, СтВЛ INT 16h
Постоянное F9, F10 INT 16h
Пошаговое F11, F12 INT 16h
Постоянное СтВВ, СтВН INT 21h
Пошаговое СтВП, СтВЛ INT 21h
Постоянное F5, F10 INT 21h
Пошаговое F6, F12 INT 21h

Содержание отчета

1. Краткие сведения о подсистеме ввода информации с клавиатуры, используемых прерываниях, буфере клавиатуры и функциях обслуживания ввода с клавиатуры.

2. Алгоритмы и тексты отлаженных программ.

4.8. Контрольные вопросы


1. Что относится к устройствам ввода информации в ЭВМ?

2. Как можно классифицировать устройства ввода?

3. Назовите основные характеристики устройств ввода информации.

4. Зачем нужен буфер клавиатуры?

5. Почему существует ввод с буферизацией и без нее?

6. Какие бывают прерывания?

7. Зачем для ввода данных с клавиатуры используют прерывания?

8. Какое прерывание вырабатывается при нажатии клавиши?

9. Назовите основные характеристики системы прерываний.

10. Почему нужны программные прерывания?

11. Почему для организации ввода с клавиатуры используются два программных прерывания INT 21h и INT 16h?

12. Какие функции библиотеки C++ для ввода с клавиатуры Вы знаете?

13. Какие функции прерывания INT 16h Вы знаете?

14. Какие функции прерывания INT 21h Вы знаете?

15. Можно ли в прикладной программе обойтись без ввода с клавиатуры?

Лабораторная работа № 5.

Последнее изменение этой страницы: 2020-06-06; Нарушение авторского права страницы

Asmworld Программирование на ассемблере для начинающих и не только

Учебный курс. Часть 23. Ввод чисел с консоли

Автор: xrnd | Рубрика: Исходники, Учебный курс | 07-08-2010 | Распечатать запись

В прошлой части мы научились преобразовывать числа в строку и выводить на консоль. А в этой займёмся обратной задачей — вводом чисел с консоли и преобразованием строки в число. Поскольку ввод в двоичном и восьмеричном виде используется редко, я рассмотрю только примеры ввода чисел в десятичном виде (со знаком и без знака) и в шестнадцатеричном.

Вводить числа сложнее, чем выводить, так как помимо преобразования необходимо проверять корректность введённой пользователем строки. Хорошая программа должна устойчиво работать при любых входных данных (в том числе специально введённых так, чтобы нарушить её работу).

Ввод строки с консоли

Для ввода строки можно использовать функцию MS-DOS 0Ah. Функция позволяет ввести строку длиной от 1 до 254 символов. При вызове в DX передаётся адрес буфера, первый байт которого должен содержать максимально допустимую длину строки. Длина считается вместе с символом конца строки CR (0dh). В результате работы функции во второй байт буфера записывается фактическая длина введённой строки (не считая символа CR). Начиная с третьего байта в буфер записываются символы строки. Подробнее о работе функции можно узнать в раритетном справочнике по DOS ��

Чтобы удобнее было использовать эту функцию, можно написать небольшую процедуру. Например, такую:

;Процедура ввода строки c консоли ; вход: AL — максимальная длина (с символом CR) (1-254) ; выход: AL — длина введённой строки (не считая символа CR) ; DX — адрес строки, заканчивающейся символом CR(0Dh) input_str: push cx ;Сохранение СX mov cx,ax ;Сохранение AX в CX mov ah,0Ah ;Функция DOS 0Ah — ввод строки в буфер mov [buffer],al ;Запись максимальной длины в первый байт буфера mov byte[buffer+1],0 ;Обнуление второго байта (фактической длины) mov dx,buffer ;DX = aдрес буфера int 21h ;Обращение к функции DOS mov al,[buffer+1] ;AL = длина введённой строки add dx,2 ;DX = адрес строки mov ah,ch ;Восстановление AH pop cx ;Восстановление CX ret . buffer rb 256

Процедура использует отдельно объявленный буфер. В качестве единственного параметра ей передаётся максимальная длина строки в регистре AL. После возврата из процедуры в этот регистр записывается фактическая длина строки, а в регистр DX — адрес начала строки. Старшая часть AX сохраняется.

Ввод десятичных чисел без знака

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

34710 = 3·10 2 + 4·10 1 + 7·10 0 = (3·10 + 4)·10 + 7

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

Следующая процедура преобразует строку в слово в регистре AX. Адрес строки передаётся в DX, длина строки передаётся в AL. Если строка не корректна, процедура возвращает 0 и устанавливает флаг CF. Ошибка возвращается в следующих случаях:

  • строка имеет нулевую длину, то есть пустая строка;
  • строка содержит любые символы кроме десятичных цифр;
  • число находится вне границ диапазона представления чисел (для слова без знака 0…65535).

;Процедура преобразования десятичной строки в слово без знака ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка str_to_udec_word: push cx ;Сохранение всех используемых регистров push dx push bx push si push di mov si,dx ;SI = адрес строки mov di,10 ;DI = множитель 10 (основание системы счисления) movzx cx,al ;CX = счётчик цикла = длина строки jcxz studw_error ;Если длина = 0, возвращаем ошибку xor ax,ax ;AX = 0 xor bx,bx ;BX = 0 studw_lp: mov bl,[si] ;Загрузка в BL очередного символа строки inc si ;Инкремент адреса cmp bl,’0′ ;Если код символа меньше кода ‘0’ jl studw_error ; возвращаем ошибку cmp bl,’9′ ;Если код символа больше кода ‘9’ jg studw_error ; возвращаем ошибку sub bl,’0′ ;Преобразование символа-цифры в число mul di ;AX = AX * 10 jc studw_error ;Если результат больше 16 бит — ошибка add ax,bx ;Прибавляем цифру jc studw_error ;Если переполнение — ошибка loop studw_lp ;Команда цикла jmp studw_exit ;Успешное завершение (здесь всегда CF = 0) studw_error: xor ax,ax ;AX = 0 stc ;CF = 1 (Возвращаем ошибку) studw_exit: pop di ;Восстановление регистров pop si pop bx pop dx pop cx ret

Для установки флага CF используется команда STC. Сбросить флаг CF можно командой CLC. В коде данной процедуры она не используется, так как в случае успешного завершения цикла флаг CF всегда будет равен 0.

На основе этой процедуры несложно написать ещё одну для ввода чисел размером 1 байт. Сначала строка преобразуется в слово без знака, а затем выполняется проверка старшей части на равенство нулю. Обратите внимание, что команда TEST всегда сбрасывает флаг CF.

;Процедура преобразования десятичной строки в байт без знака ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка str_to_udec_byte: push dx ;Сохранение регистров push ax call str_to_udec_word ;Преобразование строки в слово (без знака) jc studb_exit ;Если ошибка, то возвращаем ошибку test ah,ah ;Проверка старшего байта AX jz studb_exit ;Если 0, то выход из процедуры (здесь всегда CF = 0) xor al,al ;AL = 0 stc ;CF = 1 (Возвращаем ошибку) studb_exit: pop dx mov ah,dh ;Восстановление только старшей части AX pop dx ret

Следующие две процедуры совмещают ввод строки с преобразованием строки в число. Для слова нужно ввести максимум 5 символов, а для байта — максимум 3.

;Процедура ввода слова с консоли в десятичном виде (без знака) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка input_udec_word: push dx ;Сохранение DX mov al,6 ;Ввод максимум 5 символов (65535) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_udec_word ;Преобразование строки в слово (без знака) pop dx ;Восстановление DX ret

;Процедура ввода байта с консоли в десятичном виде (без знака) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка input_udec_byte: push dx ;Сохранение DX mov al,4 ;Ввод максимум 3 символов (255) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_udec_byte ;Преобразование строки в байт (без знака) pop dx ;Восстановление DX ret

Ввод десятичных чисел со знаком

Ввод чисел со знаком немного труднее. Необходимо проверить первый символ строки: если это символ ‘-‘, то число отрицательное. Кроме того, нужно внимательно проверить диапазон представления (для слова со знаком -32768…32767). Строку без символа ‘-‘ можно преобразовать процедурой для беззнакового числа.

;Процедура преобразования десятичной строки в слово со знаком ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка str_to_sdec_word: push bx ;Сохранение регистров push dx test al,al ;Проверка длины строки jz stsdw_error ;Если равно 0, возвращаем ошибку mov bx,dx ;BX = адрес строки mov bl,[bx] ;BL = первый символ строки cmp bl,’-‘ ;Сравнение первого символа с ‘-‘ jne stsdw_no_sign ;Если не равно, то преобразуем как число без знака inc dx ;Инкремент адреса строки dec al ;Декремент длины строки stsdw_no_sign: call str_to_udec_word ;Преобразуем строку в слово без знака jc stsdw_exit ;Если ошибка, то возвращаем ошибку cmp bl,’-‘ ;Снова проверяем знак jne stsdw_plus ;Если первый символ не ‘-‘, то число положительное cmp ax,32768 ;Модуль отрицательного числа должен быть не больше 32768 ja stsdw_error ;Если больше (без знака), возвращаем ошибку neg ax ;Инвертируем число jmp stsdw_ok ;Переход к нормальному завершению процедуры stsdw_plus: cmp ax,32767 ;Положительное число должно быть не больше 32767 ja stsdw_error ;Если больше (без знака), возвращаем ошибку stsdw_ok: clc ;CF = 0 jmp stsdw_exit ;Переход к выходу из процедуры stsdw_error: xor ax,ax ;AX = 0 stc ;CF = 1 (Возвращаем ошибку stsdw_exit: pop dx ;Восстановление регистров pop bx ret

Обратите внимание, что для перехода после проверки диапазона используется команда JA (как для сравнения чисел без знака). Ввод байта со знаком реализуется с помощью той же процедуры и дополнительной проверки диапазона значения.

;Процедура преобразования десятичной строки в байт со знаком ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка str_to_sdec_byte: push dx ;Сохранение регистров push ax call str_to_sdec_word ;Преобразование строки в слово (со знаком) jc stsdb_exit ;Если ошибка, то возвращаем ошибку cmp ax,127 ;Сравнение результата с 127 jg stsdb_error ;Если больше — ошибка cmp ax,-128 ;Сравнение результата с -128 jl stsdb_error ;Если меньше — ошибка clc ;CF = 0 jmp studb_exit ;Переход к выходу из процедуры stsdb_error: xor al,al ;AL = 0 stc ;CF = 1 (Возвращаем ошибку) stsdb_exit: pop dx mov ah,dh ;Восстановление только старшей части AX pop dx ret

Наконец, ещё две процедуры совмещают ввод строки с преобразованием её в слово и байт со знаком.

;Процедура ввода слова с консоли в десятичном виде (со знаком) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка input_sdec_word: push dx ;Сохранение DX mov al,7 ;Ввод максимум 7 символов (-32768) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_sdec_word ;Преобразование строки в слово (со знаком) pop dx ;Восстановление DX ret

;Процедура ввода байта с консоли в десятичном виде (со знаком) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка input_sdec_byte: push dx ;Сохранение DX mov al,5 ;Ввод максимум 3 символов (-128) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_sdec_byte ;Преобразование строки в байт (со знаком) pop dx ;Восстановление DX ret

Полный исходный код примера вы можете скачать отсюда: inputdec.asm. В случае некорректной строки программа выводит сообщение об ошибке и повторяет запрос ввода числа:

Ввод шестнадцатеричных чисел

Преобразование шестнадцатеричной строки в число несколько проще. Удобно реализовать в виде отдельной процедуры преобразование одной цифры. Процедура воспринимает символы ‘A’-‘F’ независимо от регистра. Так как перед вычитанием выполняются проверки, флаг CF всегда будет равен нулю после успешного преобразования.

;Процедура преобразования шестнадцатеричной цифры в число ; вход: DL — символ-цифра ; выход: DL — значение цифры (0-15, в случае ошибки DL = 0) ; CF = 1 — ошибка convert_hex_digit: cmp dl,’0′ ;Сравнение с символом ‘0’ jl chd_error ;Если меньше, возвращаем ошибку cmp dl,’9′ ;Сравнение с символом ‘9’ jg chd_a_f ;Если больше, то возможно это буква a-f или A-F sub dl,’0′ ;Преобразование цифры в число ret ;Возврат из процедуры (здесь всегда CF = 0) chd_a_f: and dl,11011111b ;Преобразование буквы в верхний регистр cmp dl,’A’ ;Сравнение с символом ‘A’ jl chd_error ;Если меньше, возвращаем ошибку cmp dl,’F’ ;Сравнение с символом ‘F’ jg chd_error ;Если больше, возвращаем ошибку sub dl,’A’-10 ;Преобразуем букву в число ret ;Возврат из процедуры (здесь тоже всегда CF = 0) chd_error: xor dl,dl ;DL = 0 stc ;CF = 1 ret ;Возврат из процедуры

Теперь легко можно написать преобразование шестнадцатеричной строки в слово. Вместо умножения на 16 в процедуре используется сдвиг на 4 бита влево, а вместо сложения — операция ИЛИ. Проверки диапазона значения не нужны, достаточно проверить длину строки и преобразовать цифры.

;Процедура преобразования шестнадцатеричной строки в слово ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка str_to_hex_word: push cx ;Сохранение регистров push dx push si movzx cx,al ;CX = счётчик цикла = длина строки jcxz sthw_error ;Если длина строки = 0, возвращаем ошибку cmp cx,4 jg sthw_error ;Если длина строки больше 4, возвращаем ошибку xor ax,ax ;AX = 0 mov si,dx ;SI = адрес строки sthw_lp: mov dl,[si] ;Загрузка в DL очередного символа строки inc si ;Инкремент адреса строки call convert_hex_digit ;Преобразование шестнадцатеричной цифры в число jc sthw_error ;Если ошибка, то возвращаем ошибку shl ax,4 ;Сдвиг AX на 4 бита влево or al,dl ;Добавление преобразованной цифры loop sthw_lp ;Команда цикла jmp sthw_exit ;CF = 0 sthw_error: xor ax,ax ;AX = 0 stc ;CF = 1 sthw_exit: pop si ;Восстановление регистров pop dx pop cx ret

Для ввода байта используется та же процедура, но дополнительно проверяется длина строки — она должна быть не больше 2.

;Процедура преобразования шестнадцатеричной строки в байт ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка str_to_hex_byte: push cx ;Сохранение CX mov cx,ax ;Сохранение AX в CX cmp al,2 ;Проверка длины строки jg sthb_error ;Если больше 2, возвращаем ошибку call str_to_hex_word ;Преобразование строки в слово jnc sthb_exit ;Если нет ошибки, то переход к выходу из процедуры sthb_error: stc ;CF = 1 sthb_exit: mov ah,ch ;Восстановление AH pop cx ;Восстановление CX ret

Ещё две процедуры для ввода и преобразования строки, также как для десятичного ввода:

;Процедура ввода слова с консоли в шестнадцатеричном виде ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка input_hex_word: push dx ;Сохранение DX mov al,5 ;Ввод максимум 4 символов (FFFF) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_hex_word ;Преобразование строки в слово pop dx ;Восстановление DX ret

;Процедура ввода байта с консоли в шестнадцатеричном виде ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка input_hex_byte: push dx ;Сохранение DX mov al,3 ;Ввод максимум 2 символов (FF) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_hex_byte ;Преобразование строки в байт pop dx ;Восстановление DX ret

Полный исходный код примера: inputhex.asm. Как и в примере с десятичными числами, программа повторяет запрос ввода, пока не будут введены корректные данные:

Упражнение

Напишите программу для ввода байта с консоли в двоичном виде. Желательно с проверкой корректности ввода �� Результаты можете писать в комментариях или на форуме.

Ещё раз ссылки на примеры:

  • inputdec.asm — ввод десятичных чисел с консоли (со знаком и без)
  • inputhex.asm — ввод шестнадцатеричных чисел с консоли

Комментарии:

Здаравсвуйте!
Вот, кажется работает.

vvod db 13,10,’Vvedite byte v dvoichnom vide: $’
pak db 13,10,’Press any key…$’
oshibka db 13,10,’Error!$’,13,10
ok db 13,10,’OK!$’,13,10
buffer rb 10
vved_byte rb 1
;—————————
start:
mov byte[buffer],10
mov byte[buffer+1],0
mov dx,vvod
mov ah,09h
int 21h
mov dx,buffer
mov ah,0Ah
int 21h
add dx,2
mov al,byte[buffer+1]
cmp al,8
jne error
xor di,di
mov di,2
mov cx,8
lp:
mov dl,byte[buffer+di]
cmp dl,’0′
jne odin
shl bl,1
inc di
loop lp
jmp fsjo
odin:
cmp dl,’1′
jne error
or bl,00000001b
shl bl,1
inc di
loop lp
fsjo:
mov [vved_byte],bl
mov dx,ok
mov ah,09h
int 21h
mov dx,pak
mov ah,09h
int 21h
mov ah,08h
int 21h
mov ax,4c00h
int 21h

error:
mov dx,oshibka
mov ah,09h
int 21h
jmp start

Привет!
Хорошая программа, работает правильно, но есть ошибки.


Можно ввести 9 символов. При этом размер буфера оказывается мал. Последний символ вводится в vved_byte, а символ конца строки затирает первый байт команды mov byte[buffer],10. По счастливой случайности, твоей программе это не мешает работать ��

Тебе нужно в первый байт буфера записать 9, а не 10.

Тогда размер буфера 9+2 = 11 байтов

Кроме того, можно твою программу сильно оптимизировать. Убрать xor di,di, убрать add dx,2 (похоже вообще бесполезное действие) и не делить цикл на 2 ветки. У тебя получается 2 команды loop и ещё по две повторяющихся команды.

А-а-а, теперь понял чего она глючила. Исправил, спасибо.

Привет!
При решении заданий иногда хочется повторить какой-нибудь предыдущий урок.
Было бы удобней, если была бы ссылка «предыдущая часть».

Хорошая идея. Сделаю обязательно ��

Вот, что у меня получилось:

; ввод байта с консоли в двоичном виде
use16
org 100h
jmp start
lb db 11 dup(9) ;1(MAX)+1(LEN)+8(TEXT)+1(0DH)=11
;запись мах длины,чтоб не пусто было �� (8+1(CR))
lb1 db ?
s_byte db ‘Enter byte: $’
s_error db 13,10,’ERROR!’,13,10,’$’
s_pak db 13,10,’OK! Press any key for exit’,13,10,’$’
start:
mov dx,s_byte
call print_str; печать ‘Enter byte: ‘
call input_str; ввод чего-нибудь
call str_to_byte; преобразование строкового байта
jnc in_end ;;если не было ошибок — выход
mov dx,s_error
call print_str ;печать ‘ERROR!’
jmp start; может что-нибудь введут правильное
in_end:
mov dx,s_pak
call print_str ;печать ‘Press any key…’

mov ah,8
int 21h

Илон Маск рекомендует:  Что такое код create index

mov ax,4C00h
int 21h
;———————————————————————
;Процедура ввода строки с консоли
;выход CX = длина введённой строки и
;в DX = адрес строки
input_str:
push ax
mov dx,lb ;DX = адрес буфера
mov ah,0Ah ;
int 21h ;ввод строки
movzx cx,[lb+1] ;CX = длина введённой строки
add dx,2
pop ax
ret
;———————————————————————
Процедура преобразования
;в lb1 результат
str_to_byte:
push cx
push bx
push si

mov si,dx ;SI = DX
xor ax,ax ;AX = 0
xor bx,bx ;BX = 0

studw_lp:
jcxz error ;Если длина введённой строки = 0, возвращаем ошибку
lp1: mov bl,[si] ;BL=символ строки
cmp bl,’0′ ;символ= ‘0’?
jz stu ;если да, то преобразуем
cmp bl,’1′ ;символ=’1′?
jnz error ; если нет, возвращаем ошибку
stu: sub bl,’0′ ;\
shl al,1 ; преобразуем
add al,bl ;/
inc si ;
loop lp1 ;
jmp studw_exit ;завершаем

error:
xor ax,ax ;AX = 0
stc ;CF = 1 (ERROR)

studw_exit:
mov [lb1],al;сохраняем полученное
pop si
pop bx
pop cx
ret
;———————————————————————
;Процедура вывода строки на консоль
; DX — адрес строки
print_str:
push ax
mov ah,9
int 21h
pop ax
ret

Получилось хорошо, всё правильно написано.

Можно немного сократить проверку введённого символа. Вместо первой команды сравнения сразу делать вычитание символа ‘0’. Команда CMP делает то же самое, но результат не сохраняется.

lp1: mov bl,[si] ;BL=символ строки sub bl,’0′ ;символ= ‘0’? jz stu ;если да, то преобразуем cmp bl,1 ;символ=’1′? jnz error ; если нет, возвращаем ошибку stu: shl al,1 ; преобразуем add al,bl

use16
org 100h
mov al,9;———максимальный размер 8(9-1)
call input_str; —-процедура сохраняет ведённые значения
xor dx,dx ;—очищаем так как процедура изменила значение
xor bx,bx ;
xor ax,ax ;
mov al,11111110b ; этот байт используется для обнуление 1 бита
mov bh,11111111b; этот байт значение
mov si,2 ; — данные начинаются со смещения 2
mov cl,[buffer+1] ; узнаём длину , ведёной строки
cmp cx,8 ; если длинна больше 8 или меньше ошибка
jnz metca3

zicol:
JCXZ metca4 ; может возникнуть ситуация при которой CX=0 , а loop -1 и cx= ffff
mov bl,byte[buffer+si] ; выгружаем значения из памяти в bl
inc si
sub bl ,30h ; 30h -для десятичных чисел , чтобы преобразовать строку в число
jz metca2 ; если вели 0 — (30-30) FZ=0
cmp bl ,1 ; если вели 1 — (1-1) FZ=0
jz metca1 ;1
jnz metca3; если вели не 1 и не 0 (ошибка), сообщение об ошибка будет выведена ;на экран
loop zicol

jmp metca4 ; если ошибок не было программа закроется

metca1: ; если вели 1 , цыкал просто уменьшится на 1
dec cx
jmp zicol

metca2:;если вели 0
push cx ; сохраняем cx
push ax ;для того что бы ноль всегда был 0(битом) и не менял положение при ;сдвиги
dec cx ; тут уменьшается счётчик сдвига на 1 , так как ноль это 0 бит
; если сдвинуть на 1 , обнулится 2 бит а не первый
rol al,cl ; сдвик
AND bh,al ; копируем результат в bh
pop ax ; восстанавливаем позицию нуля в байте
pop cx
dec cx ; уменьшаем счётчик цыкал
jmp zicol
metca3:
mov dx ,error
mov ah,09h
int 21h
mov ah,08h
int 21h
metca4:
mov ax,4C00h
int 21h
;—————
error db ‘error$’
buffer rb 256
rezultat rb 2

input_str: ; позаимствована у автора ,)
push cx
mov cx,ax
mov ah,0Ah
mov [buffer],al
mov byte[buffer+1],0
mov dx,buffer
int 21h
mov al,[buffer+1]
add dx,2
mov ah,ch
pop cx
ret

Вроде работает, но есть ошибки.

Обнулять регистры не обязательно, если ты всё равно что-то в них записываешь.
Кстати, позаимствованная процедура возвращает адрес строки и длину, можно не вычислять заново.

Вот здесь сравнение может быть неверным:

mov cl,[buffer+1] ; узнаём длину , ведёной строки cmp cx,8 ; если длинна больше 8 или меньше ошибка

Длина записывается только в младшую часть CX, поэтому и сравнивать надо CL, либо явно обнулить CH.

jz metca1 ;1 jnz metca3; если вели не 1 и не 0 (ошибка) loop zicol jmp metca4 ; если ошибок не было программа закроется

В этом коде команда LOOP никогда не будет выполнена. Переход, если ноль, и переход, если не ноль — то есть в любом случае будет переход �� Команда JMP тоже лишняя.

Ты используешь интересный алгоритм — если символ ‘0’, то сбрасывается соответствующий бит (если я правильно понял).

Следующий код можно оптимизировать:

metca1: ; если вели 1 , цыкал просто уменьшится на 1 dec cx jmp zicol metca2:;если вели 0 push cx ; сохраняем cx push ax ;для того что бы ноль всегда был 0(битом) dec cx ; тут уменьшается счётчик сдвига на 1 , так как ноль это 0 бит ; если сдвинуть на 1 , обнулится 2 бит а не первый rol al,cl ; сдвик AND bh,al ; копируем результат в bh pop ax ; восстанавливаем позицию нуля в байте pop cx dec cx ; уменьшаем счётчик цыкал jmp zicol

Например, разместить метку metca1 перед двумя последними командами.
Или сохранять CX не обязательно, если после извлечения из стека снова выполняется декремент. Сохранять и восстанавливать AX тоже как-то сложно.
Можно просто присваивать AL нужное значение.

metca1: ; если вели 1 , цыкал просто уменьшится на 1 dec cx jmp zicol metca2:;если вели 0 mov al,0FEh dec cx rol al,cl ; сдвик AND bh,al ; копируем результат в bh jmp zicol

Стало гораздо проще .
Спасибо ,что тратещ своё время на разбегание такова зачистившую бреда ,)
Кроме этого сайта я негде и не практиковался в ассемблере .

Для начинающего у тебя неплохо получается. Просто некоторые вещи приходят с опытом.

Столкнулся с проблемой написании программы. При вычислении результируещего
байта в цикле на loopz происходит выход при CX > 0 и любом значении ZF.
Версия компилятора fasm 1.69
Версия отладчика td 3.0

; Напишите программу для ввода байта с консоли в двоичном виде.
; Желательно с проверкой корректности ввода.

use16
org 100h
jmp START
;—————————————
hex_digit db ‘0123456789ABCDEF’
out_str db 13,10,’ h’,13,10,’$’
err_str db 13,10,’Error binary digit’,13,10,’$’
;—————————————
START:
; Получаем двоичное представление байта в виде строки
mov al, 8
call input_str

; Строка корректна, если не содержит символов кроме 0 и 1
movzx cx, al
mov di, 0FFFFh
LOOP1:
inc di
cmp byte[bx+di], ‘0’
jz END_LOOP1
cmp byte[bx+di], ‘1’
END_LOOP1:
loopz LOOP1 ; . При CX > 0 и любом значении ZF цикл завершается

jz END_IF1
mov ah, 09h
mov dx, err_str
int 21h
jmp EXIT
END_IF1:

; Преобразуем строку в байт AH
movzx si, al ; Вычисляем смещение для последного символа
mov cx, si
dec si
xor ah, ah
LOOP2:
mov dl, [bx+si]
sub dl, ‘0’
or ah, dl
shl ah, 1
dec si
loop LOOP2

; Выводим строку с hex представлением AH
mov al, ah ; AL — 0-3 биты
; AH — 4-7 биты
and al, 00001111b
shr ah, 4

movzx si, ah ; Заносим старший разряд
mov bl, [hex_digit+si]
mov [out_str+2], bl

movzx si, al ; Заносим младший разряд
mov bl, [hex_digit+si]
mov [out_str+3], bl

mov ah, 09h
mov dx, out_str
int 21h
EXIT:
mov ax, 4C00h
int 21h
;—————————————
;—————————————
input_str: ; Процедура ввода с клавиатуры
; AL — максимальный размер строки
; Результат:
; AL — длина введенной строки (не считая CR)
; BX — адрес строки, с CR на конце (0Dh)
push dx
push cx

mov cl, ah
mov ah,0Ah ; Функция DOS 0Ah — ввод строки в буфер
mov [str_buf],al ; Запись максимальной длины в первый байт буфера
mov byte[str_buf+1],0 ; Обнуление второго байта (фактической длины)
mov dx, str_buf ; DX = aдрес буфера
int 21h ; Обращение к функции DOS
mov al,[str_buf+1] ; AL = длина введённой строки
mov bx,dx
add bx,2 ; DX = адрес строки

mov ah, cl
pop cx
pop dx
ret
;—————————————
str_buf rb 256

Сам дурак — сам виноват. При отладке по F8 проскачил данный цикл и не проверил di.

А как быть с двойным словом?

Ввод проще сделать. примерно также как ввод слова.
Только сложение надо делать по частям, в два этапа )))
Опять же, если нужно — я готов написать пример кода.

Если вам не сложно, то напишите. А то столкнулся с проблемой, что не могу вывести строку после ввода, выводятся крокозябры…=(

Автор, спасибо тебе огромное. Спас, (в буквальном смысле), мою задницу от незачета по программированию.

use16
org 100h
jmp start
buffer rb 11
bbyte db 0
erm db 13,10,’Invalid symbol, try again…’,13,10,’$’
prim db ‘Hello, enter your binary byte’,13,10,’$’
start:
mov ah,09h
mov dx,prim
int 21h
cont:
mov dx,buffer
mov ah,0ah
mov byte[buffer],9
int 21h
movzx cx,byte[buffer+1]
mov si,2

loop_bin:
movzx bx,[buffer+si]
inc si
cmp bx,’0′
jz next
cmp bx,’1′
jnz error
stc
next:
rcl [bbyte],1
loop loop_bin

jmp term
error:
mov ah,09h
mov dx,erm
int 21h
jmp cont
term:
mov ax,4c00h
int 21h

sub bl,’0′ ;Преобразование символа-цифры в число

вот этот момент не как не освещен, не понятно что ASCII символа-цифры отнять от строки ‘0’ получится цифра. Или я не правильно понял?

Здравствуйте!
Решил написать универсальную функцию, которая преобразует строку цифр любой длины в целое положительное число указанного размера. Как ею пользоваться: перед вызовом функции необходимо в регистр BP положить адрес строки, в которой находятся цифры, а в регистр BX — адрес числа, в CX необходимо указать размер числа в байтах. Также функция выдаёт код ошибки в регистр DL. Например, если цифр слишком много, а в CX указано мало байтов, то старшая часть числа (старшие байты) отбросятся, и в регистре DL запишется код ошибки равный 2. Если будет 0, то всё нормально.
Как функция работает. Десятичное число делится на 256 по частям, точнее по одной цифре, после деления остаток записывается в первый байт числа. Далее на 256 делится то что осталось от предыдущего деления, а остаток записывается в следующий байт числа. Так происходит до тех пор, пока не заполнятся все байты числа, размер которого указан в регистре CX. Изначально я хотел делить на 16. Но в остатке будет полубайт, младший или старший, а это как-то заморочено. Я решил, что проще делить на 256. Но вот проблема, 256 не помещается в 8-битный регистр. Тогда я подумал, что можно использовать команду сдвига регистра вправо. Число 256 же степень двойки. Можно сдвигать регистр на 8 разрядов. Но это деление без остатка, а мне и результат нужен и остаток. И тут мне пришла гениальная мысль — а зачем собственно делить? Ведь когда мы делим 16-битное число на 256, то результатом является содержимое старшего байта (старшего регистра), а остатком — содержимое младшего байта (младшего регистра). То есть, делить ничего не надо. Фактически я делил без команды деления, используя умножение и сложение. Вот же ж как бывает.
Функция не оптимизирована на скорость, поэтому может выполняться много лишних действий. Не хотел больше голову ломать. С другой стороны код более короткий и более понятный. Проверял всяко, вроде работает нормально, но кто его знает.

;Function convert_string_to_integer
;Вход
;bp — адрес строки. На конце $
;bx — адрес числа
;cx — размер числа в байтах
;Выход
;dl — код ошибки
; 0 — ок
; 1 — строка пустая
; 2 — переполнение, для старших байтов в числе не хватило места
; 3 — указан нулевой размер числа в регистре CX
; 4 — указан нулевой адрес строки в регистре BP
; 5 — указан нулевой адрес числа в регистре BX
; 6 — в строке содержатся недопустимые символы
convert_string_to_integer:
push ax
push bx
push cx
push si
push di

;проверка входных данных
cmp cx,0
jz error_3_func_csti
cmp bp,0
jz error_4_func_csti
cmp bx,0
jz error_5_func_csti

;проверка строки на пустоту
xor si,si
cmp byte[bp+si],’$’
jz error_1_func_csti

;проверка строки на символы
loop_6_func_csti:
cmp byte[bp+si],’$’
jz continue_1_func_csti
cmp byte[bp+si],29h
jna error_6_func_csti
cmp byte[bp+si],39h
ja error_6_func_csti
inc si
cmp si,1000 ;на всякий случай, вдруг отсутствует $
jz error_6_func_csti
jmp loop_6_func_csti

;сохранение строки в стек, и понижение символов на 30h
continue_1_func_csti:
xor si,si
loop_1_func_csti:
mov al,[bp+si]
push ax
sub al,30h
mov [bp+si],al
inc si
cmp byte[bp+si],’$’
jnz loop_1_func_csti

;преобразование строки в число
mov dl,10
loop_3_func_csti:
xor di,di
xor ax,ax
loop_2_func_csti:
mul dl
add al,[bp+di]
adc ah,0
mov [bp+di],ah
inc di
cmp di,si
jnz loop_2_func_csti
mov [bx],al
inc bx
loop loop_3_func_csti

;проверка на переполнение
xor di,di
loop_4_func_csti:
cmp byte[bp+di],0
jnz error_2_func_csti
inc di
cmp di,si
jnz loop_4_func_csti
xor dl,dl

;восстановление строки из стека
loop_5_func_csti:
dec si
pop ax
mov [bp+si],al
cmp si,0
jnz loop_5_func_csti
jmp exit_func_csti

;запись в DL кода ошибки
error_1_func_csti:
mov dl,1
jmp exit_func_csti
error_2_func_csti:
mov dl,2
jmp loop_5_func_csti
error_3_func_csti:
mov dl,3
jmp exit_func_csti
error_4_func_csti:
mov dl,4
jmp exit_func_csti
error_5_func_csti:
mov dl,5
jmp exit_func_csti
error_6_func_csti:
mov dl,6
jmp exit_func_csti

exit_func_csti:
pop di
pop si
pop cx
pop bx
pop ax
ret
;EndFunction


Дополнил функцию возможностью преобразовывать строку цифр в отрицательное число. Строка должна начинаться с символа «-»

;Function convert_string_to_integer
;Вход
;bp — адрес строки. На конце $
;bx — адрес числа
;cx — размер числа в байтах
;Выход
;dl — код ошибки
; 0 — ок
; 1 — строка пустая
; 2 — переполнение, не хватает места для записи числа.
; Результат некорректный
; 3 — указан нулевой размер числа в регистре CX
; 4 — указан нулевой адрес строки в регистре BP
; 5 — указан нулевой адрес числа в регистре BX
; 6 — в строке содержатся недопустимые символы
; 7 — переполнение для отрицательного числа.
; Отброшен один старший байт числа со значением FF.
; В редких случаях FF на конце не обязателен, например,
; положительное 128 равно -128, если число имеет размер 1 байт,
; но ошибка 7 будет установлена
convert_string_to_integer:
push ax
push si
push di
push bp
push bx
push cx

;проверка входных данных
cmp cx,0
jz error_3_func_csti
cmp bp,0
jz error_4_func_csti
cmp bx,0
jz error_5_func_csti

;проверка строки на пустоту и на знак вначале
xor si,si
cmp byte[bp+si],’+’
jz continue_2_func_csti
cmp byte[bp+si],’-‘
jnz continue_3_func_csti
continue_2_func_csti:
inc bp
continue_3_func_csti:
cmp byte[bp+si],’$’
jz error_1_func_csti

;проверка строки на символы
loop_6_func_csti:
cmp byte[bp+si],’$’
jz continue_1_func_csti
cmp byte[bp+si],29h
jna error_6_func_csti
cmp byte[bp+si],39h
ja error_6_func_csti
inc si
cmp si,1000 ;на всякий случай, вдруг отсутствует $
jz error_6_func_csti
jmp loop_6_func_csti

;сохранение строки в стек, и понижение символов на 30h
continue_1_func_csti:
xor si,si
loop_1_func_csti:
mov al,[bp+si]
push ax
sub al,30h
mov [bp+si],al
inc si
cmp byte[bp+si],’$’
jnz loop_1_func_csti

;преобразование строки в число
mov dl,10
loop_3_func_csti:
xor di,di
xor ax,ax
loop_2_func_csti:
mul dl
add al,[bp+di]
adc ah,0
mov [bp+di],ah
inc di
cmp di,si
jnz loop_2_func_csti
mov [bx],al
inc bx
loop loop_3_func_csti

;проверка на переполнение
xor di,di
loop_4_func_csti:
cmp byte[bp+di],0
jnz error_2_func_csti
inc di
cmp di,si
jnz loop_4_func_csti
xor dl,dl

;восстановление строки из стека
loop_5_func_csti:
dec si
pop ax
mov [bp+si],al
cmp si,0
jnz loop_5_func_csti
cmp dl,0
jnz exit_func_csti

;преобразование положительного числа в отрицательное
pop cx
pop bx
pop bp
push bp
push bx
push cx
xor si,si
cmp byte[bp+si],’-‘
jnz exit_func_csti
mov di,cx
dec di
test byte[bx+di],10000000b
jnz error_7_func_csti
loop_7_func_csti:
not byte[bx+si]
inc si
cmp si,di
jna loop_7_func_csti
xor si,si
dec cx
add byte[bx+si],1
loop_8_func_csti:
inc si
adc byte[bx+si],0
loop loop_8_func_csti
jmp exit_func_csti

;запись в DL кода ошибки
error_1_func_csti:
mov dl,1
jmp exit_func_csti
error_2_func_csti:
mov dl,2
jmp loop_5_func_csti
error_3_func_csti:
mov dl,3
jmp exit_func_csti
error_4_func_csti:
mov dl,4
jmp exit_func_csti
error_5_func_csti:
mov dl,5
jmp exit_func_csti
error_6_func_csti:
mov dl,6
jmp exit_func_csti
error_7_func_csti:
mov dl,7
jmp loop_7_func_csti

exit_func_csti:
pop cx
pop bx
pop bp
pop di
pop si
pop ax
ret
;EndFunction

Написал ещё пару функций и программу, которая их использует. Суть программы: ввести строку цифр в консоли со знаком или без, затем строка преобразуется в число, а после число обратно преобразуется в строку и выводится в консоль, где их можно сверить и проверить правильность работы подпрограмм. Размеры строк и числа можно ставить любые, главное чтобы хватило памяти, поэтому в разумных пределах. Функцию для ввода числа в консоли решил написать свою. Она отличается от досовской тем, что можно вводить только цифры и знак «-» вначале, не имеет ограничения на размер (главное чтобы хватило памяти), в конце строки ставится символ «$», завершение происходит при нажатии enter или введено максимум символов. Недостаток моей функции — нельзя удалять введённые символы, в досовской это можно делать, но работает некорректно при переходе на следующую строку, поэтому такую возможность решил не добавлять. Может можно сделать, пока не знаю.

jmp start
;var
stroka_input rb 50 ;размер переменных можно менять
stroka_output rb 100 ;но так же необходимо поменять их
chislo rb 30 ;в основной программе, где есть комментарии
new_line db 13,10,’$’
msg_input db ‘Enter chislo: $’
msg_output db ‘You enter: $’

start:
mov ah,9
mov dx,new_line
int 21h
mov dx,msg_input
int 21h

mov bx,stroka_input
mov cx,50 ;размер переменной stroka_input в байтах
call input_string_of_integer
mov dx,new_line
int 21h
mov bp,stroka_input
mov bx,chislo
mov cx,30 ;размер числа в байтах
call convert_string_to_integer
mov bp,chislo
mov si,30 ;размер числа в байтах
mov bx,stroka_output
mov di,100 ;размер переменной stroka_output в байтах
call convert_integer_to_string

mov dx,msg_output
int 21h
mov dx,stroka_output
int 21h
mov dx,new_line
int 21h

mov ax,4c00h
int 21h

;Function input_string_of_integer
;Вход
;bx — адрес строки
;cx — длина строки в байтах вместе с $
;Выход
;dl — код ошибки
; 0 — ok
; 1 — нулевой адрес строки
; 2 — длина строки меньше трёх символов
input_string_of_integer:
push ax
push bx
push cx

;проверка входных данных
cmp bx,0
jz error_1_func_isoi
cmp cx,3
jc error_2_func_isoi

;ввод хотя бы одной цифры или минуса
loop_3_func_isoi:
mov ah,8
int 21h
cmp al,’-‘
jz continue_1_func_isoi
cmp al,30h
jc loop_3_func_isoi
cmp al,39h
ja loop_3_func_isoi
jmp continue_2_func_isoi

;отображение и запись минуса
continue_1_func_isoi:
mov ah,2
mov dl,al
int 21h
mov [bx],al
inc bx
dec cx

;если «-«, то ввод хотя бы одной цифры
loop_2_func_isoi:
mov ah,8
int 21h
cmp al,30h
jc loop_2_func_isoi
cmp al,39h
ja loop_2_func_isoi
jmp continue_2_func_isoi

;ввод цифр, отображение и запись в строку
loop_1_func_isoi:
mov ah,8
int 21h
cmp al,13
jz noerror_func_isoi
cmp al,30h
jc loop_1_func_isoi
cmp al,39h
ja loop_1_func_isoi
continue_2_func_isoi:
mov ah,2
mov dl,al
int 21h
mov [bx],al
inc bx
loop loop_1_func_isoi

;запись в dl кода ошибки
noerror_func_isoi:
mov byte[bx],’$’
mov dl,0
jmp exit_func_isoi

error_1_func_isoi:
mov dl,1
jmp exit_func_isoi

error_2_func_isoi:
mov dl,2

exit_func_isoi:
pop cx
pop bx
pop ax
ret
;EndFunction

;Function convert_string_to_integer
;Вход
;bp — адрес строки. На конце $
;bx — адрес числа
;cx — размер числа в байтах
;Выход
;dl — код ошибки
; 0 — ок
; 1 — строка пустая
; 2 — переполнение, не хватает места для записи числа.
; Результат некорректный
; 3 — указан нулевой размер числа в регистре CX
; 4 — указан нулевой адрес строки в регистре BP
; 5 — указан нулевой адрес числа в регистре BX
; 6 — в строке содержатся недопустимые символы
; 7 — переполнение для отрицательного числа.
; Отброшен один старший байт числа со значением FF.
; В редких случаях FF на конце не обязателен, например,
; положительное 128 равно -128, если число имеет размер 1 байт,
; но ошибка 7 будет установлена
convert_string_to_integer:
push ax
push si
push di
push bp
push bx
push cx

;проверка входных данных
cmp cx,0
jz error_3_func_csti
cmp bp,0
jz error_4_func_csti
cmp bx,0
jz error_5_func_csti

;проверка строки на пустоту и на знак вначале
xor si,si
cmp byte[bp+si],’+’
jz continue_2_func_csti
cmp byte[bp+si],’-‘
jnz continue_3_func_csti
continue_2_func_csti:
inc bp
continue_3_func_csti:
cmp byte[bp+si],’$’
jz error_1_func_csti

;проверка строки на символы
loop_6_func_csti:
cmp byte[bp+si],’$’
jz continue_1_func_csti
cmp byte[bp+si],29h
jna error_6_func_csti
cmp byte[bp+si],39h
ja error_6_func_csti
inc si
cmp si,1000 ;на всякий случай, вдруг отсутствует $
jz error_6_func_csti
jmp loop_6_func_csti

;сохранение строки в стек, и понижение символов на 30h
continue_1_func_csti:
xor si,si
loop_1_func_csti:
mov al,[bp+si]
push ax
sub al,30h
mov [bp+si],al
inc si
cmp byte[bp+si],’$’
jnz loop_1_func_csti

;преобразование строки в число
mov dl,10
loop_3_func_csti:
xor di,di
xor ax,ax
loop_2_func_csti:
mul dl
add al,[bp+di]
adc ah,0
mov [bp+di],ah
inc di
cmp di,si
jnz loop_2_func_csti
mov [bx],al
inc bx
loop loop_3_func_csti

;проверка на переполнение
xor di,di
loop_4_func_csti:
cmp byte[bp+di],0
jnz error_2_func_csti
inc di
cmp di,si
jnz loop_4_func_csti
xor dl,dl

;восстановление строки из стека
loop_5_func_csti:
dec si
pop ax
mov [bp+si],al
cmp si,0
jnz loop_5_func_csti
cmp dl,0
jnz exit_func_csti

;преобразование положительного числа в отрицательное
pop cx
pop bx
pop bp
push bp
push bx
push cx
xor si,si
cmp byte[bp+si],’-‘
jnz exit_func_csti
mov di,cx
dec di
test byte[bx+di],10000000b
jnz error_7_func_csti
loop_7_func_csti:
not byte[bx+si]
inc si
cmp si,di
jna loop_7_func_csti
xor si,si
dec cx
add byte[bx+si],1
loop_8_func_csti:
inc si
adc byte[bx+si],0
loop loop_8_func_csti
jmp exit_func_csti

;запись в DL кода ошибки
error_1_func_csti:
mov dl,1
jmp exit_func_csti
error_2_func_csti:
mov dl,2
jmp loop_5_func_csti
error_3_func_csti:
mov dl,3
jmp exit_func_csti
error_4_func_csti:
mov dl,4
jmp exit_func_csti
error_5_func_csti:
mov dl,5
jmp exit_func_csti
error_6_func_csti:
mov dl,6
jmp exit_func_csti
error_7_func_csti:
mov dl,7
jmp loop_7_func_csti

exit_func_csti:
pop cx
pop bx
pop bp
pop di
pop si
pop ax
ret
;EndFunction

;Function convert_integer_to_string
;Вход
;bp — адрес числа
;si — размер числа в байтах
;bx — адрес строки
;di — размер строки, включая $
;Выход
;dx — код ошибки
; ffff — нулевой адрес числа в bp
; fffe — нулевой размер числа в si
; fffd — нулевой адрес строки в bx
; fffc — указан размер строки в di меньше 3 символов
; 0 и более — количество цифр, которые
; не поместились в конце строки.
; 0 означает, что все цифры поместились.
convert_integer_to_string:

push ax
push bx
push cx
push si
push di

;проверка входных данных
cmp bp,0
jz error_ffff_func_cits
cmp si,0
jz error_fffe_func_cits
cmp bx,0
jz error_fffd_func_cits
cmp di,3
jc error_fffc_func_cits

;сохраняем число в стек
dec si
xor ax,ax
xor cx,cx
loop_1_func_cits:
mov al,[bp+si]
push ax
inc cx
dec si
jns loop_1_func_cits
push cx

;проверка знака числа
;отрицательное число преобразуется в положительное
mov si,cx
dec si
test byte[bp+si],10000000b
jz continue_1_func_cits
mov byte[bx],’-‘
inc bx
dec di
loop_2_func_cits:
not byte[bp+si]
dec si
jns loop_2_func_cits
dec cx
xor si,si
add byte[bp+si],1
loop_3_func_cits:
inc si
adc byte[bp+si],0
loop loop_3_func_cits

;преобразование числа в строку
;запись цифр в стек
continue_1_func_cits:
inc si
mov dl,10
xor cx,cx

loop_4_func_cits:
dec si
js continue_2_func_cits
cmp byte[bp+si],0
jz loop_4_func_cits
push si
xor ax,ax
loop_5_func_cits:
mov al,[bp+si]
div dl
mov [bp+si],al
dec si
jns loop_5_func_cits
pop si
inc si
push ax
inc cx
jmp loop_4_func_cits
continue_2_func_cits:
dec di
xor si,si
cmp cx,0
jnz loop_6_func_cits
mov byte[bx],’0′
inc bx
mov byte[bx],’$’
xor dx,dx
jmp continue_4_func_cits

;запись цифр из стека в строку
loop_6_func_cits:
pop ax
add ah,30h
mov byte[bx+si],ah
inc si
dec di
jz error_lack_func_cits
loop loop_6_func_cits
xor dx,dx
continue_3_func_cits:
mov byte[bx+si],’$’

;восстановление числа из стека
continue_4_func_cits:
pop cx
xor si,si
loop_7_func_cits:
pop ax
mov byte[bp+si],al
inc si
loop loop_7_func_cits
jmp exit_func_cits

;запись кода ошибки в dx
error_ffff_func_cits:
mov dx,0ffffh
jmp exit_func_cits
error_fffe_func_cits:
mov dx,0fffeh
jmp exit_func_cits
error_fffd_func_cits:
mov dx,0fffdh
jmp exit_func_cits
error_fffc_func_cits:
mov dx,0fffch
jmp exit_func_cits
;недостаточно места для записи последних цифр.
;в dx указывается сколько цифр отброшено
error_lack_func_cits:
dec cx
mov dx,cx
loop_8_func_cits:
pop ax
loop loop_8_func_cits
jmp continue_3_func_cits

exit_func_cits:
pop di
pop si
pop cx
pop bx
pop ax
ret
;EndFunction

Консоль ввода-вывода

Макс Петров май 2013

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

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

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

Для создания консоли приложение вызывает API-функцию Windows AllocConsole:
Function AllocConsole Lib «kernel32» Alias DWORD «AllocConsole» ().
Из описания этой функции видно, что она содержится в библиотеке Windows kernel32, поэтому в секцию директив нашей ассемблерной программы мы должны включить соответствующие файлы прототипов (kernel32.inc) и библиотек (kernel32.lib). По выполнении функция AllocConsole записывает (возвращает) в регистр EAX значение длиной 4 байта (DWORD). Если консоль создать не удалось, в регистр EAX будет записан ноль.

Хэндл созданной консоли приложение получает при помощи API-функции GetStdHandle:
Function GetStdHandle Lib «kernel32» Alias DWORD «GetStdHandle» (DWORD nStdHandle).
В отличие от предыдущей функции, которая не принимала (пустые скобки) от приложения никаких параметров, функции GetStdHandle должно быть передано 4-байтное значение одной из набора констант nStdHandle. После выполнения функции в регистр EAX будет помещено 4-байтное значение хэндла консоли.

Хэндлы для ввода в консоль и вывода через нее не равны, если мы планируем организовать в нашей программе и ввод, и вывод символьной информации через консоль, функцию GetStdHandle нужно вызывать дважды, передавая ей соответствующие значения констант nStdHandle:
STD_INPUT_HANDLE (ввод);
STD_OUTPUT_HANDLE (вывод).
Записи STD_INPUT_HANDLE и STD_OUTPUT_HANDLE обозначают в стандарте обозначений Microsoft всего лишь числа (константы). Замена числовых значений констант принятыми для них символьными именами хороша уже тем, что улучшает читаемость программ, избавляя от необходимости каждый раз вспоминать, что может означать то или иное число. Значения констант STD_INPUT_HANDLE и STD_OUTPUT_HANDLE содержатся в файле windows.inc (входит в комплект поставки MASM32), на который мы укажем в секции директив нашей программы.

Ввод и вывод через консоль осуществляется посредством двух API-функций Windows, которые определяются следующим образом. Для ввода:
Function ReadConsole Lib «kernel32» Alias DWORD «ReadConsoleA» (DWORD hConsoleInput, DWORD lpBuffer, DWORD nNumberOfCharsToRead, DWORD lpNumberOfCharsRead, DWORD lpReserved);
для вывода:
Function WriteConsole Lib «kernel32» Alias DWORD «WriteConsoleA» (DWORD hConsoleOutput, DWORD lpBuffer, DWORD nNumberOfCharsToWrite, DWORD lpNumberOfCharsWritten, DWORD lpReserved).

Функциям должны быть переданы параметры:
hConsoleInput (hConsoleOutput) — хэндл для ввода (вывода);
lpBuffer — адрес памяти, с которого начинается буфер ввода или вывода;
nNumberOfCharsToRead (nNumberOfCharsToWrite) — устанавливаемое приложением число вводимых (выводимых) символов;
lpNumberOfCharsRead (lpNumberOfCharsWritten) — адрес ячейки памяти, куда функция запишет число фактически введенных (выведенных) символов;
lpReserved — адрес ячейки памяти для зарезервированного параметра.

Об API-функции CharToOem, которая понадобится, если в консоли мы намерены выводить кириллические символы, будет рассказано в следующей статье.

Ну все, пишем программу:

В программе присутствуют незнакомые читателю записи. Первая из них

mov (приемник), (источник)

являет собой команду процессора — пересылку. Мнемоника команды происходит от английского слова moving, что означает перемещение. В нашем случае при помощи этой команды мы дважды предписывали процессору скопировать содержимое регистра EAX , в который функция GetStdHandle записывала хэндл консоли, в соответствующую переменную.

ADDR (имя переменной)

подменяется в исполняемом коде адресом переменной в памяти, то есть является указателем на эту переменную.

SIZEOF (имя символьной строки)

подменяется в исполняемом коде длиной (в байтах) символьной строки.

В конце программы ввод через консоль одного символа нужен только для того, чтобы мы смогли на программу (и на консоль) посмотреть. Ввод в консоль осуществляется с клавиатуры, завершает ввод всегда клавиша Enter. Таким образом, пока мы ничего не ввели консоль будет ожидать ввода, после нажатия Enter программа закроется, поскольку ее исполняемый код будет исчерпан.

Завершает программу вызов API-функции ExitProcess, которая говорит операционной системе, что процесс следует закрыть.

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL