IgorA
1) посмотри исходники console.obj
2) http://devotes.narod.ru/Books/3/ch05_02a.htm.
то, что нужно, начинается со слов "Для удобства ссылок на параметры, переданные в стеке".
правда, там код 16-разрядный.
! обрати внимание на ret 6.
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; тогда код вызова выглядит следующим образом:
При этом в момент начала выполнения func стек выглядит следующим образом:
Так что к переданным аргументам уже можно обращаться через esp со смещением. Это один из вариантов работы.
Есть и другой вариант. Работать с esp не всегда удобно, поскольку оно меняется при всяких push/pop и нужно соответственно добавлять 4*число заpushенных dwordов; кроме того, в 16-битном режиме адресации через sp не было вообще, а в 32-битном она хотя и есть, но занимает на байт больше (mov eax,[esp+4] на байт длиннее mov eax,[ebp+4]); кроме того, если процедура работает с постоянно меняющимся esp, то нельзя автоматически из внешнего кода раскрутить стек в поисках цепочки вызовов, приведших к текущему состоянию (есть и другие аспекты). Поэтому часто используется также адресация через ebp. Для этого в начало функции добавляется код
после чего стек принимает вид
В конце процедуры, естественно, нужно восстановить стек и старое значение ebp. Минусы такого стиля адресации заключаются в дополнительном коде пролога/эпилога процедуры и в потере одного регистра, который можно было бы задействовать для других целей.
В коде, приведённом ранее, отсутствует инициализация ebp, так что [ebp+N] указывает в никуда.
Пусть процедура вызывается как stdcall с тремя параметрами param0, param1, param2; тогда код вызова выглядит следующим образом:
Code: Select all
push param2
push param1
push param0
call func
label:
Code: Select all
[esp] = label ; на вершине стека находится адрес возврата, результат инструкции call
[esp+4] = param0 ; последнее запихнутое в стек значение, результат последнего push
[esp+8] = param1 ; предпоследнее запихнутое в стек значение, результат предпоследнего push
[esp+12] = param2
Есть и другой вариант. Работать с 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+N] указывает в никуда.
Ушёл к умным, знающим и культурным людям.
Учел то что сказали Albom и diamond, и сделал более новую версию библиотеки. Убрал ссылку на структуру mb_procinfo, потому что передаю ее в стеке.
Кроме того несколько изменений: улучшил работу с кнопками Влево и Вправо, окно размещается в центре экрана.
Описал в файле msgbox.asm все константы и переменные. Функция теперь stdcal потому думаю с ней все понятно и так.
Кроме того несколько изменений: улучшил работу с кнопками Влево и Вправо, окно размещается в центре экрана.
Описал в файле msgbox.asm все константы и переменные. Функция теперь stdcal потому думаю с ней все понятно и так.
- Attachments
-
-
msgbox.7z (7.37 KiB)
- 19.03.2009
Downloaded 387 times
-
чувствую, что скоро библиотекой можно будет пользоваться!
IgorA
не понимаю зачем в вызывающей прогремме нужно передавать структуру procinfo и массив thread? они в ней не используются. может как-нибудь перенести в библиотеку? да и экспорт библиотекой mb_text и mb_reinit немного нелогичный.
IgorA
не понимаю зачем в вызывающей прогремме нужно передавать структуру procinfo и массив thread? они в ней не используются. может как-нибудь перенести в библиотеку? да и экспорт библиотекой mb_text и mb_reinit немного нелогичный.
массив thread нужен для функции 51
из структуры procinfo я определяю ширину окна (client_box.width), а исходя из ширины окна определяю отступ для рисования кнопок по центру окна.
Хотя эту структуру можно и не давать указателем, а обьявить ее внутри msgbox.lib, но тогда размер библиотеки будет на 1Кб больше. Я решил что если приложение будет использовать структуру procinfo, то зачем ее дублировать 2 раза.
Экспорт mb_text и mb_reinit сделал в расчете на то, что сообщение можно будет динамически изменять в процессе работы. Допустим программа что-то выполняет в несколько этапов ...
При запуске выдала сообщение: Выполнено 0% [Закрыть][Прервать], прошло время и изменили надпись: Выполнено 30% [Закрыть][Прервать], и т. д., а потом : Выполнено все [Закрыть].
Потому mb_text и mb_reinit выкинуты на всеобщее обозрение.
Хотя возможно функцию mb_reinit стоит изменить, что-бы она принимала параметр mb_reinit через стек.
Code: Select all
Функция 51 - создать поток
* edx = указатель стэка потока (начальный esp)
Хотя эту структуру можно и не давать указателем, а обьявить ее внутри msgbox.lib, но тогда размер библиотеки будет на 1Кб больше. Я решил что если приложение будет использовать структуру procinfo, то зачем ее дублировать 2 раза.
Экспорт mb_text и mb_reinit сделал в расчете на то, что сообщение можно будет динамически изменять в процессе работы. Допустим программа что-то выполняет в несколько этапов ...
При запуске выдала сообщение: Выполнено 0% [Закрыть][Прервать], прошло время и изменили надпись: Выполнено 30% [Закрыть][Прервать], и т. д., а потом : Выполнено все [Закрыть].
Потому mb_text и mb_reinit выкинуты на всеобщее обозрение.
Хотя возможно функцию mb_reinit стоит изменить, что-бы она принимала параметр mb_reinit через стек.
а создавать поток в mb_create не пробовал?массив thread нужен для функции 51
это единственная причина? этот килобайт сожмётся kpack'ом до пары десятков байт.тогда размер библиотеки будет на 1Кб больше
ну это другое дело!возможно функцию mb_reinit стоит изменить, что-бы она принимала параметр mb_reinit через стек
Да ну?IgorA wrote:но тогда размер библиотеки будет на 1Кб больше.
Ушёл к умным, знающим и культурным людям.
Наконец-то попробовал! Выглядит интересно, багов не заметил.
Albom
А mb_procinfo вкинул внутрь библиотеки.
Сделал пример на функцию mb_reinit , но перерисовка окна сама не делается, нужно подвигать окно чтобы заметить изменение сообщения.
Почему-то но не удалось , кроме того мне кажется, что если вдруг возникнет необходимость создать несколько сообщений, то нужно разные массивы для стеков давать. Потому оно пока из внешней программы передается.а создавать поток в mb_create не пробовал?
А mb_procinfo вкинул внутрь библиотеки.
Сделал пример на функцию mb_reinit , но перерисовка окна сама не делается, нужно подвигать окно чтобы заметить изменение сообщения.
можно спокойно динамически выделять 4 кила. вопрос только в том, когда эту память освобождать - не всё так просто.IgorA wrote: если вдруг возникнет необходимость создать несколько сообщений, то нужно разные массивы для стеков давать.
Добавил в библиотеку msgbox функцию mb_setfunctions. Пример использования можно посмотреть в примере на 2-м сообщении на 3-й кнопке с надписью "Помощь".
Смысл данной функции в том, что окну сообщения можно назначить функции на нажатие кнопок, т. е. сразу при нажатии на кнопку сообщения выполнится вызов функции по назначенному адресу. (Если адрес равен 0 то ничего не делается). Раньше планировалось в вызывающей программе анализировать какую кнопку нажали и по ней определять что делать, а теперь можно и так и по новому.
Смысл данной функции в том, что окну сообщения можно назначить функции на нажатие кнопок, т. е. сразу при нажатии на кнопку сообщения выполнится вызов функции по назначенному адресу. (Если адрес равен 0 то ничего не делается). Раньше планировалось в вызывающей программе анализировать какую кнопку нажали и по ней определять что делать, а теперь можно и так и по новому.
- Attachments
-
-
msgbox3.7z (10.37 KiB)Downloaded 387 times
-
Очень полезная функция. Код пока не смотрел, но пример работает здорово.IgorA wrote:Добавил в библиотеку msgbox функцию mb_setfunctions
Маленький вопросик: зачем выделять кнопки? (чёрным цветом)
Дело в том, что можно кнопками влево и вправо на клавиатуре выбрать нужную кнопку, и нажать потом enter для выбора. Т. е. можно не только мышкой на кнопку нажать, а и на клавиатуре. Потому возникает необходимость выделить кнопку, показать что она в фокусе. А черный цвет, это цвет текста который берется из системного скина. Если взять другой скин то эта кнопка может выглядеть и не черной.зачем выделять кнопки? (чёрным цветом)
А нельзя просто рисовать поверх кнопки прямоугольник с толщиной линии в 1 пиксел? Или (что было бы вообще здорово) 4 прерывистых линии?
Who is online
Users browsing this forum: No registered users and 2 guests