Несколько технических вопросов по ассемблеру

Тема в разделе "WASM.BEGINNERS", создана пользователем net_name, 3 сен 2009.

  1. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    т.е. масм генерирует call offset32 и по offset32 размещает jmp relative (если конечно не ошибаюсь насчет relative, но вроде было так, проверять влом, если нет то jmp offset32)
     
  2. delphi_jedi

    delphi_jedi New Member

    Публикаций:
    0
    Регистрация:
    21 фев 2009
    Сообщения:
    8
    редактирование было да всплыло... кто-нибудь знает почему?
     
  3. net_name

    net_name New Member

    Публикаций:
    0
    Регистрация:
    3 сен 2009
    Сообщения:
    25
    так я потом написал, что не понял что за прыжок такой...
    Пока для меня наверное сложно понять, но как я представляю, если например в проге используется функция, например API (MessageBox) код которой расположен в user32, то в программе должен быть организован переход на библиотеку котороя находится в памяти (грузится при загрузке системы) Это правильное представление?

    +1
     
  4. IceT

    IceT IceT

    Публикаций:
    0
    Регистрация:
    13 авг 2009
    Сообщения:
    233
    Адрес:
    RU
    Да, это происходит благодоря таблице импорта, которую заполняет загрузчик. Читай про формат ПЕ и все станет ясно.
     
  5. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    net_name
    да. но на масм по другому не получится (если юзать прямые способы, про кривые (мануальные) см http://www.wasm.ru/forum/viewtopic.php?id=20506). но можно и так
    call rel32@user32.MessageBoxA. кстати, что масм выигрывает от связки call+jmp не понятно.
     
  6. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    ну или call [mem32] а уже по mem32 в импорте расположить адрес user32.MessageBoxW
     
  7. net_name

    net_name New Member

    Публикаций:
    0
    Регистрация:
    3 сен 2009
    Сообщения:
    25
    Но можно и без таблицы импорта путём динамической подгрузки с диска...
    А эти системные длл всегда по фиксированным адресам в памяти находятся?
     
  8. IceT

    IceT IceT

    Публикаций:
    0
    Регистрация:
    13 авг 2009
    Сообщения:
    233
    Адрес:
    RU
    Это уже твое дело.

    Почти всегда, но совсем не обязательно.
     
  9. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    net_name
    это зависит от версии винды. в каждом билде могут адреса отличаться
     
  10. IceT

    IceT IceT

    Публикаций:
    0
    Регистрация:
    13 авг 2009
    Сообщения:
    233
    Адрес:
    RU
    Вообще-то память по адресам, куда грузятся либы проецируется на все процессы в системе, чтобы избежать избыточных копий. Но это прозрачно для процесса, а адреса отличаются в зависимости от сборки, да.
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    IceT
    Первое утверждение не верно.
    Многие модуля имеют фтксированные базы во всех процессах, например ядро мапит ntdll по фиксированному адресу, User32 также не может быть загружена по другому адресу, ибо например подсистема заполняет при запуске некоторые системные таблицы(pfnClientArray etc.) в ядре адресами обработчиков в этом модуле, адреса эти глобальны в системе.
     
  12. IceT

    IceT IceT

    Публикаций:
    0
    Регистрация:
    13 авг 2009
    Сообщения:
    233
    Адрес:
    RU
    Угу. Просто сначала я говорил про _все_ системные модули, и имелось ввиду, что самые "важные" по фикс. адресам, остальные - не обязательно, хоть и часто по одинаковым адресам. Прсто выразился не удачно.
     
  13. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    IceT
    Ну и различаться они могут не только в зависимости от сборки, но и с каждой новой загрузкой системы.
    Clerk
    Может. Работать может и не будет, но загрузитьcя может, если, например, адрес загрузки уже занят другой dll.
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    l_inc
    Я имел ввиду чтоб работала после загрузки нормально. Процесс выпадет наверно на сепшине, ибо шадов будет передавать управление вникуда.
     
  15. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Clerk
    Ну хоть DllMain отработает. А дальше её можно и не использовать. :) Вот и будет user32 в АП, но по другому адресу.
    P.S. Шудко, конечно.
     
  16. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    l_inc
    ага. да и вообще из адресного пространства удалить. фигли она место отнимает у проги!!! ;)
     
  17. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.708
    Повторюсь, длина инструкции call _imp__foo - 6 байт, call foo - 5 байт, jmp _imp__foo - 6 байт, составляем уравнение n*6 > n*5 + 6 --> отсюда мораль, если foo требуется вызвать 6 и менее раз программа с call _imp__foo будет короче, в противном случае (более 6 раз вызвать foo) используйте call foo и jmp _imp__foo. Правда, если в одном месте требуется несколько раз вызвать API-функцию с разными параметрами (например, SendMessage), а использовать цикл затруднительно, тогда можно использовать следующую конструкцию: lea esi,_imp__foo (6 байт), а затем несколько раз вызвать call dword ptr [esi] (2 байта). Вместо esi можно использовать edi, ebx, ebp по вкусу :)
    А вообще-то была тема можно ли избавиться от переходников call __foo; __foo: call [foo]
     
  18. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Mikl___
    стоп
    если у нас имеется 2 функции
    MessageBox и вызывается 8 раз
    ExitProcess и вызывается 1 раз
    то call MessageBox + jmp [user32.MessageBoxA] + call ExitProcess + jmp [kernel32.ExitProcess] = 8*5+6+1*5+6 = 57 байт
    или call [user32.MessageBox] + call [kernel32.ExitProcess] = 8*6+6 = 54 байта
    т.е. не все api функции вызываются столь часто и большинство вызывается единожды. отсюда вопрос
    что мы выигрываем от такого подхода.
     
  19. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.708
    max7C4
    Может быть я не очень понятно написал, но если ExitProcess вызывается 1 раз, то он и должен вызываться через call _imp__ExitProcess@4 (1*5+6=11>1*6), а вот MessageBox вызывается 8 раз и, с точки зрения уменьшения размера, его имеет смысл вызвать через связку call MessageBox + jmp [user32.MessageBoxA], так как 8*5+6=46 байт это меньше, чем 8*6=48 байт и эта разница будет тем заметнее, чем большее количество раз мы будем вызывать MessageBoxA
     
  20. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.615
    Адрес:
    Russia
    net_name
    зачем вам максимум оптимизации на программе здравствуй мир ???

    современная технология разработки предпочитает компромиссный вариант оптимизации напрвленный на повторное использование

    max7C4
    имхо call + jmp - для того чтоб если перетряхнуть всякие там kernel32.dll можно былобы сохранить работоспособность программ для прошлой версии

    ну а масм - инструмент претворяющий идею в жизнь