Привет всем! Предлагаю использовать этот топик для обмена опытом по работе с RadASM. Теперь к делу. RadASM, при работе с листингом, позволяет Вам скрывать и раскрывать содержимое некоторых конструкций. К таким конструкциям относятся секции, процедуры, ветвления, описание структур и т.д. В общем, это очень удобная фича! Огромное спасибо KetilO за то, что он сделал это! К сожалению, она далека от совершенства, и, IMHO, имеет свои недостатки. Перечислю их: 1. В основном, она ориентирована на HLL-конструкции, и почти бесполезна в листинге, написанном на “чистом” ассемблере; 2. Стандартные блоки для секций имеют врожденный дефект, который в некоторых случаях не позволяет программе корректно определить нижнюю границу таких блоков. Возьмем, к примеру, следующий листинг (в скобках указанны номера строк): (1) ...... (2) literal MACRO quoted_text:VARARG (3) LOCAL local_text (4) .data (5) local_text db quoted_text, 0 (6) .code (7) EXITM <local_text> (8) ENDM (9) (10) SADD MACRO quoted_text:VARARG (11) EXITM <ADDR literal(quoted_text)> (12) ENDM (13) ;----------------------------------------------------- (14) (15) PART STRUCT (16) OnePart DWORD ? (17) TwoPart DWORD ? (18) TreePart DWORD ? (19) PART ENDS (20) .data (21) ...... (22) .data? (23) ...... если попытаться свернуть блок, начало которого находится в стр. 6, то программа вместо того, чтобы скрыть только стр. 7 скроет строки 7-19… Я говорил KetilO об этом баге, на что он признался что с этим трудно что-нибудь сделать. И судя по всему, ничего сделано и не будет; 3. Не обладает достаточной гибкостью. К примеру, она не позволит Вам просмотреть отдельные ветви в многовариантной конструкции IF-ELSEIF-ELSE-ENDIF. Это БОЛЬШОЙ минус. 4. Мне хотелось бы иметь возможность объединять в блок произвольную группу соседствующих операций. Вообще-то, такая возможность есть (Format->Hide selected lines), но ее реализация лично меня абсолютно не устраивает по следующим причинам (перечислю их в порядке серьезности): a)Созданные блоки не сохраняются, т.е. в следующем сеансе работы придется делать все заново… А ведь таких блоков может быть очень много… b)Если в тело такого блока добавить новую строку, то строка бывшая до этого в нем последней выйдет за его пределы наружу… c)Есть проблема с определением границ блока при его создании. Если выделить группу строк и попытаться объединить их в блок, то в этот блок не попадет первая и последняя строка выделенной группы. Вообще-то, я говорил KetilO об этих недостатках, и он обещал исправить их. Но, это было, кажется, еще прошлой зимой, а “воз и ныне там”… 5. И напоследок, еще одна очень неприятная вещь. Она касается тех, кто при работе с листингом пользуется режимом разделения окна (split). Если при работе в этом режиме в одном из окон Вам потребуется свернуть или развернуть большой блок строк, а во втором окне будет в это время отображаться та часть листинга, которая находится ниже этого блока, то после манипуляции с этим блоком содержимое второго окна будет сдвинуто и Вам придется снова искать нужное место… Когда я сказал об этом KetilO, он не согласился признать это багом И сказал, что не будет возиться с такой мелочью. Я хочу предложить Вам один очень простой способ для решения проблем 1,2,3 и 4 (далее я буду считать, вы пользуетесь MASM32). Для этого открываем файл masm.ini, который находится в той директории, куда установлен RadASM, и ищем в нем секцию [CodeBlock]. Обычно эта секция выглядит так: [CodeBlock] 1=$ proc,? endp,,,6 2=.if,.endif,.elseif,.else,0 3=.while,.endw,.break,,0 4=$ struct,? ends,,,6 5=$ struc,? ends,,,6 6=$ macro,endm,,,14 7=.data,,,,16 8=.data?,,,,16 9=.const,,,,16 10=.code,,,,16 11=BEGIN,END,,,0 Именно здесь определены все стандартные блоки… Фишка в том, что мы можем добавить сюда определение для СВОЕГО блока, например, добавив в конец этой секции строку: 12=;{,;},,,0 мы получаем возможность определять любые блоки строк, в листинге, просто добавив в их начало и конец строки: “;{“ и “;}”. Например: Код (Text): invoke GetProcessHeap .if eax != NULL ;{ mov hHeap, eax ;} .else ;{ invoke HandleError, hWin, SADD("Не удалось получить хэндл heap'à процесса.") invoke EndDialog, hWin, 0 ;} .endif в данном примере можно просматривать только одну ветвь ветвления, в то время как другая при этом может быть свернута… Вот еще один пример: ;{ mov eax, wParam mov edx, eax shr edx, 16 and eax, 0FFFFh ;} в котором в блок объединены строки, содержащие “чисто” ассемблерный код. Причем, обратите внимание на то, что в следующем сеансе работы с этим проектом, определенные Вами блоки никуда не исчезнут Для решения проблемы №2 Нам придется отказаться от использования стандартных блоков для секций. Для этого удаляем в вышеуказанной секции следующие строки: 7=.data,,,,16 8=.data?,,,,16 9=.const,,,,16 10=.code,,,,16 После этого, определять блоки секций можно вручную, используя для этого предложенный мной способ. Обратите внимание на то, что в [CodeBlock] у каждого описания блока есть свой номер (он стоит перед знаком “=”). Первоначально номера всех описаний последовательно увеличиваются с шагом в единицу. Поэтому, если вы вносите в эту секцию какие-то изменения (добавляете или удаляете описания), то не забывайте следить за правильностью нумерации. Этот способ можно использовать как совместно со стандартными блоками, так и монопольно, удалив (или закомментировав) описания всех стандартных блоков. Можно также выбрать золотую середину. Я, к примеру, предпочитаю удалять, наряду с описаниями блоков для секций, описание для блоков конструкций “ветвление”. Вот и все. Как видите, в этом нет ничего сложного. Надеюсь это сделает вашу работу с RadASM более комфортной.
Да, проходили такое. Если пишешь на чистом асме половины проблем не будет, если пишешь еще и на фасме, то не будет почти всех проблем. У меня в коде нет понятия "процедура" с синтаксической точки зрения. Я пользуюсь метками Но я не робот, и человеческое мне не чуждо. Поэтому захотелось мне чтобы мои процедуры тоже коллапсировались. Строчка 7=$ :,ret,,,2 частично решила проблему, но при этом накладываются некоторые ограничения. Во-первых, необходимо двоеточие после имени функции отодвигать на пробел. Это сделано для того, чтобы глупый радасм не пытался сворачивать все метки, какие видит. Во-вторых, как вы, наверное, заметили, свертка идет до первой инструкции ret. Но если где-то посреди кода функции есть досрочный возврат... Вторую проблему можно, конечно решить наложением ограничений на структуру функций, но не для того мы на асме программируем, чтобы самим себе клетки строить, не так ли? Поэтому немного помедитировав, я пришел к выводу, что все суета и заменил свою строчку на 7=$ :, :,,,2 Эта строчка выделяет название функции кнопкой свертки и строкой над именем. Но при этом функция сворачиваться не будет. Ну и ладно. Не очень-то и хотелось. Зато каждая функция выделена и ее хорошо видно. Правда, до этих извращений я выделял функции коментсами вида ; ===================================================== Это был разделитель между однородными функциями. Между логическими блоками ставилось две таких строки. Достаточно удобно. Лично я в таком коде запутаться не мог. Вот такие пироги с котятами. Сейчас еще поковыряюсь в направлении свертки.
Еще немного помедитировав, строчка 7=$ :, :,,,2 была заменена на 7=$ :, :,,,18 Поясню. Теперь каждая метка вида label : считается секцией и свертка происходит до следующей подобной метки или до конца файла. Также добавились строчки 6=@@,$ @B,,,8 7=$ @F,@@,,,8 для коллапсинга блоков анонимных меток. Правда, строка 6 не работает почему-то.. Ну и я не уверен, что это будет удобно. Поэтому добавил, посмотрел и закоментарил до лучших времен. ЗЫ: а я вот подумал: а что если попробовать скрестить РадАсм и С++? Сотоварищи явушники лопнут от зависти. Найду свободный часик - попробую.
Частное мнение о коллапсинге: вещь (на мой взгляд) бесполезная. Что представляют из себя свернутые процедуры? По сути дела, просто дублируется список процедур, уже имеющийся в правом окошке. Навигация не упрощается, т.к. в том же правом списке найти процедуру и кликнуть её проще, чем найти и развернуть свернутую процедуру в основном поле IDE. Имхо.
cresta Ну-ну. Коллапсинг процедур это только частный случай коллапсинга. Если ты считаешь, бесполезным его применение для процедур то так и скажи. Зачем же обобщать? К тому же обрати внимание на то, что процедуры это по сути HLL-конструкции и мы вполне сможем обойтись без них. Если перестать использовать HLL-конструкцию "proc" в программе, то чего будет стоить список процедур имеющийся в правом окошке? IMHO, он станет бесполезен... Чрезмерная ориентация RadASM на HLL-конструкции это скорее плохо чем хорошо (если только его нельзя от этого отучить)… И кстати, как я уже говорил выше, предложенный способ повышения гибкости коллапсинга позволяет использовать этот механизм в “чисто” ассемблерном листинге. З.Ы.: У меня сложилось сильное впечатление, что ты не читал мой предыдущий пост… Жаль.
Ну так и написано же всё применительно к процедурам )) Зачем же ещё отдельными словами подтверждать? Что касается поста, то читал Тот "баг",: можно обойти очень просто, по крайней мере применительно к процедурам: после ret в конце процедуры вставить ещё раз .code. И коллапс будет закончен именно в конце процедуры, и не будет распространяться ниже по листингу. Попробуй Правда, не вижу в этом необходимости, по причине, оговоренной выше, но вот такой способ существует. Очень возможно, что и для макросов это справедливо (макросы предпочитаю не использовать, поэтому не проверял)
cresta Ну, значит, это я недостаточно четко выразил свои мысли. Основной акцент, в том посте, я делал на повышении гибкости коллапсинга реализацией реальной возможности объединять произвольной группы соседних инструкций в коллапсирующийся блок... Именно это позволяет использовать коллапсинг в листинге с "чистым" ассемблерным кодом. Далее я показал, как эту же возможность можно использовать для повышения гибкости коллапсинга HLL-конструкции "ветвление" (if-elseif-else-endif). Это тоже очень удобно. А о HLL-процедурах я упоминал только вскользь, когда перечислял стандартные коллапсирующиеся конструкции...
cresta "Что представляют из себя свернутые процедуры? По сути дела, просто дублируется список процедур, уже имеющийся в правом окошке." Правильно, у нас есть несколько способов выполнить одно и тоже действие (обычная избыточность для Win32-приложений). Какой из этих способов выбрать зависит вкуса и конкретной ситуации. И вообще, это хорошо когда есть выбор... А что касается коллапсинга HLL-процедур, то его можно использовать, или не использовать, но улучшать там, IMHO, нечего (итак все нормально работает), поэтому я и не стал особо затрагивать их в своем посте.
А не приведёт это к тому, что больше времени уйдёт на коррекцию masm.ini, чем на написание собственно кода? Ведь произвольных начал, концов, размеров блоков достаточно большое количество. Может есть способ автоматом вставить в листинг своеобразные теги, например *StartCollapce* - *EndCollapce* и оговорить их в .ini? Естественно, чтобы для компилятора они были невидимыми. Думаю, тут действительно будет гибкость, практически абсолютная
Я сделал так: определил свои начало и конец блока ;beg ;endb и использую их в основном дли того что бы выделять обработчики сообщений. Вот здесь как раз очень удобно т.к. можно видеть какие сообщения обрабатываются практически на одной странице (ну +- немного).
Для примера: Код (Text): ;<< some block ... ;>> [end of some block] Что в квадратных скобках, можно и не писать. А вообще, проблемы с коллапсингом возможно (на 100% не уверен) решить с помощью плагинов.
cresta А разве нельзя пользоваться вегда только одним вариантом начало-конец коллапсирующегося блока? Нужно просто добавить ограничители (";{" и ";}") в нужные места...
IceStudent Наверно можно, но, сколько для этого потребуется трудозатрат? IMHO, немало... А предложенный способ использует уже существующий механизм коллапсинга и реализуется очень быстро и просто.
Прикрутить С++ к РадАсму удалось без всяких проблем. Пока, правда, еще не очень хорошо получилось, но я над этим работаю. Во всяком случае, прога спокойно компилится и линкуется. Правда, надо еще продумать коллапсинг, цветовая раскраска тоже пока отсутствует. Но начало положено.
А теперь о грустном. Как отлаживать прогу в радасме я не представляю. Оля - это, конечно, хорошо, но так как в большинстве моих задач на С++ используется crt, то Олей отлаживать очень неудобно. Особенно если еще и ООП используется.. Надо думать.
n0p Ну как... Писать Addin, сабклассить RaEdit (чтобы бряки расставлять), а Addin будет перед компиляцией добивать перед брякнутыми строками __asm int3, отображать значения регистров, отлавливать исключения, выводить отладочные сообщения. И еще обратить внимание на пару тысяч тонкостей отладки вообще, и отладки сишного кода в частности, о которых я и не подозреваю. imho, овчинка не стоит свеч. Это во всяком случае не на неделю.
Arvensis Не, это задача не этой пятилетки. Пока я склоняюсь к тому, что хорошо бы было обнаружить внешний дебагер сишного кода. Добавлено: ЗЫ: А бряки в РадАсме уже реализованы, только не знаю как работают. Клавосочетание Alt+F8.
;If you are doing source code breakpoints, this file must be included. ;You don't need it with int 3 breakpoints. include C:\masm32\radasm\masm\inc\radbg.inc И брякает исправно (ну и соотв.Alt+F8 на строке)