Локальная переменная в макросе

Тема в разделе "WASM.ASSEMBLER", создана пользователем Tupo, 26 янв 2005.

  1. Tupo

    Tupo New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2005
    Сообщения:
    69
    Адрес:
    Moscow
    Забыл важный коммент:

    По значению поля type определяется какой член из списка используется.



    Это условие в нашем случае(попытка заполнения структуры через push) не так важно, потому что известно каков конечный вид структуры.



    Вот я и привел в пример самый "фатальный" - byte+dword+word, то есть type+pszVal+cchVal



    Проще метода, чем вычитание выровненной длины из esp((длина shr 2) * 4) и последующее заполнение через мувы, я не нашел.



    Будут варианты? ;)
     
  2. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Tupo >




    Не вижу ничего общего между DBVARIANT и SSS (кроме одинаковых названий полей) - расположение в памяти различное.



    #pragma pack не приведена, видимо это будет выглдадеть так:
    Код (Text):
    1.  
    2. name - offset - size
    3. type    +0        1
    4.  
    5. bVal    +4        1
    6. cVal    +4        1
    7.  
    8. wVal    +4        2
    9. sVal    +4        2
    10.  
    11. dVal    +4        4
    12. lVal    +4        4
    13.  
    14. pszVal  +4        4
    15. cchVal  +8        2
    16.  
    17. cpbVal  +4        2
    18. pbVal   +8        4


    Какие проблемы с помещением значений в стэк push'ами ?

    Все аргументы можно рассматривать как dword и всё... правда при этом masm не сможет проверять размер, и не ясно как быть с командами вроде "push al"... это в fasm можно просто переопределить макрос push и он будет делать push eax ;)
     
  3. Tupo

    Tupo New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2005
    Сообщения:
    69
    Адрес:
    Moscow




    Как же лихо ты сделал всё кратное 4 ;)



    Думаю, легче от того не станет, если я скажу, что #pragma pack(1) ;)



    Я же привел в пример именно эту структуру, так как с ней уже работал. И меня особо не волновало "как-там-у-них-в-MSVC" - я ж её в асме обрабатываю. ;)



    Так что правильные смещения такие:
    Код (Text):
    1. name - offset - size
    2. type    +0        1
    3.  
    4. bVal    +1        1
    5. cVal    +1        1
    6.  
    7. wVal    +1        2
    8. sVal    +1        2
    9.  
    10. dVal    +1        4
    11. lVal    +1        4
    12.  
    13. pszVal  +1        4
    14. cchVal  +5        2
    15.  
    16. cpbVal  +1        2
    17. pbVal   +3        4
     
  4. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Tupo

    любую структуру можно сформировать на стэке методом S_T_A_S_ независимо от выравнивания её членов. Кстати так ещё и автоматически поддерживается необходимое выравнивание стэка.

    Конечно push тогда не всегда будет соответствовать инициализации отдельного члена структуры.



    Можно и комбинированным методом в конце концов...
     
  5. Tupo

    Tupo New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2005
    Сообщения:
    69
    Адрес:
    Moscow
    green

    Приведи пример, плз.
     
  6. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Код (Text):
    1.  
    2. #pragma pack(1)
    3. typedef struct
    4. {
    5.     BYTE type;
    6.     struct
    7.     {
    8.         WORD cpbVal;
    9.         BYTE *pbVal;
    10.     };
    11. };
    12. } DBVARIANT_SIMPLIFIED;
    13.  
    14.  
    15. void __stdcall SomeAPIFunc(DBVARIANT_SIMPLIFIED *pdbv);
    16.  
    17. // {{ MASMed snippet
    18. void sample()
    19. {
    20.     DBVARIANT_SIMPLIFIED dbv = {1, {2, 0x12345678}};
    21.     SomeAPIFunc(&dbv);
    22. }
    23. //}}
    24.  
    25. ----------------------------------------------------------------------  -----------
    26.  
    27. sample proc
    28.     push 00123456h
    29.     push 78000201h
    30.     push esp
    31.     call SomeAPIFunc
    32.     add esp, 08h
    33.     ret
    34. sample endp
    35.  
     
  7. Tupo

    Tupo New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2005
    Сообщения:
    69
    Адрес:
    Moscow
    Эт-понятно.

    Срезать/переносить байты я умею. ;)



    Проблема в другом:

    В отличие от твоего примера на С, пример на асме абсолютно НЕчитаем.



    Когда такую структуру заполняешь раз 10-15 в разных участкх программы, то вручную осуществлять такую оптимизацию слишком накладно!



    Проще и нагляднее:
    Код (Text):
    1. @StructSize macro   StructName
    2. if (sizeof StructName and 3)
    3.         EXITM   %((sizeof StructName shr 2) + 1) * sizeof DWORD
    4. else
    5.         EXITM   %sizeof StructName
    6. endif
    7.         endm
    8.  
    9.  
    10. sample  proc
    11.     sub esp, @StructSize(DBVARIANT_SIMPLIFIED)
    12.     mov BYTE PTR [esp+DBVARIANT_SIMPLIFIED.btype], 1
    13.     mov WORD PTR [esp+DBVARIANT_SIMPLIFIED.cpbVal], 2
    14.     mov DWORD PTR [esp+DBVARIANT_SIMPLIFIED.pbVal], 12345678h
    15.     push    esp
    16.     call    SomeAPIFunc
    17.     add esp, @StructSize(DBVARIANT_SIMPLIFIED)
    18.     ret
    19. sample  endp




    P.S. Подправил малость код
     
  8. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Ну, думаю можно это дело макросами облегчить как-то...



    А вообще, IMHO, читабельность и эффективность кода на асме - взаимоисключающие критерии.

    Для достижения приемлемого компромисса компилятор должен быть оптимизирующим.



    Многие "читабельные" программы на асме не лучше кода сгенерированного скажем MS VC с отрубленной оптимизацией.

    :-(
     
  9. Tupo

    Tupo New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2005
    Сообщения:
    69
    Адрес:
    Moscow




    Это не выход.

    Оптимизация кода - вещь хорошая, но для программ на ассемблере ненужная. ;)

    Оптимизировать нужно не код, а алгоритм.



    Оптимизация кода осуществляется только в критичных участках программы.



    Вот оптимизатор алгоритмов - вещь нужная, ибо в подавляющем большинстве случаев(из моей личной практики) производительность программы значительно повышается за счет оптимизации алгортма этой программы.



    Кстати, на wasm.ru нет ни одной статьи о программах, которые позволяют удобно и быстро рисовать алгоритмы ;)



    Возможно потому что настоящий генерал дзена "держит-алгоритм-в-голове" :Р
     
  10. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine


    Гм... можно тогда узнать, почему ты выбрал MASM в качестве среды программирования ?





    И мы ведь о построении кода говорим, а не алгоритма, так ведь ?



    Я просто имел ввиду, что повышение читабельности ассемблерного кода почти всегда приводит к понижению качества результирующего бинарного кода и наоборот. Это обратная сторона полного контроля над генерируемым кодом, который дает асм - сильная связь между исходным и бинарным кодом.

    Оптимизирующий компилятор ослабляет эту связь, давая возможность программисту выразить алгоритм в более читабельном коде, сохраняя приемлемую эффективность. Конечно за счет снижения контроля над бинарным кодом.



    То есть IMHO на асме стоит писать в том случае, если главный критерий -- эффективность кода.

    А если на первом месте - читабельность, сопровождаемость, масштабируемость и т.п., то думаю следует писать на С/С++.

    Лично я предпочитаю смешанный вариант.
     
  11. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Tupo >




    Я изходил из приведённого кода, разве я ошибся?





    green >




    на fasme так можно:
    Код (Text):
    1.  
    2. macro  PUSH_DBVARIANT_SIMPLIFIED type, cpbVal, pbVal
    3. {
    4.        local  .type, .cpbVal, .pbVal
    5.        local  .dword1, .dword2
    6.        ; можно добвить условную компиляцию
    7.        ; if  type =
    8.        virtual at 0
    9.            .type        db type
    10.            .cpbVal      dw cpbVal
    11.            .pbVal       dd pbVal
    12.                         dd 0
    13.  
    14.            load   .dword1 dword from 0
    15.            load   .dword2 dword from 4
    16.        end virtual
    17.  
    18.        push .dword2 .dword1
    19. }
    20.  
    21. ; используем
    22.        PUSH_DBVARIANT_SIMPLIFIED 1, 2, 0x12345678
    23.  
    24. ; fasm rulezzz:
    25. 68 56341200   push    123456
    26. 68 01020078   push    78000201
     
  12. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    S_T_A_S_

    класс!



    я бы тоже на fasm перешёл... но AFAIK он плохо согласуется со средствами разработки от MS: нет H2INC, развитой командной стоки, генерации debug info...
     
  13. Tupo

    Tupo New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2005
    Сообщения:
    69
    Адрес:
    Moscow
    S_T_A_S_

    прмоединяюсь к green'у - супер!



    Наконец-то(на третьей странице топика) ты написал то, что обещал в самом начале топика ;)



    Как говорится - вопрос исчерпан.



    Надо будет глянуть что за зверь этот flat assembler.



    Меня такие нюансы как green'а не останавливают:

    1. h2inc - не использую.

    Ибо 7 потов сойдет, пока устранишь все места в хедере, которые не нравятся этой утилите. Плюс, в конце концов, h2inc скажет тебе, что добрую половину хэдера он не смог перевести. ;)

    По мне быстрее вручную конвертнуть.

    И имея столь печальный опыт общения с h2inc, выработался стиль: к каждому проекту делаю "кастом"-инклуды, хоть это и занимает немного дополнительного времени, зато вспомнишь все нюансы использования функций, участвующих в проекте ;)

    2. debug info - не использую.

    Так как быстрее и эффективнее прогу отлаживать в отладчике.

    Под 98ой пользовал SoftIce, но когда переехал на XP оказалось что для моих нужд достаточно OllyDbg ;)



    green



    Раньше я использовал связку MASM+Basic - в MASM'e писал программы, а в Бейсике отлаживал алгоритмы тех самых критичных мест - например, алгоритм расшифровки/шифровки блока данных.

    Затем я стал использовать MASM+MSVC98 - приоритеты те же самые. Плюс VC помог мне понять оконный механизм винды(под Win3.11 оконных приложений не писал).



    Сейчас, когда MSVC98 под XP не поставить, я использую связку MASM+PHP - приоритеты те же.

    (Был коротенький этап - использовал яву, в качестве второго языка. Но быстро утомило неимоверное количество классов)



    Главная причина использования MASM'а - не люблю, когда в конечном коде появляются куски кода, которые я не писал ;)







    Я хотел сказать, что занесение push'ами структуры в стек - это ненужная оптимизация, так как прирост производительности программы от такой оптимизации очень незначительный!

    Оптимизация всего кода достаточно эффективна в HLL.

    Для программы на ассемблере - её нужно использовать выборочно, хотя бы потому что есть возможность использовать её выборочно ;)

    Оптимизация алгоритма - очень эффективный прием повышения производительности для программ на асме, а для програм на HLL - этот приём эффективен втройне.
     
  14. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    green >




    fasm может делать ms coff - мне этого достаточно.



    Параметры командной строки отсутствуют - это идеология fasm! Да и к чему она там? тип выходного файла определяется директивой format, что ещё нужно от ассемблера...



    С debug info это проблема всех трансляторов, т.к. формат pdb закрыт :-(

    но fasm может делать листинг, и из него можно получить практически всё что угодно (даже тот же pdb)

    Кстати, можно просто экспортировать нужные метки - тогда Olly "имена" для всего, что есть в секции экспорта.



    H2INC никогда не использовал и в masm - толку от неё мало на сложных файла. Кто-то использует perl, но можно и ручками конвертить.

    IMHO хорошо бы сразу .h файлы скармливать ассемблеру научаться, но это требует изменения самого синтаксиса ассемблера.





    Tupo >




    Ну это не совсем то, вернее совсем не то, да и доходит до меня долго :))))



    >




    Скорее прироста как раз не будет, только объём меньше, зато уменьшается вероятность ошибок вроде 2х mov в одно место :)
     
  15. Tupo

    Tupo New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2005
    Сообщения:
    69
    Адрес:
    Moscow




    Ну-да, сумбурно всё как-то получилось.

    На самом деле меня интересовало:

    1. Объявление и использование стековой структуры(спросил про переменную, так как у неё формат проще)...

    2. ...в макросе...

    3. ...при условии, что поля её имеют разный размер.



    Ранее ты сказал(и показал), что fasm без труда собирает все стековые переменные, объявленные в разных местах процедуры, в один кадр.

    А сейчас привел пример объявления и использования структуры с полями различной длины в макросе.

    Из примера видно, что выдержана и наглядность и оптимальность кода одновременно.



    Так что твой ответ, как говорится, прямо в десятку!



    Дело за малым - переехать на fasm ;)