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



Вопросы
  Компонент HotKey
   Категория: Компоненты
  Округление времени до 5 мин
   Категория: Базы данных
  Сохранить документ Word как RTF на DELPHI
   Категория: Файловая система
  Номер строки в memo под курсором
   Категория: Текст и строки
  Создать *.mdb-файл и таблицу в ней
   Категория: Базы данных
  Группировка TopAdvGrid
   Категория: Компоненты
  Узнать установлена ли BDE
   Категория: Базы данных
  Упаковать TinyDB
   Категория: Базы данных
  Вычислить логарифм
   Категория: Математика
  Что такое хук (hook)?
   Категория: Приложение

Assembler and Win32

  << Назад к Содержанию  

Assembler&Win32. Курс молодого бойца. Урок 4.

Первая программа

    На этом уроке мы с вами напишем первую программу на ассемблере. Но сначала я вам объясню структуру программы на ассемблере. Самая первая программа будет написана на TASM, потому что язык TASM классический, стандартный, без наворотов, а о MASM (макроассемблер) я вам буду говорить на следующих уроках.

     Общая структура программы.

         .386p ;тип процессора
         .model flat, stdcall ; модель памяти и вызова подпрограмм
;объявление включаемых (заголовочных) файлов, макросов, макроопределений,
; также внешних определений
         .data
; Инициализированные данные
         .data?
; неинициализированные данные
         .const
; константы
         .code
; исполняемый код
         End <метка точки входа>


    Процессоры могут быть 386, 486, 586, обычно всегда стоит 386p, но ничто вам не мешает поставить 486p или 586. Модель памяти всегда flat и никакой другой не может быть. Вызов подпрограмм обычно всегда stdcall, стандарт вызова почти всех API функций. Секция .data секция с инициализированными данными она включается в исполняемый файл. Секция .data? секция с неинициализированными данными, она не включается в исполняемый файл и появляется только тогда, когда программа загружается в память. Секция .const секция констант. Секция .code содержит исполняемый код программы. В конце программы всегда должно стоять слово end, которая задаёт точку входа программы, т.е. место с которого начнётся выполняться программа. Секции .data, .data? имеют полный доступ. Разумеется, секции .const и .code имеют атрибут доступа - только чтение. Секция .const наиболее редко встречается в программах, так как константы можно задавать с помощью макроопределений.
     При программировании под Win32 мы не имеем доступ к портам ввода вывода и не можем вызывать прерывания (самые главные команды в DOS), у нас есть только WIN API, которые экспортируют системные библиотеки. Вызывая API функцию, вы просто передаёте управление точке входа функции (точка входа функции это первая инструкция функции), сама функция находится где-то в памяти вашего процесса внутри некоторой библиотеки. API функции находятся в библиотеках kernel32.dll, user32.dll, gdi32.dll (классика) advapi32.dll и т.д., для того чтобы использовать некоторую функцию этих библиотек надо сначала загрузить нужную библиотеку в свою память, либо включить используемые функции в таблицу импорта и тогда загрузчик загрузит библиотеки за вас. О kernel32.dll можно не волноваться, потому что эта библиотека есть в каждом процессе в любом случае, тем более она там существует ещё до запуска главной нити процесса, она даже проецируется в вашу память всегда по одинаковым адресам. Как я уже говорил все функции, используют модель вызова stdcall, а значит, параметры подпрограмме передаются "задом-на-перёд" и вызываемый очищает стек. Общий вид вызова API функции будет такой:

     Push параметр 3
     Push параметр 2
     Push параметр 1
     Call функция ; если быть точнее то здесь должен стоятб ажрес функции
         ; т.е. адрес её точки входа

     Каждая программа в Win32 в конце своего выполнения ОБЯЗАТЕЛЬНО должна вызвать функцию ExitProcess. Сами подумайте, после выполнения последней инструкции программы, дальше идёт пустота, даже если там что-то осмысленное, все равно у выделенной памяти есть конец, а после конца идёт невыделенная (т.е. несуществующая) память. Процессор начнёт выполнять непоймёшь чё, пойдут глюки, и ваша программа даст в конце хорошо всем знакомый звук - "ДУНГ". А это уже бессмыслица. Вот определение ExitProcess из MS SDK:

VOID ExitProcess(
     UINT uExitCode // exit code for all threads
     );
uExitCode - это значение никогда не используется и всегда равно 0.

     Первая программа.
     Теперь я приведу вам программу, которая выводит легендарное сообщение "Hello, World!".

.386
.model flat

extrn ExitProcess:PROC
extrn MessageBoxA:PROC

.data

Ttl db "First ASSEMBLER program",0h
Msg db 'Hello, World!!!!',0h

.code

start:
     push 0h
         push offset Msg
         push offset Ttl
         push 0h
         call MessageBoxA
         push 0h
         call ExitProcess
end    start


    Мы вызываем функцию MessageBoxA, для вывода окна сообщения потом выходим из процесса. Теперь поподробнее.

    Определение функции MessageBox из MS SDK в оригинале:
int MessageBox(
     HWND hWnd, // handle of owner window
     LPCTSTR lpText, // address of text in message box
     LPCTSTR lpCaption, // address of title of message box
     UINT uType // style of message box
     );

    Мы указали только модель памяти и модель вызов подпрограмм не указали, так как это просто не к чему. В качестве первого параметра мы передаём ноль, поэтому у окна сообщения не будет родительского окна. В качестве параметров lpText и lpCaption мы передаём адреса соответствующих строк, заметьте, что мы передаём адрес строки (т.е. её первого символа) у которой в конце стоит символ #0, это нужно, для того чтобы функция смогла найти конец строки. Последний параметр определяет стиль окна сообщения, в данном случае мы передали 0, что обозначает, что там будет только одна кнопка OK, иначе этот стиль обозначается MB_OK. Функцию ExitProcess вы уже знаете. После директивы end мы указали метку, с которой начнётся выполнение ваша программа.

     Зачем нужна буква A в конце функции?
     В Win32 есть 2 типа функции заканчивающиеся на A и на W. Всё отличие в строках, которые принимают функции. А-функции принимают ANSI строки. W-функции принимают Unicode строки. У каждой функции, которая принимает строки, есть обе версии. Обычно все пользуются ANSI версиями функций. Но в любом случае при вызове ANSI функции все строки сначала преобразуются в Unicode строки, и будет вызвана Unicode функция.

    Компиляция.
     Чуть-чуть не забыл рассказать, как надо компилировать программы. Для этого вам надо написать текст программы на ассемблере и сохранить в файл с расширением *.asm. Потом надо ассемблировать его. Для этого вам понадобится программа tasm32.exe она нахидтся в папке %tasmdir%\bin asm32.exe, формат её вызова такой: TASM [options] source [,object] [,listing] [,xref] (доп сведения смотрите в tasm32 /?) для большинства программ ассемблирование проходит так:
     %tasmdir%\BIN asm32 /m3 /ml asmfile,,;
     Где asmfile - имя вашего файла БЕЗ расширения. Потом будет создан объектный файл, файл листинга и т.д. Теперь вам надо всё это слинковать. Для Линковки вам понадобится программа tlink32.exe. Вот формат её вызова:
TLINK objfiles, exefile, mapfile, libfiles, deffile, resfiles
    Для всех программ в этом туториале линковка будет такой:
%tasmdir%\BIN link32 /Tpe /aa asmfile,asmfile,,%tasmdir% \Lib\import32.lib
    Где asmfile - имя вашего файла БЕЗ расширения.
    Статическая библиотека %tasmdir% \Lib\import32.lib содержит в себе все функции библиотек kernel32.dll, user32.dll, gdi32.dll и может быть других стандартных библиотек. Желательно чтобы asmfile находился в папке %tasmdir%.
     Для бысрой компиляции я вам советую создать *.bat файл, который всё это делает за вас. Вот текст моего файла.
Compile.bat
cls
echo off
d: asm_5\BIN asm32 /m3 /ml %1,,;
d: asm_5\BIN link32 /Tpe /aa %1,%1,,d:\TASM_5\Lib\import32.lib
echo "Succesful"
Теперь после вызова
     Compile sample
У вас готовый к выполнению экзешник.
     Подошёл к концу четвёртый урок. На этом уроке мы написали первую программу на ассемблере. Но я вам почти не объяснил, как надо пользоваться меткам и данными. Именно, для этого и предназначены 2 следующий урока

Источник: http://www.programmersclub.ru

  << Назад к Содержанию