Message Box

...
  • Не получается сделать вызов параметров, как в примере. Вызов желаю так:

    Code: Select all

    but_3:
      push eax
        mov eax,[mb_procinfo]
        mov [eax],dword procinfo
      pop eax
      push msgbox_3 ;дал адрес сообщения +4(1)
      push thread ;дал адрес памяти для стека +4(2)
      call [mb_create] ;вызвал функцию +4(3)
      jmp still
    А саму функцию так:

    Code: Select all

    MsgBoxCreate:
    ;  push ebp
    ;  mov ebp,esp
    ;    push eax ebx ecx edx
        mov eax,[ebp+12] ;беру адрес сообщения 4(3)+4(2)+4(1)=12
        m2m dword[mb_text],dword[eax] ;адрес пишу в переменную mb_text
        mov edx,[ebp+8] ;беру адрес памяти для процесса 4(3)+4(2)=8
        mov eax,51 ;создание потока функцией 51 ...
        mov ebx,1
        mov ecx,start
        int 0x40
    ;    pop edx ecx ebx eax
      ret 8 ;выкидаю из стека переменные 4(1) и 4(2)
    В результате не работает, могу дать весь код, но думаю что и в этом можно найти ошибку
  • Принцип работы со переменными, передаваемыми в стеке, следующий.
    Пусть процедура вызывается как stdcall с тремя параметрами param0, param1, param2; тогда код вызова выглядит следующим образом:

    Code: Select all

        push param2
        push param1
        push param0
        call func
    label:
    
    При этом в момент начала выполнения func стек выглядит следующим образом:

    Code: Select all

        [esp] = label ; на вершине стека находится адрес возврата, результат инструкции call
        [esp+4] = param0 ; последнее запихнутое в стек значение, результат последнего push
        [esp+8] = param1 ; предпоследнее запихнутое в стек значение, результат предпоследнего push
        [esp+12] = param2
    
    Так что к переданным аргументам уже можно обращаться через esp со смещением. Это один из вариантов работы.
    Есть и другой вариант. Работать с esp не всегда удобно, поскольку оно меняется при всяких push/pop и нужно соответственно добавлять 4*число заpushенных dwordов; кроме того, в 16-битном режиме адресации через sp не было вообще, а в 32-битном она хотя и есть, но занимает на байт больше (mov eax,[esp+4] на байт длиннее mov eax,[ebp+4]); кроме того, если процедура работает с постоянно меняющимся esp, то нельзя автоматически из внешнего кода раскрутить стек в поисках цепочки вызовов, приведших к текущему состоянию (есть и другие аспекты). Поэтому часто используется также адресация через ebp. Для этого в начало функции добавляется код

    Code: Select all

        push ebp
        mov  ebp, esp
    
    после чего стек принимает вид

    Code: Select all

        [ebp] = старое значение ebp ; верхушка стека
        [ebp+4] = адрес возврата из процедуры
        [ebp+8] = param0
        [ebp+12] = param1
        [ebp+16] = param2
    
    В конце процедуры, естественно, нужно восстановить стек и старое значение ebp. Минусы такого стиля адресации заключаются в дополнительном коде пролога/эпилога процедуры и в потере одного регистра, который можно было бы задействовать для других целей.

    В коде, приведённом ранее, отсутствует инициализация ebp, так что [ebp+N] указывает в никуда.
    Ушёл к умным, знающим и культурным людям.
  • Учел то что сказали Albom и diamond, и сделал более новую версию библиотеки. Убрал ссылку на структуру mb_procinfo, потому что передаю ее в стеке.
    Кроме того несколько изменений: улучшил работу с кнопками Влево и Вправо, окно размещается в центре экрана.
    Описал в файле msgbox.asm все константы и переменные. Функция теперь stdcal потому думаю с ней все понятно и так.
    Attachments
    msgbox.7z (7.37 KiB)
    19.03.2009
    Downloaded 384 times
  • чувствую, что скоро библиотекой можно будет пользоваться! :)

    IgorA
    не понимаю зачем в вызывающей прогремме нужно передавать структуру procinfo и массив thread? они в ней не используются. может как-нибудь перенести в библиотеку? да и экспорт библиотекой mb_text и mb_reinit немного нелогичный.
  • массив thread нужен для функции 51

    Code: Select all

    Функция 51 - создать поток
      * edx = указатель стэка потока (начальный esp)
    из структуры procinfo я определяю ширину окна (client_box.width), а исходя из ширины окна определяю отступ для рисования кнопок по центру окна.
    Хотя эту структуру можно и не давать указателем, а обьявить ее внутри msgbox.lib, но тогда размер библиотеки будет на 1Кб больше. Я решил что если приложение будет использовать структуру procinfo, то зачем ее дублировать 2 раза.
    Экспорт mb_text и mb_reinit сделал в расчете на то, что сообщение можно будет динамически изменять в процессе работы. Допустим программа что-то выполняет в несколько этапов ...
    При запуске выдала сообщение: Выполнено 0% [Закрыть][Прервать], прошло время и изменили надпись: Выполнено 30% [Закрыть][Прервать], и т. д., а потом : Выполнено все [Закрыть].
    Потому mb_text и mb_reinit выкинуты на всеобщее обозрение.
    Хотя возможно функцию mb_reinit стоит изменить, что-бы она принимала параметр mb_reinit через стек.
  • массив thread нужен для функции 51
    а создавать поток в mb_create не пробовал?
    тогда размер библиотеки будет на 1Кб больше
    это единственная причина? этот килобайт сожмётся kpack'ом до пары десятков байт. :)
    возможно функцию mb_reinit стоит изменить, что-бы она принимала параметр mb_reinit через стек
    ну это другое дело! :)
  • IgorA wrote:но тогда размер библиотеки будет на 1Кб больше.
    Да ну?
    Ушёл к умным, знающим и культурным людям.
  • Наконец-то попробовал! Выглядит интересно, багов не заметил.
  • Albom
    а создавать поток в mb_create не пробовал?
    Почему-то но не удалось :( , кроме того мне кажется, что если вдруг возникнет необходимость создать несколько сообщений, то нужно разные массивы для стеков давать. Потому оно пока из внешней программы передается.
    А mb_procinfo вкинул внутрь библиотеки.
    Сделал пример на функцию mb_reinit , но перерисовка окна сама не делается, нужно подвигать окно чтобы заметить изменение сообщения.
    Attachments
    msgbox.7z (7.4 KiB)
    20.03.2009
    Downloaded 356 times
    Last edited by IgorA on Sun Mar 22, 2009 10:55 pm, edited 1 time in total.
  • IgorA wrote: если вдруг возникнет необходимость создать несколько сообщений, то нужно разные массивы для стеков давать.
    можно спокойно динамически выделять 4 кила. вопрос только в том, когда эту память освобождать - не всё так просто. :)
  • Добавил в библиотеку msgbox функцию mb_setfunctions. Пример использования можно посмотреть в примере на 2-м сообщении на 3-й кнопке с надписью "Помощь".
    Смысл данной функции в том, что окну сообщения можно назначить функции на нажатие кнопок, т. е. сразу при нажатии на кнопку сообщения выполнится вызов функции по назначенному адресу. (Если адрес равен 0 то ничего не делается). Раньше планировалось в вызывающей программе анализировать какую кнопку нажали и по ней определять что делать, а теперь можно и так и по новому.
    Attachments
    msgbox3.7z (10.37 KiB)
    Downloaded 383 times
  • IgorA wrote:Добавил в библиотеку msgbox функцию mb_setfunctions
    Очень полезная функция. :) Код пока не смотрел, но пример работает здорово.

    Маленький вопросик: зачем выделять кнопки? (чёрным цветом)
  • зачем выделять кнопки? (чёрным цветом)
    Дело в том, что можно кнопками влево и вправо на клавиатуре выбрать нужную кнопку, и нажать потом enter для выбора. Т. е. можно не только мышкой на кнопку нажать, а и на клавиатуре. Потому возникает необходимость выделить кнопку, показать что она в фокусе. А черный цвет, это цвет текста который берется из системного скина. Если взять другой скин то эта кнопка может выглядеть и не черной.
  • А нельзя просто рисовать поверх кнопки прямоугольник с толщиной линии в 1 пиксел? Или (что было бы вообще здорово) 4 прерывистых линии?
  • Who is online

    Users browsing this forum: No registered users and 2 guests