Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2014- СП 3.0 ЛАБЫ ОБЯЗАТ.doc
Скачиваний:
99
Добавлен:
01.03.2016
Размер:
896 Кб
Скачать
      1. Вывод и ввод в консольных приложениях

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

При консольном выводе прямо или косвенно используется функция WinAPI WriteFile. Вот её формальная спецификация из MSDN:

BOOL WriteFile(

HANDLE hFile, // манипулятор файла

LPCVOID lpBuffer, // указатель на буфер данных

DWORD nNumberOfBytesToWrite, // число байтов для записи

LPDWORD lpNumberOfBytesWritten, //указатель на ячейку для хранения числа

// фактически записанных байтов

LPOVERLAPPED lpOverlapped // указатель на асинхронный буфер,

// обычно это NULL

);

описание которой находится по адресу http://msdn.microsoft.com/en-us/library/ms892380.aspx.

Пример применения этой процедуры для вывода.

.data ; сегмент данных

ZapisanoByte dd 0 ; сколько байт фактически выведено ФРАГМЕНТ 1

AnyString db "Строка для вывода.”,0

DlinaStroki dd 18

PotokStdOut dd ? ; Для записи манипулятора Стд Потока Вывода

.code ; сегмент кода

;Запросить у Windows манипулятор выводного потока ФРАГМЕНТ 2

Invoke GetStdHandle,std_output_handle ; манипулятор возвращен в еах, ...

mov PotokStdOut, eax ; ... и переписан в переменную PotokStdOut

invoke WriteFile, PotokStdOut, ADDR AnyString, DlinaStroki, ADDR ZapisanoByte, NULL

В этом примитивном примере длина строки просто задана значением переменной DlinaStroki. Лучшим решением является ее программное определение. Если строка заканчивается нуль-байтом (строка типа «string-zero»,sz), то схема действий (на псевдокоде) может быть такая:

Установить указатель (например, ЕВХ) на начало строки.

Начальное значение счетчика_символов задать равным 0.

Метка1:

Байт [EBX] равен нуль-байту?

Если да, перейти на метку2. Алгоритм 1.

Увеличить счетчик_символов на 1.

Указатель EBX перенести на следующий символ строки.

Перейти на метку1.

Метка2:

На выходе из этого цикла счетчик_символов содержит длину строки.

При консольном вводе прямо или косвенно используется WinAPI-шная функция ReadFile

BOOL WINAPI ReadFile(

__in HANDLE hFile, // манипуляторвводногопотока

__out LPVOID lpBuffer, // указатель на буфер ввода

__in DWORD nNumberOfBytesToRead, // максимальное количество читаемых байтов

__out_opt LPDWORD lpNumberOfBytesRead, // указатель на переменную,

// куда будет записано количество фактически прочитанных байтов

__inout_opt LPOVERLAPPED lpOverlapped // для ввода с консоли NULL

);

описание которой находится по адресу http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx/

Эта функция вводит символы в буфер ввода. Ввод оканчивается нажатием Enter, которое в буфере ввода добавляет в конец введенной строки символыCRиLF(0D0A). Именно поэтому параметр nNumberOfBytesToRead не должен превышать (длину_вводного_буфера – 2), иначе введенная строка с завершающими символами может выйти за пределы буфера.

Заметьте, что получившаяся строка НЕ является sz-строкой. Для превращения ее в таковую (если требуется) символLF(0D) надо обнулить.

Пример применения этой процедуры для ввода.

.data ; сегмент данных