Win32ASM Hello World и три халявы MASM32



d8ef8794

Задача 2 - часть 2


  Единственный параметр, который она от нас требует - указание, на какое устройство мы желаем получить "квиток"-хендл. Вот табличка:

Хэндл стандартного ввода -10
Хэндл стандартного вывода -11
Хэндл "ошибок" -12

  Что нам нужно? Вывести строчку! Значит - запрашиваем хэндл для стандартного вывода, то есть перед вызовом функции "суем" в стек -11. После выполнения функции регистр EAX содержит столь желанный "хэндл стандартного вывода". Кладем этот хэндл в переменную hStdout (которую мы столь предусмотрительно определили на бряке 1) для последующего использования.

  - Это ж что за безобразие? - воскликните вы. - Что это за таблица такая нездоровая? Какие-то отрицательные числа, которые ни в жисть не запомнить! Хотим таблицу как в MSDN'е! Чтобы не -10, -11, -12, а длинные мнемонические STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE!
  Спокойно! Исходник, который мы сейчас рассматриваем, весьма точно отображает реальные процессы, происходящие в программе. Чуть позже мы приведем его к варианту в стиле Cи и посмотрим, как можно использовать некоторые высокоуровневые конструкции, значительно облегчающие жизнь низкоуровневому программисту.

  Бряк 4. Ну наконец-то, самое главное - функция, которая, собственно, и выводит на консоль строку символов. Вот ее описание: BOOL WriteConsole( HANDLE hConsoleOutput, // handle to screen buffer CONST VOID *lpBuffer, // write buffer DWORD nNumberOfCharsToWrite, // number of characters to write LPDWORD lpNumberOfCharsWritten, // number of characters written LPVOID lpReserved // reserved );

  Расшифровываем. Перед вызовом функции WriteConsole мы должны поместить в стек целых пять параметров:

  1. Хэндл. Какие проблемы? Мы его уже получили и предусмотрительно сохранили в переменной hStdout. Командой push hStdout заносим его в стек, и все дела.
  2. Указатель на строку символов, которую мы хотим напечатать. Сама строка у нас определена в секции констант под именем sWriteText. Получить ее адрес мы можем при помощи offset. Укладываем все в одну строчку - push offset sWriteText. Два в одном - и адрес получаем и в стек его заталкиваем :).
  3. Число символов, которые мы хотим напечатать. В смысле - число "буковок" из строки sWriteText. Сколько символов в строке "hEILo, Wo(R)LD!!"? Включая пробелы - 16d. Пишем - push 16d. Заметьте, функция WriteConsole не требует нуля в конце буфера!
  4. Указатель на переменную, в которой будет возвращено число напечатанных символов. Функция нам любезно сообщает, сколько символов из шестнадцати ей удалось напечатать. И требует переменную, в которую эту информацию ей занести. Давайте сделаем вид, что она нам не нужна, то есть напишем 0. Ничего страшного не случится, а в ошибочности подобного рода игнорирований убедимся в следующей главе. Пишем - push 0, но для себя оставляем пометку, что что-то функция от нас все же хотела.
  5. Резерв. Так сказать, зарезервировано для следующих версий. Смело пишем - push 0.




Содержание  Назад  Вперед