Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Ассемблер? Это просто! Учимся программировать


Информационный Канал Subscribe.Ru


Дизайн рассылки разработан для Microsoft Internet Explorer 5.0+
при разрешении экрана 800х600+ точек

Ассемблер? Это просто!
Учимся программировать
Выходит с июня 2000 года

Выпуск № 35
05 июня 2002 года
Выпуск подготовил: Вал.Ик.


 Сегодня в номере:

Информация для новых подписчиков

Уважаемые читатели!

Архив выпусков настоящей рассылки можно скачать по адресу http://asm.kalashnikoff.ru/dos.

Ваши вопросы можно задавать экспертам. Специальную форма находится по адресу http://kalashnikoff.ru/cgi-bin/Message.cgi.

Подписаться на рассылку "Ассемблер? Это просто! Учимся программировать (FAQ)" можно на головной странице сайта http://kalashnikoff.ru. В данной рассылке публикуются часто задаваемые вопросы по программированию на Ассемблере.

ВНИМАНИЕ: В связи с переездом сайта на новый домен указанные ссылки могут временно не работать. О всех проблемах просьба немедленно сообщать Администратору.


Вал.Ик. представляет...

Сегодня в выпуске:
  • Игра для идиотов
  • MessageBox: Прошло две недели!
  • MessageBox: Прошло два месяца!!!

Ну, снова всем привет!

 

Игра для идиотов (это я про себя)…

 

         Загружаемся в чистом DOSe и набираем команду TIME. Высветится текущее время и запрос на ввод нового времени. Медленно набираем : 0.00.00. А потом начинается самое главное – как можно быстрее нажимаем ввод, опять TIME и снова ввод. На экране высвечивается текущее время, допустим – 0.00.00,67. Таким образом «скорострельность» наших пальчиков будет 0,67 секунды. Именно за это время они нажали шесть клавиш – ввод,T,I,M,E,ввод! Вот этим я занимаюсь уже третий час. Вопрос, который меня мучит все это время – есть ли критическое время (ну типа скорости отработки самого железа) меньше которого нельзя опуститься? Надо будет как-нибудь на досуге высчитать... А может кто-нибудь знает? У меня пока рекорд – 0,54... 

        А какое это имеет отношение к программингу под Win? А хрен его знает... Никакого. Вдохновения нет. Вообще-то я рассылку сел писать. А тут вот такое дело с timом... Пойду, пожалуй, спать. Завтра напишу.

Да! Забыл! Время-то после этой фигни восстановить не забудьте!

 

 

Прошло две недели!

 

            Ну, хорошо. Ну, ладно. Ну, обещал я вам про оптимизацию и SoftIce чего-нибудь рассказать. Ну, НЕ ДО ЭТОГО МНЕ СЕЙЧАС!!! Я программу ПИШУ! Издеваюсь над нашим Биллом и МессаджБоксом. Давайте-ка быстренько набивайте где-нибудь эти извращения и полюбуйтесь что эта Виндовус вытворяет со всеми своими переменными. Конкретно речь пойдет о тех самых переменных, которые в нашем МессаджБоксе определяют иконки, кнопки и прочую красивую ерунду, которую какой-то безвестный программист Microsofta не поленился нарисовать.

           

.386
.model flat
extrn                       MessageBoxA:proc
extrn                       ExitProcess:proc
.data
mb_text       db  'MB_OK = 0000',0Dh,0Dh,'IDOK = 0001',0
                     db  'MB_OKCANCEL = 0001',0Dh,0Dh,'IDOK = 0001',0Dh,'IDCANCEL = 0002',0
                     db  'MB_ABORTRETRYIGNORE = 0002',0Dh,0Dh,'IDABORT = 0003',0Dh,'IDRETRY = 0004',0Dh,'IDIGNORY = 0005',0
                     db  'MB_YESNOCANCEL = 0003',0Dh,0Dh,'IDYES = 0006',0Dh,'IDNO = 0007',0Dh,'IDCANCEL = 0002',0
                     db  'MB_YESNO = 0004',0Dh,0Dh,'IDYES = 0006',0Dh,'IDNO = 0007',0
                     db  'MB_RETRYCANCEL = 0005',0Dh,0Dh,'IDRETRY = 0004',0Dh,'IDCANCEL = 0002',0
                     db  'MB_ICONHAND = 0010',0
                     db  'MB_ICONQUESTION = 0020',0
                     db  'MB_ICONEXCLAMATION = 0030',0
                     db  'MB_ICONASTERISK = 0040',0
mb_number          dd  0000000Ah
mb_length            db  00h,1Ah,30h,4Ah,40h,2Ah,36h,13h,17h,1Ah,17h
mb_caption          db 'И все-таки Билл - гей... Тс-с-с-с...',0
mb_var                  dw 0000h,0001h,0002h,0003h,0004h,0005h,0010h,0020h,0030h,0043h

 .code

start:     mov ecx,mb_number                        ;количество окон
              mov edi,offset mb_var                     ;адрес значений переменной MB_RIGHT
              mov esi,offset mb_text                     ;адрес текстовых строк
_0100:          xor eax,eax
                     mov ax,[word ptr edi]                 ;в ах значение переменной
                     push ecx                                       ;сохранить счетчик
                     push eax                                       ;параметр для MessageBox
                     push offset mb_caption             ;параметр для MessageBox
                     mov eax,mb_number                   ;вычисление адреса текстового сообщения
                     sub eax,ecx
                     mov ebx,offset mb_length
                     xlat
                     add esi,eax

                      push esi                                         ;параметр для MessageBox (текстовое сообщение)
                      push 0
                      call MessageBoxA
                      pop ecx
                     inc edi
                     inc edi
                     loop _0100

                     push 0
                     call ExitProcess
end start

                А кто говорил, что будет «легко»? А вы думали это вам просто так – на ассемблере программировать? Я вот когда прогу пытался написать Зубкова на досуге почитал, так тот прямо так и говорит  - развею, грит, миф о том, что на асме трудно программировать. Запросто, грит, научу. Ну, книжку, в общем неплохую написал, это да... С такой книжкой и я бы в детстве не мучался и ночами бы в гнилой монохром не таращился. Но насчет «легко» - это только кролики легко плодятся, мягко выражаясь.

            Что в сущности я тут наваял... Это костяк проги-справочника, которая демонстрирует MessageBox в зависимости от переменных MB_  и тут же эту переменную и ее значение нам показывает. Почему костяк, а не вся программа? Потому что в мире нет ничего идеального – некоторые переменные под Windows 98 не доступны, некоторые не вызывают никаких видимых эффектов, а некоторые вообще машину вешают. Поэтому идею вам дарю, а реализацией занимайтесь сами. В проге же мы с вами должны увидеть десять окошек, сменяющих друг друга по нажатию любой высвечиваемой кнопки. Пока же попробуем разобраться с этим делом в теории.

Информация о характеристиках разных окошек, создаваемых функциями сходными с MessageBox передается через один push. Ну допустим – push 0. А кто-нибудь задумывался, что это, в принципе, за ноль? Это байт? Или слово?? Или кто??? Люди продвинутые в этом деле знают, что непосредственные значения (по-русски говоря, цифири в push) загоняются в стек как 32-битные значения. То есть как двойное слово. А если мы загоняем в стек регистр. Например – push bx? Он же 16-битный…

Мы с вами люди не продвинутые и хотим убедится во всем на примере. Пример будет таков:

 

            push ebx

 

            push ax

            push offset ля-ля-ля

            push offset тру-ля-ля

            push 0

            call MessageBox

 

            pop ebx

 

Вопрос – что будет после этого дела в ebx? Наше сохраненное значение? Ничего подобного! Функция MessageBox тупо восстановит стек после четырех 32-ух разрядных переменных (это она будет думать, что переменные 32-ух разрядные) и ей совершенно начихать, что первый параметр у нас 16-ти битный. Это весьма распространенная ошибка у тех, кто начинает програмить на Win32 после Dosa. Они привыкли, что стек восстанавливают они сами и что совершенно не принципиально какой разрядности переменную они туда загонят. Какую загонят – такую и восстановят.

            Впрочем, возможно кто-то подумает, что все вышеописанное и ежу понятно и незачем было так об этом орать. Ну что ж тут поделаешь – надо же было дойти до самой истины:)))

            Поехали дальше. Разберемся как организована передача информа о параметрах окошек MessageBoxа.

            В принципе, когда-то где-то я читал мемуары одного программиста-мелкософтника (на аглицком, естесно) который утверждал, что всю информацию о параметрах любого окна задумывалось передавать в 16-ти битовой переменной, которая будет разделена на четыре «тетради» (кто не знает: тетрада – полбайта, 4 бита, две «тетради» - байт). Ну, здесь не соврали значит, как задумывали, так и реализовали. Только переменная теперь 32-ух битная и «тетрадей», соответственно, восемь.

            Для понимания процесса :))) воспользуемся такой аналогией:

Представьте себе шкаф, внутри которого находятся восемь ящичков с надписями категорий (например, «ЦВЕТ», «ФОРМА» и т.д.), а внутри каждого ящичка шестнадцать карточек с определениями категории (например, в ящичке «ЦВЕТ» содержатся карточки «БЕЛЫЙ», «КРАСНЫЙ», «ЗЕЛЕНЫЙ» и т.д.). Вот в нашем случае тоже самое: шкаф – это 32-ух разрядное двойное слово, разделенное на восемь «тетрадей» (ящичков). Тетрадь, как уже упоминалось, это четыре бита, а четырьмя битами можно закодировать число от 0 до 15 (лучше в шестнадцатеричной системе, от 0 до F).

            Шкаф – это наш четвертый параметр в вызове функции MessageBox.

            В первом ящичке содержаться переменные, отвечающие за количество и название кнопок на нашем окошке. Например, если мы напишем «push 00000001», то это будет соответствовать тому, что мы в первом ящичке взяли первую карточку, и в нашем случае она называется MB_OKCANCEL.

            Второй полубайт отвечает за переменные определяющие выводимую иконку рядом с нашим сообщением. Например, «push 00000020» - переменная MB_ICONQUESTION и у нас выведется в окошке вопросик.

            Третья «тетрадь» - за переменные, определяющие на какой кнопке оставить фокус по умолчанию. Например, «push 00000101» соответствует тому, что мы определили переменную MB_OKCANCEL, которая выведет окошко с двумя кнопками (понятно, какими?) и переменную MB_DEFBUTTON2 (из третьего ящичка), которая установит фокус на вторую кнопку.

            В четвертом ящике содержаться переменные отвечающие за «модальность» окна. Ну это умное слово сами можете посмотреть где-нибудь в толковом словаре. А в реальности оно означает – будет или не будет торчать наш МессаджБокс на экране, если мы перейдем в другую задачу. Для тех кто скучный и нудный – не надо кривиться такому определению модальности окна.

            Хотя впрочем повод есть. Это я погорячился с модальностью. Это штука важная и разобраться с ней надо поподробнее, тем более что понятие модальности будет присуще не только нашему Мессаджу, но и вообще всем окнам, которые мы создадим. Поэтому отвлечемся пока от нашего шкафа и поговорим о модальности. Единственное, что меня раздражает в таких понятиях это их определения. Почему нельзя объяснить все просто – доступным человеческим языком? Почему-то все думают, что чем больше словарный запас, тем лучше они знают русский язык. А по-моему, даже с тридцатью словами Эллочки-людоедки можно легко и, главное доступно все объяснить. Ну, например, определение модальности из Словаря-справочника лингвистических терминов:

   Модальность – «грамматико-семантическая категория, выражающая отношение говорящего к высказываемому, его оценку отношения сообщаемого к объективной действительности». (????????????). Вы можете понять этот бред? А ведь кто-то может! Иначе бы такого определения не давал.

            Короче говоря, дети мы не малые, или, пожалуй, не малые мы дети, а поэтому модальность окон в программировании, это совсем не та модальность, которая в «лингвистических терминах». Смысел тут таков: если выводится модальное диалоговое окно, то работа нашей програмки приостанавливается до тех пор, пока мы с выведенным окном все дела не перетрем (то есть вступим в диалог с ним и удовлетворим его по полной программе). При этом наше главное окно и все дочерние окна им порожденные заблокируются и перестают получать какие-либо сообщения. А вот с другими программками работать мы свободно можем. Умным языком это звучит так – наша диалоговая панель модальна по отношению к главной программе. Для MessageBoxa все это богатство включается переменной MB_APPLMODAL.

            Программисты – не лингвисты, им мало «модально-немодально». Они придумали еще третий вариант – системную модальность. Это когда выводимое окошко до завершения своей работы блокирует не только главную свою программу, но и все приложения в округе, требуя полного вашего внимания и не дает вам отвлекаться на всякие Ворды и Проводники. Для MessageBoxa эта фишка включается MB_SYSTEMMODAL.

            Ну и немодальное окно чихать на вас хотело. Будете вы отвечать на его вопросы, не будете, захотите переключится в Ворд, не захотите – дело ваше, окно вам мешать не будет. Только для мессаджа нашего такой свободы нету. По умолчанию используется стиль MB_APPLMODAL и баста!

            Ну, пожалуй с модальностью все! Теперь вернемся к нашей мебели. Остановились мы на четвертом разряде. И дальше мы не пойдем. Ушлые читатели тут же начнуть вопить и терзаться: ”А почему это он остановился только на четвертом ящичке?”. Да потому что дальше идут только язвительные реверансы в сторону Майкрософта. Мало того, что они первые “ящички” не до конца заполнили (например, в первом разряде содержится только семь переменных из 16-ти возможных, включая MB_TYPEMASK, во втором только шесть, в третьем - пять и т.д.) так они еще в оставшихся ящичках всю эту стройную мебельную систему похерили и начали совать туда все подряд. Какие-то языковые переменные, переменные для новых версий Windows, какие-то MB_RIGHT (выравнивание по правому краю) и много еще всякой чепухи. Поэтому стройная система прослеживается только вначале, когда программисты Макрософта еще программировали, а не торговали чем попало…Поэтому далее нужно запомнить только одно - весь этот гарнитур называется регистро-флаговой архитектурой. Надеюсь, принцип объяснил понятно.

 

Прошло два месяца!!!

 

Да-да, дорогие мои… Прошло два месяца. А все почему? Потому что умный человек когда-то сказал – мужчин губят вино, женщины и принципы. Вот и я пошел на принцип, и чуть не забил на рассылку. А теперь вот сдаюсь... Сдаюсь и прошу помощи.

            Проблема такова: как вы помните (или вернее я помню) остановились мы на на левых переменных типа MB_RIGHT. Как человек ответственный:))) решил я проверить данную переменную на предмет работания. Как-то раньше не приходилось мне с ней сталкиваться. Ну и что вы думаете? НЕ РАБОТАЕТ!!! Скольких людей я замучил данной фишкой, сколько Инета перекопал (мне его даже отключили за «передозу») а ему хоть бы хны. Не выравнивает и все! Вот вам следующий фрагмент программы:

 

push 00080000h                     ;переменная MB_RIGHT

            push offset m_text

            push offset m_caption

            push 0

                        call MessageBox

 

Удалось выяснить только то, что не только MB_RIGHT не работает, а и другие переменные входящие в старшие разряды (типа MB_RTLREADING). Кроме того, по всей видимости, данные неприятности проявляются только на Windows 95-98. На 2000 и XP вроде бы все работает. Хотя только сегодня я проверял эту штуку на XP – не заработала. Правда, XP был какой-то битый.

            Проблема не в том, что нашелся очередной глюк Винды. Хотелось бы докопаться до первопричин. Функция MessageBox довольна стара (одна из первых) и вряд ли раньше не заметили такой лажи. Тем не менее никаких упоминаний о проблемах с этими переменными я не нашел. Кроме того не верится, что это глюк. Нюхом чувствую, что на самом деле где-то я лажанулся. Возможно с установкой языков, возможно с поддержкой шрифтов, или что-то в этом роде... Короче говоря, прошу всех, кто что-либо думает об этой проблеме выслать свои мысли и программки (работающие на Ваших машинах!) мне на мыло.

            Напоследок грустная история. Мои похождения по друзьям-товарищам с вышеописанной проблемой MessageBoxa закончились ничем. И  дошел я до того, что начал приставать с этой ерундой к любому человеку мало-мальски имеющему отношения к компьютерам в надежде найти какого-нибудь неведомого мне компьютерного гуру, который бы развеял все мои сомнения. В конце-концов всем это надоело и отослали меня к «самому-самому». Уж если не он, то никто. Окончательный Спец. Последний.

            Робко захожу в полутемный кабинет. На экране Delphi. Перед экраном «самый-самый». С выгоревшим хохолком, очках-линзах и вчерашним красным дипломом.  Краснея и запинаясь, излагаю проблему, говорю, мол, дело принципа и т.д. и т.п.. Он морщит лоб, быстренько выкидывает на форму пресловутый Бокс, устанавливает MB_RIGHT и глубокомысленно подтверждает: «Даааа... не работает...». После чего бодренько встряхивается и объявляет – ничего, говорит, проблема решаема, выдаешь МессаджБокс, потом на выведенный Бокс накладываешь сверху серый фон, загружаешь нужный стиль и в стиле выравниваешь по правому краю текст – получаешь твой МессаджБокс с выровненным текстом.

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

 

В следующем номере:

 

1.      Следующий номер будет!

2.      Следующий номер будет обязательно!

3.      Программа будет в следующем номере.

4.      Функция ExitProcess.

5.      Чье-то интервью.

 

P.S. Огромнейшие извинения всем, кому не ответил лично на присланные письма. Понимаю – это не красиво. Отвечу обязательно всем лично, хотя также понимаю, что ответы возможно будут уже не актуальны. Поэтому прошу – не обижайтесь:))))...

 

С уважением, Вал.Ик.

 

Все пинки, благодарности, критика и маты принимаются в неограниченном количестве по адресу:  p_avtom@amk.lg.ua


Администратор:
Электронный адрес:
Адрес сайта:
ICQ №
Калашников Олег
Assembler@Kalashnikoff.ru
http://www.Kalashnikoff.ru
68951340
 
 
 
 
(C) 2002, Россия, Вал.Ик.

 


SpyLOG be number one SUPERTOP


http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное