На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
Дорогие друзья! Поздравляем вас с днем Победы!
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Как загрузить в регистр CPU значения указателя, VC++ 2019 inline assembler
Привет всем. Не знаю, куда правильно помещать тему - сюда или в раздел по ассемблеру.

Пишу функцию обработки изображения на си. Хочу написать на inline ассемблере (точнее надо, это принципиально, неважно).
Заготовка для функции:
ExpandedWrap disabled
    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] валится?

спасибо.
Прикреплённая картинка
Прикреплённая картинка
Цитата hd44780 @
Любая из 3 последних команд под отладкой дают ошибку - см скрин.
Ну у меня в 19-й вижуалке вторая ваша команда всё нормально делает:
ExpandedWrap disabled
    void tt( unsigned char *ppt)
    {
        unsigned char *ggh;
        __asm {
            mov ebx, [ppt]
            inc ebx
            mov [ggh], ebx
            inc ecx
            mov ecx, [ggh]
        }
    }
Вот тут на что-то похожее жалуются https://github.com/opencv/opencv/issues/15690

Правда, без ассемблера, на чистом сишнике, но ошибка ровно как у меня. Попробую я VC++ грохнуть и переставить, может какие-то апдейты кривые пришли.
Сообщение отредактировано: hd44780 -
Ситуация совершенно непонятная. Ни одна из трёх команд не может бросать этого исключения. По ссылке почти наверняка пример неподдерживаемой процессором инструкции, сгенерированной компилятором, например, SIMD из нереализованного в нём набора SSEx, но тут стандартный i386. Чтобы ассемблер неверно сгенерировал код, а дизассемблер полностью зеркально скрыл этот факт? Не верю.
Могу предположить три варианта:
  • баг отладчика или системного ПО, например, антивируса; не исключено, что точка останова int 3 неверно обрабатывается в среде;
  • проявление зловреда, не отловленного антивирусом; именно подобным образом по времена DOS палились многие вирусы под TD386;
  • разогнанный процессор.
Разгон кристалла ещё и не такие выкрутасы умеет. hd44780, попробуй вынести эту функцию в отдельный .asm и скомпилить специализированным Ассемблером. Например, NASM или хотя бы MS-ым MASM. Так же не помешает посмотреть байты кода, желательно не в отладчике, а в листинге по ключу -Fa. Ну и попытаться проверить все три предположения путём смены инструмента явно лишними мне будут.
Рекомендую прогнать через дизассемблер свой exe и увидеть, что там фактически сгенерировалось на этом месте:
ExpandedWrap disabled
    dumpbin /disasm my_exe.exe /out:my_exe.asm



И я конечно не знаю как msvc разруливает все эти конфликты использования регистров, флагов и пр. Знаю, что во времена Borland C любое использование было на свой страх и риск, ничего не синхронизировалось вообще. В gcc во встроенном ассемблере нужно обязательно указывать все, что ты потенциально мог испортитьиспользовать.
Сообщение отредактировано: shm -
Спасибо всем. Как и ожидалось после прочтения https://github.com/opencv/opencv/issues/15690 снос и переустановка VC 2019 решила все эти проблемы.

Вот и ставь после этого все эти апдейты :D .

Тему пока замораживаю, т.к. эта работа ещё идёт.
По поводу отладки асм-кода в VS я скажу, что это полное дно.
Я нечасто юзаю студию для отладки кода на асме, но точки останова там постоянно ставятся мимо и курсор ходит мимо (открываешь отладчик Ctrl+Alt+D и видишь, что код исходника там один, а дизасм другой).
Сбивают всё пустые строки (и закомментированные соответственно), насколько я помню (полгода уже, наверное, не отлаживал там асм-код).

Плюс ко всему, регистры ebx, esi, edi, ebp нужно сохранять и восстанавливать при изменении (или не использовать их). На этот счёт есть соглашение о вызовах.
Исключение может возникнуть по этой причине, но не в самом асм-коде, а уже после него (либо если вызывать какие-то функции из асм-кода).

Не знаю, дело ли в обновлении или в том, что отладчик тупо показывает не ту строку, а по факту из-за изменения ebx возникает исключение в коде за асм-блоком.
1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
0 пользователей:


Рейтинг@Mail.ru
[ Script execution time: 0,0365 ]   [ 24 queries used ]   [ Generated: 9.05.21, 07:38 GMT ]