Pull to refresh

Comments 29

Тема выглядит не очень раскрытой.
— как передавать параметры в функции? Как передаются различные типы (включая struct)?
— чем отличаются конвенции fastcall и cdecl? Как ими управлять? Какие ещё есть варианты?
— какие регистры можно «портить» в коде функции, а какие нужно сохранить?
— как возвращается результат (опять же, для разных типов)?
Наверное, есть и другие вопросы. Но это первое, что бросается в глаза.
Самый главный вопрос-то пропустили: а где здесь C++?
Была мысль спросить об устройстве таблиц виртуальных функций, но решил, что пока не стоит.
Буду еще редактировать. Однако это не совсем то, что я хотел донести. Суть вопроса в том, чтобы «подружить» asm и cpp. Имхо, данная тема раскрыта.
В любом случае, благодарю за тему для дальнейших исследований.
К сожалению, «подружить» два языка, не раскрывая протокола вызова функций, написанных на одном из них, из другого языка, не очень получится. А протокол этот не очень очевидный.
На всякий случай предупрежу.
в исходниках VirtualDub есть такой файл: a_resample_mmx.asm (этот код используется при изменении разрешения изображения).
В этом файле несколько раз встречается такая строчка:
and esi,byte -4

Так вот, в 2010 студии (имеется ввиду компилятор ml.exe) эта строчка компилировалась правильно, а вот в 2013 — ошибочно (только что проверил на update4 — ошибка на месте).
2013 студия компилирует эту строчку в следующие опкоды: 0152EBDC, что эквивалентно команде:
and esi,0FFFFFFFDh  

или, если записать в знаковом виде:
and esi,byte -3

Упс.
Пришлось заменить явно на
and esi,0FFFFFFFCh ;byte -4


Повторюсь: сей баг проявляется, если использовать компилятор ассемблера ml.exe, который идет в составе Visual Studio 2013.
UFO just landed and posted this here
Вы внимательно читали? Это не я писал так. Это исходники VirtualDub. Вы знаете, про такую программу VirtualDub?
UFO just landed and posted this here
на счет опкода ошибся, да. Вроде бы правильно копировал, но нет. Прошу прощения.
На самом деле вот так:

Оу. Извините :) Это же адреса а не опкоды. (ушел ковырять настройки disassembler view в студии)
Если вы считаете, что ключеове слово byte перед числом -4 правомерно превращает его в -3, объясните пожалуйста, почему я должен считать такое поведение правильным? Вполне допускаю, что мои знания ассемблера не достаточно полны.
UFO just landed and posted this here
UFO just landed and posted this here
byte превращается в 1 компилятором ml? Это где нибудь описано? Странно, что в 2010 студии этого не было.
UFO just landed and posted this here
А почему не что-то вроде
int __stdcall __declspec(naked) Foo(int x, int y)
{
    __asm
    {
        pop eax
        pop ecx
        add eax, ecx
        ret
    }
}
Получаем ассемблерную функцию без пролога и эпилога и не имеем ненужных приседаний с .asm-файлами и обменом экспортами.
Потому что в 64 битах будет
error C4235: nonstandard extension used: '__asm' keyword not supported on this architecture
Можно начать использовать Clang в качестве компилятора — он поддерживает ассемблерные вставки для x64 тоже =)
UFO just landed and posted this here
А если у тебя уже есть пара мегабайт кода на MASM, который нужно переиспользовать?
Ну вы не путайте переиспользование и написание нового. Разные вещи.
В чем Вы видите смысл подключения ассемблерных модулей к программе на C++?

На мой взгляд, это может быть полезно исключительно для использования MMX/SSE и подобных средств. В базовой системе команд довольно сложно переплюнуть компилятор по качеству кода.
Смысл любой совместимости, как всегда, в переиспользовании уже имеющегося кода на MASM.
По-моему вы просто попытались изобрести велосипед.
Напишите простейший helloworld с вызовом чего-нибудь вроде memcpy — и зайдите отладчиком по F11. Вы увидите, что эта функция падает в недра ассемблера.
С пониманием вопроса на уровне «падает в недра ассемблера» стоило бы постесняться комментировать подобную статью.
С отношением на уровне «прочитал, проверять ничего не стал, сразу побежал троллить» Вам стоило бы постесняться писать комментарии на Хабре.

— Многие из этих низкоуровневых функций написаны на ассемблере. Со всевозможными оптимизациями под разные архитектурные особенности (вроде наличия SSE и т.д.). И при отладке вы попадаете прямо в этот текст (не автоматический дизассемблер, которая студия предлагает при отсутствии исходника модуля, а именно в ассемблерный исходник, с комментариями и т.д.). Т.е. эти функции уже реализованы дОлжным образом. И потому отдельная статья на тему, что «смотрите, так, оказывается, можно сделать!» — она да, уровня песочницы.
Рад, что у Вас с пониманием все же несколько лучше, чем показалось после прочтения комментария. Если хотите, чтобы Вас понимали правильно — имеет смысл выражаться яснее.

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

Так что Ваш комментарий, мало того, что непонятен, он еще и лишен всякого смысла.
Плюс за статью.
Проект из примера успешно компилируется также в Visual Studio 2015.
До этого приседал 2 дня, пытаясь слинковать MASM проект с C-шным.
Думаю, что эта статья спасла мне пару дней жизни.
Sign up to leave a comment.

Articles