1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Пирогов Владислав Юрьевич

Тема в разделе "WASM.BOOKS и WASM.BLOGS", создана пользователем bers, 9 май 2006.

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.151
    Пирогов Владислав Юрьевич и его книги:
    1. «Ассемблер на примерах» СПб.: БХВ-Петербург, 2012 ― 416 с.: ил. ISBN 978-5-94157-745-3
      06.jpg
      На практических примерах рассмотрен широкий круг вопросов программирования на языке ассемблера, начиная от азов и заканчивая основами многозадачного программирования в операционных системах Windows NT\2000\XP\2003. Описаны команды микропроцессора, использование MASM, создание консольных и оконных приложений в Windows, работа с файлами и др. Все примеры сопровождаются подробными комментариями. Большое внимание уделяется совместному использованию языков ассемблера и C++, а также основам API-программирования
    2. «Ассемблер и дизассемблирование» СПб.: БХВ-Петербург, 2006 ― 464 с.: ил. ISBN 5-94157-677-3
      Рассмотрены вопросы исследования кода Windows-приложений. Подробно описаны формат исполняемых модулей и структура инструкций микропроцессора Intel. Дан полный обзор инструментария по исследованию исполняемого кода: отладчики, дизассемблеры, редакторы ресурсов, НЕХ-редакторы и др. Большое внимание уделено работе с популярными программами по дизассемблированию и отладке SoftlCE и IDA Pro. Приведены примеры исследования исполняемого кода и описаны основные принципы подобного исследования: идентификация программных структур, поиск данных и т.д.
    3. «Assembler. Учебный курс» М.:Нолидж 2000 ― 848 с.: ил. ISBN: 5-89251-094-8
      9432[1].jpg
      1. Трансляция программ с языка ассемблера. В главе даны начальные сведения о средствах программирования на языке ассемблер. Приводятся простейшие программы.
      2. Адресное пространство, структура программ. Говорится о адресном пространстве компьютеров IBM PC, работающих под управлением ОС MS DOS. Рассматривается структура программ на языке ассемблера.
      3. Первые программы. Приводятся несколько примеров программ на ввод-вывод информации с подробным их разбором. Разбирается понятие стека.
      4. Обзор команд микропроцессоров 8088/8086. Дан обзор команд микропроцессора 8088/8086, приведены программы и фрагменты программ, демонстрирующие свойства этих команд.
      5. Работа микропроцессора в защищенном режиме. Дано описание функционирования процессора в защищенном режиме. Вводятся основные понятия защищенного режима и алгоритм перехода в защищенный режим.
      6. Уровни программирования. Даны примеры программирования внешних устройств компьютера при помощи функций DOS, функций BIOS и путем прямого обращения к устройству.
      7. Клавиатура, дисплей, принтер. Приведено более подробное описание программирования трех выше названых устройств.
      8. Работа с файлами. Дано подробное описание средств MS DOS для работы с файлами. Обработка различного вида файлов, перенаправление ввода-вывода, одновременное открытие большого числа файлов.
      9. Прерывания. Рассмотрены следующие вопросы: Аппаратные и программные прерывания, перехват прерываний, контроллер прерываний и его программирование.
      10. Графический вывод. Дано введение в графическое программирование VGA, на примере одного из графических режимов.
      11. Работа с памятью. Рассмотрены вопросы: средства MS DOS управления памятью, программный запуск программ, оверлеи.
      12. TSR-программы. Рассмотрены все аспекты создания резидентных программ: перехват прерываний, неинтерабильность, разрешение конфликтов и др.
      13. Модульное программирование. Рассмотрены вопросы написания программ, состоящих из нескольких модулей, а также проблема передачи параметров.
      14. Структура информации на диске. Подробно разбирается структура информации на диске: каталоги, FAT-таблицы, таблицы параметров, структура EXE-файлов для MS DOS и Windows и т.п.
      15. Языки высокого уровня. Рассмотрены вопросы интерфейса языков высокого уровня (Паскаль, Си, Basic) с ассемблером. Рассмотрены некоторые вопросы программирования на языках высокого уровня в свете эффективности получаемого кода.
      16. Загружаемые драйверы. Излагается теория написания и структура загружаемых драйверов для MS DOS.
      17. Работа с "мышью" на языке ассемблера. Подробно описана программное управление манипулятором "мышь" посредством стандартного драйвера.
      18. Элементы теории вирусов. Рассмотрены проблемы борьбы с компьютерными вирусами.
      19. Проблемы компьютерной безопасности. Рассмотрены проблемы компьютерной безопасности и, в частности, защиты программного обеспечения от несанкционированного использования.
      20. Микропроцессоры 8088/8086.., 80486... Дан сравнительный анализ развития семейства микропроцессоров Intel с точки зрения программиста. Дается также описание и примеры программирования арифметического сопроцессора.
      21. Программирование в локальных сетях. Описаны средства написания программ, работающих в локальных сетях. Рассматривается локальная сеть под управлением Novel NetWare. Подробно описаны протоколы IPX, SPX.
      22. О том, какая в MS DOS имеется память и как ее использовать. Описаны способы программного использования различных видов памяти в среде MS DOS (расширенная, дополнительная, верхняя).
      23. Тестирование оборудования. Приведено несколько примеров тестирования оборудования.
      24. Начала программирование для WINDOWS. Рассматривается программирование в среде WINDOWS в 16-битном варианте.
      25. 32-х битное программирование для Windows. Рассмотрено программирование для операционных систем Windows 95,98. Рассматривается консольный режим, использование ресурсов.
      26. Программирование в защищенном режиме. Рассматривается защищенный режим, приводится примерs программирования в защищенном режиме с обработкой исключений и прерываний.
      27. Программирование VGA адаптеров. Дано описание средств программирования VGA адаптеров, включая программирования нестандартных режимов. Рассматривается также программирование SVGA адаптеров, VESA стандарт.
    4. «Ассемблер для Windows» 1-ое издание М.: Издатель Молгачева С. В. , 2002 ― 552 с.: ил.
      06.jpg
      продолжение книги "Assembler Учебный курс" в которой было отведено программированию под Windows всего две главы, теперь автор решил восполнить пробелы и посвятить Assembler для Windows всю книгу. Книга содержит справочный материал по написанию всех элементов к операционной системе Windows в четырех частях:
      • Часть I. Основы 32-битного программирования (средства программирования, простые примеры)
      • Часть II. Подробное описание программирования (консольные приложения, работа с файлами)
      • Часть III. Сложные примеры программирования (многозадачность, локальная сеть, DLL)
      • Часть IV. Отладка, анализ кода программ, драйверы
    5. «Ассемблер для Windows» 2-ое издание., перераб. и доп. СПб.: БХВ-Петербург, 2003 ― 656 с.: ил. ISBN 5-94157-329-4
      image001[1].gif
      • Первая часть книги отведена основам 32-разрядного программирования в Windows: инструментальным средствам, способам обращения к функциям Windows API и тому подобным базовым вопросам.
      • Во второй части программирование под Windows рассматривается более подробно. Разбираются консольные приложения, использование редакторов и трансляторов ресурсов, работа с файлами. Затрагиваются также макросредства ассемблера.
      • В третьей части описываются более сложные моменты программирования в Windows: синхронизация событий, многозадачность, создание DLL, работа с локальной сетью, некоторые вопросы системного программирования, а также совместная работа с программами на ассемблере в языках высокого уровня.
      • Последняя, четвертая часть посвящена вопросам отладки, дизассемблированию программ, а также созданию VxD-драйверов для Windows 9x (в следующем издании книги автор обещает рассмотреть драйверы Windows NT).
    6. «Ассемблер для Windows» 3-ье издание., перераб. и доп. СПб.: БХВ-Петербург, 2005 ― 864 с.: ил ISBN 5-94157-545-9
      000247997[1].jpg
      Приведены необходимые сведения для программирования Windows-приложений на ассемблерах MASM и TASM: разработки оконных и консольных приложений, создания динамических библиотек, многозадачного программирования, программирования в локальной сети, в том числе и с использованием сокетов, простые методы исследования программ. Изложенный материал сопровождается большим количеством примеров, которые позволят читателю в короткий срок освоить программирование приложений для Windows на языке ассемблера.
    7. «Ассемблер для Windows» 4-ое издание., перераб. и доп. СПб.: БХВ-Петербург, 2012 ― 896 с.: ил ISBN: 978-5-9775-0084-5
      Рассмотрены необходимые сведения для программирования Windows-приложений на ассемблерах MASM и TASM: разработка оконных и консольных приложений; создание динамических библиотек; многозадачное программирование; программирование в локальной сети, в том числе и с использованием сокетов; создание драйверов, работающих в режиме ядра; простые методы исследования программ и др. В 4-м издании материал существенно переработан в соответствии с новыми возможностями ОС. Значительно шире рассмотрены вопросы управления файлами и API-программирования в Windows. Добавлен материал по программированию в ОС семейства Windows NT: Windows 2000/XP/Server 2003/Vista.
    8. «SQL Server 2005. Программирование клиент-серверных приложений» СПб.: БХВ-Петербург, 2006 ― 336 с.: ил ISBN: 5-94157-990-X
      1162_5-94157-990-X-231x325.jpg
      широкий круг вопросов, связанных с проектированием реляционных баз данных и созданием клиент-серверных приложений на основе SQL Server 2005. Подробно рассмотрено программирование на языке Transact-SQL на стороне сервера. Даны основы программирования в Visual Studio .NET как на стороне сервера, так и на стороне клиента. Подробно описано использование технологий ODBC и ADO.NET при создании клиентской части приложений. Приведены примеры создания хранимых процедур и других программных объектов SQL Server на языке С#/С++
    9. «Программирование на Visual C++ .NET» СПб.: БХВ-Петербург, 2003 ― 800 с.: ил ISBN: 5-94157-291-3
      Vladislav_Pirogov__Programmirovanie_na_Visual_C_.NET.jpeg
      В книге рассматриваются такие современные технологии, как многозадачное программирование, программирование сокетов, Web-программирование (в т. ч. и со стороны сервера), программирование баз данных (в т. ч. технология OLE DB), библиотека классов ATL, СОМ-программирование. За базовую основу взята последняя версия Visual C++, входящая в пакет Visual Studio .NET. Подробно описаны основы работы в среде Visual C++, позволяющие создавать проекты любого уровня сложности. Книга предназначена тем, кто уже знаком с основами программирования и хочет пополнить свой профессиональный багаж языком C++ и системой программирования Visual C++.
    10. «Операционные системы на базе набора команд x86–64 в контексте низкоуровневого программирования» 2016 ― 13 с.
      рассматривается 64‑битное расширение архитектуры x86 (x86-64). Разбираются основные особенности данной спецификации с позиций программирования. Проводится сравнительный анализ низкоуровневой организации программ для различных операционных систем, поддерживающих архитектуру x86-64. Приводятся примеры анализа программного кода, скомпилированного для операционных систем, отличающихся друг от друга реализацией соглашения о вызовах.
    11. «Информационные системы и базы данных: организация и проектирование: учебное пособие» СПб.: БХВ-Петербург, 2009 ― 529 с.: ил ISBN: 978-5-9775-0399-0
      Излагаются основные вопросы по организации и проектированию информационных систем: классификация, структура, безопасность и принципы проектирования; а также архитектура информационной системы: интерфейсы и протоколы, клиентские приложения. Большое внимание уделяется базам данных и их программному управлению, языкам SQL и QBE. Приводятся примеры новых технологий в области баз данных.
     

    Вложения:

    • 6988772[1].jpg
      6988772[1].jpg
      Размер файла:
      38,1 КБ
      Просмотров:
      289
    • coverbig.jpg
      coverbig.jpg
      Размер файла:
      49,6 КБ
      Просмотров:
      284
    • 06.jpg
      06.jpg
      Размер файла:
      198,6 КБ
      Просмотров:
      292
    • 06.jpg
      06.jpg
      Размер файла:
      34,9 КБ
      Просмотров:
      277
    Thetrik нравится это.
  2. asmlamo

    asmlamo Active Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    1.646
    а однако плодотворен этот ваш Пирогов .... книги ляпает как пирожки печет !
    Там в щадринске воздух особый ?
     
  3. texaciri

    texaciri Member

    Публикаций:
    0
    Регистрация:
    27 янв 2018
    Сообщения:
    47
    некоторые темы поглядывал в "Ассемблер и дизассемблирование", то что попадалось было написано достаточно хорошим языком. Полностью не читал.

    asmlamo, не так и много, учитывая что из представленного списка часть - переиздания.
     
  4. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.066
    Надеюсь, этот хоть не медвежонок, как Зубков? :)
     
  5. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.151
    Интересно, а как должна была выглядеть конструкция CASE? Как jmp [WM_table*4] ? Вроде бы и C++ в Visual Studio набор jump'ов...
     
  6. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.402
    Рекорд некропостинга побит?
     
  7. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.151
    Это старое сообщение из топика "Сам себе Iczelion"

    Сообщения, которые Windows посылает приложению, на самом деле получает процедура окна, определенная для данного класса. Чаще всего она представляет собой конструкцию «выбора», которую в языке C/C++ называют SWITCH, в Pascal/Delphi — CASE, в Basic — SELECT CASE, а в абстрактном языке программирования — мультивлетвением. Задача конструкции CASE заключается в проверке на равенство значения переменной var элементу из списка.
    Код (Pascal):
    1. CASE <var> OF
    2. <case A> (выполнить, если var = A)
    3. <case B> (выполнить, если var = B)
    4. .  .  .
    5. <case N> (выполнить, если var = N)
    6. <default> (выполнить, если нет соответствия)
    7. END;
    Данная конструкция направляет сообщения функциям обработчикам. На ассемблере конструкция CASE может быть реализована, по крайней мере, семью способами:
    1. тупо, через повторяющиеся команды cmp и je
    2. через макрос
    3. через высокоуровневые директивы .IF .ELSEIF .ELSE
    4. через косвенные переходы или косвенный вызов процедур
    5. через команду SCASD
    6. через последовательное приближение
    7. через имитацию команды XLAT
    Рассмотрим подпрограмму, обрабатывающую только четыре сообщения: WM_CREATE=1, WM_DESTROY=2, WM_PAINT=0Fh и WM_TIMER=113h. Пусть сообщение WM_XX обрабатывается по адресу @@WM_XX. Учтем так же, что частота появлений различных сообщений неодинакова, поэтому проверяем сперва наиболее часто посылаемые WM_PAINT и WM_TIMER, затем однократно используемую WM_CREATE, и наконец последнее сообщение в жизни нашего приложения WM_DESTROY.
    Итак, первый способ очевиден.
    Код (ASM):
    1. cmp dword ptr Msg,WM_TIMER
    2.     je @@WM_TIMER
    3. cmp dword ptr Msg,WM_PAINT
    4.     je @@WM_PAINT
    5. cmp dword ptr Msg,WM_CREATE
    6.     je @@WM_CREATE
    7. cmp dword ptr Msg,WM_DESTROY
    8.     je @@WM_DESTROY
    9. leave
    10.     jmp DefWindowProcA; обработка по умолчанию
    11. @@WM_DESTROY:
    12. . . .
    13. @@WM_CREATE:
    14. . . .
    15. @@WM_PAINT:
    16. . . .
    17. @@WM_TIMER:
    18. . . .
    один из вариантов первого способа — заменить команду cmp на команду sub
    Код (ASM):
    1. mov eax,Msg
    2. dec eax
    3. jz @@WM_CREATE    ;WM_CREATE=1
    4. dec eax
    5. jz @@WM_DESTROY    ;WM_CREATE+1=WM_DESTROY=2
    6. sub eax,WM_PAINT-WM_DESTROY
    7. jz @@WM_PAINT    ;WM_DESTROY+0Dh=WM_PAINT=0Fh
    8. sub eax,WM_TIMER-WM_PAINT
    9. jz @@WM_TIMER    ;WM_PAINT+104h=WM_TIMER=113h
    10. leave        ;все сообщения, не обрабатываемые в функции
    11.     jmp DefWindowProcA;WndProc, направляются на обработку по умолчанию
    12. @@WM_DESTROY:
    13. . . .
    Способ второй. Используем макрос с IRP-блоком (Вы, конечно, можете, если захотите, написать другой макрос). Блоки повторения IRP имеют следующий вид:
    Код (Text):
    1. IRP p,<v1,…,vn>
    2. <тело блока>
    3. ENDM
    Запись в уголках <v1,…,vn> это явно указываемые фактические параметры, p — некоторое имя, оно играет роль формального (фиктивного) параметра и используется в предложениях тела блока. Фактические параметры vi перечисляются через запятую, а вся их совокупность обязательно заключается в угловые скобки. Встретив IRP-блок, макрогенератор заменит блок на n копий тела блока (по одной копии на фактический параметр), причем в i-той копии все вхождения имени p заменятся на vi. Знак & указывает границу формального параметра, выделяет его из окружающего текста, но в окончательный текст программы не попадает. Если в теле блока повторения или макроса имеются комментарии (в конце каких-то предложений или как самостоятельные предложения), то они переносятся во все копии блока. Если комментарий полезен при описании самого блока повторения, но совершенно не нужен в его копиях — тогда комментарий начинают с двух точек с запятой — такие комментарии не копируются.
    Код (ASM):
    1. IRP CASE,<WM_TIMER,WM_PAINT,WM_CREATE,WM_DESTROY>;;последовательность вариантов
    2. cmp dword ptr Msg, CASE;;вариант найден?
    3. je @@&CASE
    4. ENDM;;закончить макроописание
    5. leave        ; обработка по умолчанию
    6.     jmp DefWindowProcA
    7. @@WM_DESTROY:
    8. . . .
    Способ третий. Пример использования директив ассемблера .IF .ELSEIF .ELSE .ENDIF:
    Код (ASM):
    1. .IF (Msg==WM_TIMER)
    2. . . .            ;здесь обрабатывается сообщение WM_TIMER
    3. .ELSEIF (Msg==WM_PAINT)
    4. . . .            ;здесь обрабатывается сообщение WM_PAINT
    5. .ELSEIF (Msg==WM_CREATE)
    6. . . .            ;здесь обрабатывается сообщение WM_CREATE
    7. .ELSEIF (Msg==WM_DESTROY)
    8. . . .            ; здесь обрабатывается сообщение WM_DESTROY
    9. .ELSE
    10.  leave
    11. jmp DefWindowProcA; обработка по умолчанию
    12. .ENDIF
    И вариант с макросом, и вариант с .IF .ELSEIF .ELSE .ENDIF все равно будут оттранслированы в повторяющиеся команды CMP и JE
    Способ четвертый. Налицо в программе очень много повторяющихся почти одинаковых фрагментов. Нельзя ли написать программу как-нибудь иначе? Чем различаются эти фрагменты программы? Разными операндами в команде CMP, разными адресами переходов или разными вызываемыми процедурами. Уберем операнды команды CMP в какой-нибудь регистр и используем для разных адресов переходов косвенный переход, а для разных вызываемых процедур — косвенный вызов процедуры.
    Код (ASM):
    1. ;Таблица сообщений, которые обрабатывает процедура окна
    2. MsgTable dd WM_PAINT, @@WM_PAINT, WM_TIMER, @@WM_TIMER, WM_CREATE, @@WM_CREATE, WM_DESTROY, @@WM_DESTROY, 0; Конец списка обязательно 0
    3. . . .
    4. ;Вызов соответствующего обработчика
    5.     mov esi,offset MsgTable    ;устанавливаем в ESI адрес таблицы-диспетчера
    6. @@:  lodsd         ;устанавливаем в eax тип сообщения
    7.     test eax,eax    ;это конец таблицы? Если да, то данное сообщение не
    8.     jz default; обрабатывается приложением - передаем управление Windows
    9.     cmp eax,Msg ;для данного сообщения не найден обработчик
    10.     jne a2   ;устанавливаем в esi адрес обработки сообщения
    11.     jmp dword ptr [esi]  ;передаем управление обработчику сообщения
    12. a2: add esi,4            ;перейдем к следующему сообщению
    13.     jmp @b
    14. default: leave        ;Обработчик не найден, возвращается значение,
    15.     jmp DefWindowProcA    ; которое дает стандартный обработчик
    16. @@WM_DESTROY:
    Способ пятый. Используем команду SCASD с префиксом REPNE. Внесем в конец таблицы сообщений, которые обрабатывает процедура окна, адрес обработки по умолчанию, а в регистр ECX количество элементов в таблице сообщений минус один (компилятор подсчитает это число автоматически). Напомню, что команда SCASD сравнивает значение в регистре EAX с ячейкой памяти, локализуемой регистром EDI. Префикс REPNE не только заставляет циклически выполняться команду сканирования, пока ECX не станет равным 0, но и отслеживает состояние флага ZF. Как только содержимое в ячейке памяти совпадет со значением в регистре EAX, сканирование остановится. Регистр EDI будет указывать не на ячейку памяти, значение которой совпадает с регистром EAX, а на следующую ячейку. Сканирование также остановится, если содержимое регистра ECX станет равным 0. При этом в регистре EDI будет адрес метки default (адрес обработки по умолчанию)
    Код (ASM):
    1. ;Таблица сообщений, которые обрабатывает процедура окна
    2. MsgTable dd WM_PAINT, @@WM_PAINT, WM_TIMER, @@WM_TIMER, WM_CREATE, \
    3. @@WM_CREATE, WM_DESTROY, @@WM_DESTROY, default
    4. MsgCount = ($ - MSGTable - 4)/4
    5. . . .
    6.      mov edi,offset MsgTable;устанавливаем в EDI адрес таблицы-диспетчера
    7.      mov eax,Msg
    8.      mov ecx,MsgCount;удвоенное количество обрабатываемых сообщений (4*2=8)
    9.      repne scasd        ;ищем сообщение и если найдем — передадим
    10.      jmp [edi]        ; управление обработчику сообщения
    11. default: leave        ; если обработчик не найден, вызывается
    12.       jmp DefWindowProcA ; обработка по умолчанию
    13. @@WM_DESTROY:
    По величине это, по-моему, самый короткий код функции обработки сообщений. Кстати, «а что произойдет, если адрес обработчика сообщения совпадет с номером сообщения?» Этого не может произойти, так как максимальный номер стандартных сообщений равен 400h, а 32-разрядная операционная система Windows отводит каждой программе свое адресное пространство размером около двух гигабайт, начиная с адреса 100000h. За границы своего адресного пространства задача выйти не может, так же, как никакая другая задача не может работать с данным пространством - этим и определяется автономность программы.
    Способ шестой — последовательное приближение. Пусть у нас уже не 4 обрабатываемых сообщения, а 100. Тогда при использовании с первого по пятый способ мы должны будем последовательно сравнить до 100 значений, до тех пор пока не найдем искомое. Увеличим скорость обработки сообщений, которые Windows посылает Вашему приложению. Рассортируем номера обрабатываемых нашей программой сообщений по возрастанию, теперь разделим номера сообщений на две равные группы — 50 сообщений с меньшими номерами в одной группе, 50 сообщений с большими номерами в другой. После определения, к какой из групп сообщений принадлежит вновь поступившее сообщение, нам потребуется уже не 100, а только 50+1 сравнение. Разобьем каждую из образовавшихся групп с номерами сообщений еще на две подгруппы, и потребуется уже 25+2 сравнений, вместо 100. Продолжаем делить подгруппы с номерами сообщений, и получаем 13+3 вместо 100, затем 7+4, далее 4+5, и, наконец, 2+6, больше разбивать подгруппы не имеет смысла (дальше было бы 1+7, а это одно и то же, что и 2+6). То есть, в общем случае, если [math]2^{n-1} < N \leq 2^{n}[/math], то определить [math]N[/math] можно не более чем за n+1 приближение. Заметьте, увеличение скорости обработки будет сопровождаться разрастанием кода программы.
    Код (ASM):
    1. mas        dd WM_DESTROY... WM_PAINT ;массив сообщений
    2.         n = ($ - mas)/4
    3. mas1        dd @@WM_DESTROY,...  @@WM_PAINT;массив адресов
    4. ...
    5.         xor ecx,ecx            ;в ecx индекс первого элемента
    6.         mov edx,n-1            ;в edx индекс последнего элемента
    7.         mov eax,Msg
    8.         cmp eax,WM_CREATE;сравниваем с минимальным элементом таблицы
    9.         jb default;если меньше, то обработка по умолчанию
    10.         je @@WM_CREATE
    11.         mov ebx,edx        ;создаем индекс центрального элемента
    12. a1:     cmp ecx,edx        ;проверка ecx>edx на окончание поиска
    13.         ja default;проверены все элементы, обработка по умолчанию
    14.         shr ebx,1    ;индекс центрального элемента равен (edx+ecx)/2
    15.         cmp mas[ebx*4],eax    ;сравниваем с искомым значением
    16.         jb a2            ;mas[ebx*4]<Msg
    17.         je a3         ;mas[ebx*4]=Msg
    18.         inc ebx        ;учтем только что проверенное значение
    19.         mov ecx,ebx            ;изменяем нижнюю границу поиска
    20.         add ebx,edx        ;создаем индекс центрального элемента
    21.         jmp a1        ;переходим к следующему элементу
    22. a2:     dec ebx        ;учтем только что проверенное значение
    23.         mov edx,ebx            ;изменяем верхнюю границу поиска
    24.         add ebx,ecx        ;создаем индекс центрального элемента
    25.         jmp a1        ;переходим к следующему элементу
    26. default:leave            ;искомое значение не найдено,
    27.         jmp DefWindowProc    ;обработка по умолчанию
    28. a3:     jmp mas1[ebx*4]        ;искомое значение найдено
    29. @@WM_CREATE: ...
    А это еще один, более короткий вариант последовательного приближения. Но для него требуется, чтобы количество сообщений должно быть равным 2n. Допустим, мы обрабатываем 16 сообщений,
    Количество элементов [math]2^{n-1} < N \leq 2^{n}[/math]
    ebx (индекс элемента) [math]2^{n-1}[/math]
    ecx (счетчик приближений) [math]n+1[/math]
    так как N = 16, то в соответствии с таблицей: n = 4, ebx = 8, ecx = 5
    Код (ASM):
    1. mas         dd  WM_DESTROY, ... WM_PAINT;массив сообщений
    2. mas1        dd @@WM_DESTROY,... @@WM_PAINT ;массив адресов
    3. n = ($-mas1)/4
    4. ...
    5.         mov ebx,1
    6.         shl ebx,n-1            ;ebx=8 индекс центрального элемента
    7.         xor edx,edx            ;нижняя граница поиска
    8.         mov eax,Msg
    9.         cmp eax,WM_CREATE;сравниваем с минимальным элементом таблицы
    10.         jb default;если меньше, то обработка по умолчанию
    11.         je @@WM_CREATE
    12. a1:     cmp mas[edx+ebx*4],eax    ;сравниваем с искомым значением
    13.         ja a2            ;mas[ebx*4]<Msg
    14.         je a3         ;mas[ebx*4]=Msg
    15.         lea edx,[edx+ebx*4]    ;изменяем нижнюю границу поиска
    16. a2:     shr ebx,1        ;изменяем индекс центрального элемента
    17.         jnz a1            ;переходим к следующему элементу
    18. default: leave            ;искомое значение не найдено
    19.         jmp DefWindowProc        ;обработка по умолчанию
    20. a3:     jmp mas1[edx+ebx*4]     ;искомое значение найдено
    21. @@WM_CREATE: ...
    Если Вы и дальше хотите экспериментировать с обработкой сообщений — попробуйте заменить команду cmp на команды sub, dec, test, or или and.
    Способ седьмой — имитация команды XLAT. При программировании на ассемблере стремятся либо получить максимально компактный код, либо достичь максимального быстродействия, хотя иногда добиваются и того, и другого. Способы четыре и пять, реализуемые через косвенный переход или косвенный вызов, хотя и имеют наименьший размер кода, но по быстродействию остаются таким же, как и способы с прямым переходом. То есть, всегда возможен вариант, когда будут перебраны все варианты сообщений, перед тем как запустится обработка сообщения по умолчанию. Реализуем мультиветвление при помощи косвенного перехода по таблице. Для увеличения скорости просмотра очереди сообщений строим процедуру подобную команде XLAT (сама команда XLAT, к сожалению, дает возможность работать только с 256 вызовами), строим таблицу MsgTable, где номер элемента таблицы соответствует номеру сообщения. Сами табличные элементы представляют собой адреса (процедур), где эти сообщения обрабатываются. Чтобы не перечислять все 400h (1024) сообщений, можно определить номер максимального сообщения Max_Msg и если номер сообщения больше максимального, сразу отправлять на обработку сообщения по умолчанию (метка default). Сообщения, не обрабатываемые в процедуре WinProc, также имеют адрес обработки соответствующий адресу метки default. При этом время выполнения перехода всегда одинаково для всех вариантов мультиветвления.
    Код (ASM):
    1.   mov eax,Msg
    2.   cmp eax,Max_Msg
    3.   ja default;MsgTable - таблица с адресами обработки
    4.   jmp MsgTable[eax*4];каждый адрес обработки расположен через 4 байта
    Но у этого способа есть и оборотная сторона. К сожалению, большая скорость обработки сообщений будет компенсирована раздувшейся таблицей MsgTable.
     
  8. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.151
    Была бы возможность -- я бы спросил через личку у bers Просто стало интересно, а как должен выглядеть CASE
     
  9. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.402
    По-моему если кейс на непрерывном множестве 0..х, то компиль студии, что-то знающий за всю эту оптимизацию, организует его на таблице адресов и jmp [eax*4+table_address]. В остальных случаях, например для WM_ сообщений, будут те же связки на cmp/jcc/jmp. Скорей всего персонажа смутила конструкция:
    Код (ASM):
    1. cmp ...,...
    2. je ..
    3. cmp ...,...
    4. je
    5. ...
    6. jmp ...
    вместо той, к которой он привык:
    Код (ASM):
    1. cmp ...,...
    2. jne @F
    3. ;обработчик
    4. jmp ...
    5. @@:
    6. cmp ...,...
    7. jne @F
    8. ...
    9.  
    Из всей "оптимизации" здесь разве что лишний безусловный переход в DefWindowProc. Что про это предикция процессоров интел думает, я хз. Но поставил бы на первый метод, хоть он и кривой, зато всё рядом и процу понадобится меньше мозгов чтобы предсказать.

    ЗЫ: а может быть пассажир имел в виду длины инструкций переходов в такой конструкции.
     
    Последнее редактирование: 18 май 2021
  10. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.151
    f13nd,
    спасибо за ответ, хотя возможно bers имел ввиду ELSEIF (Msg==WM_PAINT), хотя это тоже череда из cmp и je/jne
     
  11. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.402
    Да не, я подумал и сейчас почти уверен, что про длину инструкций он и говорил. Если на jne скипать обработчик, выше вероятность того, что jne получится 2-байтным. В то время как в предложенной конструкции переход будет всегда на сумму длин всех обработчиков до нужного и гораздо чаще они будут 5-байтными.
     
    Mikl___ нравится это.
  12. R81...

    R81... Member

    Публикаций:
    0
    Регистрация:
    1 фев 2020
    Сообщения:
    42
    По мне табличная существенно проще: наглядность для понимания и изменений.

    Посмотрел листинг XP SP3
    WM_CAP_* много тут Number 000004xxh
    WM_CHOOSEFONT_GETLOGFONT401h
    WM_CHOOSEFONT_SETFLAGS466h
    WM_CHOOSEFONT_SETLOGFONT465h
    WM_CPL_LAUNCHED7E9h
    WM_CPL_LAUNCH7E8h
    WM_DLGBORDER11EFh
    WM_DLGSUBCLASS11F0h
    WM_PSD_ENVSTAMPRECT405h
    WM_PSD_FULLPAGERECT401h
    WM_PSD_GREEKTEXTRECT404h
    WM_PSD_MARGINRECT403h
    WM_PSD_MINMARGINRECT402h
    WM_PSD_PAGESETUPDLG400h
    WM_PSD_YAFULLPAGERECT406h
    WM_RASDIALEVENT0CCCDh
    ^^^^^^^^ с большими номерами не знаю как.

    А для номеров 0..(X-1), если обрабатывать не более 256 ситуаций,

    память можно сократить c X * 4 до X + 4 * (кол-во своих)
    Код (ASM):
    1. Mov eAx,[Msg]
    2. Cmp eAx,[Max_Msg]
    3. JA default
    4. MovZx eAx,[StdToMyTab + eAx]  ; байты для перекодировки стандартной в свою
    5. Jmp [MyMsgTable + eAx * 4]  ; каждый адрес обработки расположен через 4 байта
    6. ; MyMsgTable - таблица для своих номеров
    7.  
    8.  память можно сократить c X * 4 до X + 2 * (кол-во своих)
    9. Код (ASM):
    10.   MulAdr = 8 ; 1 2 4 8  ~суммарные длины < 65536 * MulAdr (без ReJmp-овых)
    11.   Mov eAx,[Msg]
    12.   Cmp eAx,[Max_Msg]
    13.   JA WM_default
    14.   MovZx eAx,[StdToMyTab + eAx]  ; байты для перекодировки стандартной в свою
    15.   MovZx eAx,[MyMsgOffsTab + eAx * 2]  ; смещения от базового адреса
    16.   LEA  eAx,[WM_default + eAx * MulAdr]
    17.   Jmp  eAx
    18. StdToMyTab  db  0 ; например
    19. ; ....
    20.   db  0 ; например
    21.   Align 2
    22. MyMsgOffsTab dw  0
    23.   dw  (SubMsgMyInd1 - WM_default) / MulAdr
    24. ; ....
    25.   dw  (SubMsgMyInd255 - WM_default) / MulAdr
    26.   Align MulAdr
    27.   WM_default:
    28. ; ....
    29.   Align MulAdr
    30.   SubMsgMyInd1:
    31.   Jmp LongSubMsgMyInd1  ; ReJmp
    32. ; ....
    33.   Align MulAdr
    34.   SubMsgMyInd255:
    35. ; .....
    36.  
    37. ;  для длинного обработчика
    38. LongSubMsgMyInd1:
     
    Mikl___ нравится это.
  13. algent

    algent New Member

    Публикаций:
    0
    Регистрация:
    11 апр 2018
    Сообщения:
    19
    Блин, дурацкая тема затянула на несколько часов :)
    Захотелось при помощи SSEx.x сделать что-то вроде,
    псевдокод:
    jmp [int(msg == WM_N1)*adr_case1 + int(msg == WM_N2)*adr_case2 + int(msg == WM_N3)*adr_case3 + .....]

    Хотелось обойтись, по понятным причинам без AVX, но лишь в AVX512(!!!!) есть команда типа VPBROADCASTW.
    msg и adr_case - тип WORD. Сначала, всё вроде хорошо:
    VPBROADCASTW ymm1 {k1}{z}, reg -- Broadcast a 16-bit value from a GPR to all words in the
    256-bit destination subject to writemask k1
    Наш msg "заселяет" все 16 вордов 256-битного ymm1.
    VPCMPEQW ymm1, ymm1, ymm3 /m256 -- Compare packed words in ymm3/m256 and
    ymm1 for equality.
    В ymm3 /m256, до 16 констант, которые соответствуют кэйсам. После сравнения, только в одном может быть 0ffffh.
    VPAND ymm2, ymm1, ymm2/.m256 -- Bitwise AND of ymm1, and ymm2/m256 and
    store result in ymm2.
    В ymm2/.m256, до 16 адресов перехода. После VPAND, в ymm2, только один адрес не помножен на ноль.
    Его надо лишь переслать в eax и тут облом :dntknw:, за 1-2 команды похоже это не сделать.
    Остаются либо сдвиги, либо горизонтальные сложения:
    VINSERTI128 ymm1, ymm2,xmm3/m128, imm8 и PHADDW/PHADDD — Packed Horizontal Add
    Обидно :dntknw:.
     
    Mikl___ нравится это.
  14. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    770
    интересно, условная дизьюнкция в полиноме жегалкина выглядит так [​IMG] , но и через нот энд и ор она выглядит не очень сложно. это конечно не кейс, но иф. Сильно это проигрывает по тактам, по стравнению с компаре и джамп ?
     
  15. Intro

    Intro Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    268
    В UASM есть .switch ... .endswitch и .case! Работать может как в Си, так и в паскаль стиле. При компиляции выбирается табличный способ. Так же такая штука есть в asmC.
     
  16. algent

    algent New Member

    Публикаций:
    0
    Регистрация:
    11 апр 2018
    Сообщения:
    19
    Схемотехнически 2-входовой OR или AND, это 2 диода или дополнительные затворы у повторителя, и почти нулевое Tpd.
    Эти команды быстры как MOV.
    А условный JMP это вообще драма :).
    До появления спекулятивного выполнения, при ошибке блока предсказания перехода, перезагружался конвеер.
    Очищалась очередь команд и в неё загружались команды из правильной ветки.

    С появлением спекулятивного выполнения, используется 2 конвеера, для каждой ветки. И типа больше нет проблем.
    Но тут возникает вопрос: при отсутствии джампов, 2й конвеер ведь используется эффективно,
    удваивая производительность, например, удлиняя конвеер??
    А когда появляется джамп, ЭТА производительность падает, ибо один из конвееров работает в холостую??
    В доках Интела я не видел ответов. Хотя, давно читал, что-то уже забыл возможно.
    Ну и даже безусловный джамп всегда(когда указывали число тактов) был кажется дольше, чем MOV.
     
    q2e74 нравится это.
  17. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.151
    JMP это не MOV, а ADD или SUB с содержимым IP/EIP/RIP
     
  18. algent

    algent New Member

    Публикаций:
    0
    Регистрация:
    11 апр 2018
    Сообщения:
    19
    А так:
    mov [rbx+140h], ecx :) ?
    Но если вернуться к сравнению кол-ва тактов, то что-то вроде:
    mov dword ptr [rbx+rcx*8+144h], 7 проиграет jnz чисто по кол-ву тактов, даже при наличии операнда в кэше.
    Но имхо, последствия от jnz, гораздо значительнее.
    Но конечно, без тестов это пустые разговоры.
     
    q2e74 нравится это.