Код магнитолы

JS - телефон

Оппозиция в России ?

Россия и Украина

Мысли в слух...

JS - часы

Российская...власть ?

Skype

Создаём сайт

Любимые сериалы

Гостевая


На главную

Здравствуй...Fenix

Вы - угадали, мы попробуем создать, при помощи ассемблера, всё тот-же арифмометр. К сожалению (поверте на слово - искреннему) мы проскочим мимо создания com-файлов - приложение будет для Windows, а значит - 32-х разрядное. И пользоватся мы будем макроассемблером masm32, благо, он у нас уже подключен. Все Win-программы выполняются в защищённом режиме, который доступен с i80286. Т.е. - всё, о чём пойдёт разговор, распространяется на i80386 и его потомков. Каждая Win32 пpогpамма имеет 4-х гигабайтовое адpесное пpостpанство. Здесь нет сегментов по 64 Kb. И модель памяти только одна - плоская "flat". Хорошо, что можно использовать любой (esi, edi, ebp и ebx - эти регистры необходимо восстанавливать перед возвращением управления Windows, поскольку она их неявно использует) сегментный pегистp для адpесации к любой точке памяти. Плохо, что программы не видят друг-друга.
Принцип создания программы мало чем отличается от иноязычных, просто - этаж ниже. Используем либо типовые компоненты, либо - создаём свои. Распределяем их по местам и объясняем окружению процессора, при помощи различных команд, где они находятся и что с ними делать. Всё как учили: адреса, явки, пароли...
Адресов, правда, не очень много:


рис.7

На рис.7 представлены практически все (кроме ip регистров и регистров флагов) регистры процессоров 8086-80186. Это области памяти, предназначеные для временного хранения каких-либо данных.
Поскольку мы будем создавать программу для среды Windows, мы будем использовать все вышеприведённые регистры по полной программе. Причём - с различными типами адресации.
В нашем случае, всю память можно рассматривать как один сегмент. Для программирования на языке ассемблера это означает, что адрес любой ячейки памяти будет определяться содержимым одного 32-битного регистра, например EBX и, мы фактически не ограничены в объеме данных, кода или стека (объеме локальных переменных).

Что из себя представляет будущий арифмометр? Это окно определённых размеров, в верхней (меньшей) части которого находится дисплей, в нижней - 16 кнопок, отражающих основные арифметические символы и действия.
В начале создадим само окно:



Для этого мы воспользуемся АPI-функциями. Как видно из кода, окно создаётся в режиме упрощённой сегментации. Что можно заметить глядя на этот код? Для создания окна необходимо:
1) получить дескриптор создаваемой пpогpаммы
2) получить командную стpоку (не нужно до тех поp, пока пpогpамме не потpебуется ее пpоанализиpовать)
3) заpегистpиpовать класс окна (необходимо, если вы не используете один из пpедопpеделенных класов окна, таких как MessageBox или диалоговое окно)
3) создать окно
4) отобpазить окно на экpане
5) обновить содеpжимое экpана на окне
6) запустить бесконечный цикл, в котоpом будут пpовеpятся сообщения от опеpационной системы, поступающие сообщения пеpедаются специальной функции, отвечающей за обpаботку окна
7) выйти из пpогpаммы, если пользователь закpывает окно
Полученый вариант окна - не окончательный (не каламбур), в него многое придётся добавить. Этот вариант можно рассматривать как каркас будущего арифмометра. Используемые в программе имена процедур (WinMain и WndProc) - условны, а вместо процедур можно-было использовать метки (например - М1: и М2:), которые не требуют завершения. К слову сказать, имя процедуры - это метка, обозначающая первую команду процедуры. Главное, что необходимо помнить - код процедуры не должен работать по ходу программы (сам по себе), он должен работать только после обращения к процедуре. Поэтому, процедуры лучше располагать в конце кода (после вызова функции ExitProcess или перед end go). Процедура, в рамках своего участка стека, может обращаться без ограничений к любой ячейки памяти.
И ещё один момент: любая программа под Windows должна, как минимум, корректно завершится. Для этого необходимо вызвать функцию Win32 API ExitProcess. Выглядит это так:
...
push 0
call ExitProcess
end go
Однако, вполне допустимо, просто воспользоватся командой возврата из процедуры (ret).
Упоминаемые в коде rsrc.rc-файлы - это тема отдельного разговора. Они создаются в процессе ассемблирования, параллельно с asm-файлом (курсив).
Полученый asm-файл, при помощи bat-файла, превращаем в exe-файл:
 @echo off
 Rc /v rsrc.rc
 Cvtres /machine:ix86 rsrc.res
 ml /c /coff /Fl fenix_01.asm   
 link /subsystem:windows /opt:noref fenix_01.obj rsrc.res 
 del fenix_01.obj
 ::fenix_01.exe
 ::afdpro fenix_01.exe  
 pause 
 
В программе (рис.7) часто используется стэк - это такое место в памяти, которое ассемблер использует для хранения временных данных. Отличительными показателями работы со стэком являются операторы push(положить в стэк) и pop (извлечь из стэка). Представте себе трубу (лучше - прозрачную), внутренний диаметр которой чуть больше диаметра...билиардного шара. Шары, а на каждом есть номер, можно запихивать в трубу только по одному, как и вытаскивать и, только последовательно - в обратном порядке. Не забывайте - ассемблер самостоятельно использует стэк...для личных нужд.
***
Работа со стеком - это один из вариантов использования регистров:
  ...
  mov  eax,что-то
  push eax           ;теперь это "что-то" находится по адресу [(E)SP]
  ...
  
поскольку регистр (E)SP фиксирует "положение" вершины стека.
***
Ну - вот, окно у нас есть! Теперь начнётся самое интересное!

дальше...
...назад