
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.14.87] |
![]() |
|
Сообщ.
#1
,
|
|
|
Привет всем. Не знаю, куда правильно помещать тему - сюда или в раздел по ассемблеру.
Пишу функцию обработки изображения на си. Хочу написать на inline ассемблере (точнее надо, это принципиально, неважно). Заготовка для функции: ![]() ![]() void RasterDithering(uint8_t* pPixels, uint32_t dwWidth, uint32_t dwHeight) { uint32_t dwOneVal = 1; uint32_t dwRevWidth; uint8_t *pPixelData; __asm { mov ebx, [pPixels] ; ebx: = указатель на пиксели test ebx, ebx ; Выход, если jz L10 ; указатель == 0 mov [dwOneVal], 1 mov ecx, [dwHeight] ; ecx: = высота картинки mov eax, [dwRowBytes] ; eax: = длина строки dec ecx ; ecx: = высота - 1 mul ecx ; edx:eax: = eax * ecx add ebx, eax ; ebx == pPixelData - указатель на последнюю mov [pPixelData], ebx ; строку изображения ........................ // lea ecx, [pPixelData] ; ecx = pPixelData; // указатель на последнюю строку изображения // mov ecx, [pPixelData] ; ecx = pPixelData; // указатель на последнюю строку изображения mov ecx, pPixelData ; ecx = pPixelData; // указатель на последнюю строку изображения Все команды до mov [pPixelData], ebx включительно работают нормально и правильно. Надо загнать значение указателя pPixelData в ecx. Да, в данном месте можно сделать mov ecx, ebx и забыть, но после mov [pPixelData], ebx есть масса других команд. Поэтому грузить надо из [pPixelData]. Проблема такая: Любая из 3 последних команд под отладкой дают ошибку - см скрин. Как сделать правильно? Почему mov ebx, [pPixels] вверху работает, а внизу такой же mov ecx, [pPixelData] валится? спасибо. Прикреплённая картинка
|
Сообщ.
#2
,
|
|
|
Цитата hd44780 @ Ну у меня в 19-й вижуалке вторая ваша команда всё нормально делает:Любая из 3 последних команд под отладкой дают ошибку - см скрин. ![]() ![]() void tt( unsigned char *ppt) { unsigned char *ggh; __asm { mov ebx, [ppt] inc ebx mov [ggh], ebx inc ecx mov ecx, [ggh] } } |
Сообщ.
#3
,
|
|
|
Вот тут на что-то похожее жалуются https://github.com/opencv/opencv/issues/15690
Правда, без ассемблера, на чистом сишнике, но ошибка ровно как у меня. Попробую я VC++ грохнуть и переставить, может какие-то апдейты кривые пришли. |
![]() |
Сообщ.
#4
,
|
|
Ситуация совершенно непонятная. Ни одна из трёх команд не может бросать этого исключения. По ссылке почти наверняка пример неподдерживаемой процессором инструкции, сгенерированной компилятором, например, SIMD из нереализованного в нём набора SSEx, но тут стандартный i386. Чтобы ассемблер неверно сгенерировал код, а дизассемблер полностью зеркально скрыл этот факт? Не верю.
Могу предположить три варианта: Разгон кристалла ещё и не такие выкрутасы умеет. hd44780, попробуй вынести эту функцию в отдельный .asm и скомпилить специализированным Ассемблером. Например, NASM или хотя бы MS-ым MASM. Так же не помешает посмотреть байты кода, желательно не в отладчике, а в листинге по ключу -Fa. Ну и попытаться проверить все три предположения путём смены инструмента явно лишними мне будут. |
Сообщ.
#5
,
|
|
|
Рекомендую прогнать через дизассемблер свой exe и увидеть, что там фактически сгенерировалось на этом месте:
![]() ![]() dumpbin /disasm my_exe.exe /out:my_exe.asm И я конечно не знаю как msvc разруливает все эти конфликты использования регистров, флагов и пр. Знаю, что во времена Borland C любое использование было на свой страх и риск, ничего не синхронизировалось вообще. В gcc во встроенном ассемблере нужно обязательно указывать все, что ты потенциально мог |
Сообщ.
#6
,
|
|
|
Спасибо всем. Как и ожидалось после прочтения https://github.com/opencv/opencv/issues/15690 снос и переустановка VC 2019 решила все эти проблемы.
Вот и ставь после этого все эти апдейты ![]() Тему пока замораживаю, т.к. эта работа ещё идёт. |
![]() |
Сообщ.
#7
,
|
|
По поводу отладки асм-кода в VS я скажу, что это полное дно.
Я нечасто юзаю студию для отладки кода на асме, но точки останова там постоянно ставятся мимо и курсор ходит мимо (открываешь отладчик Ctrl+Alt+D и видишь, что код исходника там один, а дизасм другой). Сбивают всё пустые строки (и закомментированные соответственно), насколько я помню (полгода уже, наверное, не отлаживал там асм-код). Плюс ко всему, регистры ebx, esi, edi, ebp нужно сохранять и восстанавливать при изменении (или не использовать их). На этот счёт есть соглашение о вызовах. Исключение может возникнуть по этой причине, но не в самом асм-коде, а уже после него (либо если вызывать какие-то функции из асм-кода). Не знаю, дело ли в обновлении или в том, что отладчик тупо показывает не ту строку, а по факту из-за изменения ebx возникает исключение в коде за асм-блоком. |