Доброго времени суток! Есть прога с несколькими местами, в которых используются цепочечные команды (scasb, cmpsb и т.д.) Достаточно ли выставить df только один раз в начале программы или нужно делать это каждый раз перед намерением воспользоваться данными командами? (типа этот флаг может испортить какая-либо инструкция или другая программа, процессор то один на всех)
Я точно не знаю, но можно прочитать доки и проверить под отладчиком. ДУмаю, что нужно каждый раз выставлять.
FeD, по-умолчанию, под Windows, DF=0 и если программа использует команду std, то перед вызовом любой WinAPI необходима команда cld, также сброс DF понадобится и перед выходом из программы
yashechka, пробежался я по докам, такие команды типа push, mov по идее не должны трогать это флаг. Mikl___, Я использую только cld. Программа не очень большая (лаба). Хотя, склоняюсь к тому, что лучше этот флаг выставлять каждый раз.
Если взвести DF и вызвать апи, то апп упадёт. Этот флаг должен быть всегда сброшен. Нет причины его устанавливать, зачем копировать память назад.
За всё время мне понадобилось устанавливать DF лишь несколько раз, при перемещении стека например. Но это слишком спец задачи, такое обычно не нужно. Поэтому два флага - AF и DF можно считать deprecated.
Спасибо за ответы. Получается, что за cld можно сильно не переживать. Но возможен ли случай, когда (т.к. Windows многозадачная система) другая посторонняя программа делает std и, внезапно, управление получает наша программа, которая не ожидает такого сюрприза? Или я пишу полную херню? [offtop]На этом форуме можно редактировать заголовки тем? У меня тут очепятка[/offtop]
FeD, Windows, перед тем как передать управление другой программе, запомнит содержимое регистров твоей программы, в том числе и содержимое регистра EFLAGS. Когда управление будет передано твоей программе, содержимое регистров будет восстановлено, в том числе и содержимое флага DF. Сюрпризов не будет.
http://www.agner.org/optimize/calling_conventions.pdf Короче, если некоторая функция не чистит DF после его изменения, то она багованная.
FeD, Вся система предполагает что данный флаг сброшен, приложение должно его сбросить(те сохранить и восстановить). Иначе произойдёт копирование памяти в обратную сторону, что в конце приведёт к падению. В нт память расширяется только вверх, за исключением стека, он растёт вниз. В случае стека необходимо обратное перемещение памяти(выборка данных), иначе он не будет расширяться. Но так никогда не делается - стек растёт естественным образом за счёт PUSH/CALL. Принудительно же он расширяется листанием его страниц, но никак не обратным проходом по нему через rep.
Вообще обработка строк от конца к началу имеет место быть во всяких грамматических разборах. То что для апи вызовов флаг направления имеет такую важность и критичность свидетельство их ущербности. Такое требование для калбеков еще можно понять но для обычных апи - бред.
Rockphorr, Сохранение DF в каждой апи - во первых не профайл(перезагрузка флагов), во вторых анстаб(возможна перезапись флагов произвольным значением).
Вообще, есть такое понятие, как ABI, где чётко прописано: Какие регистры не должны меняться функцией (то есть, после выхода из функции должны иметь те же значения, что и при входе); Какие регистры могут быть изменены функцией по своему усмотрению (функция их не обязана восстанавливать); Какие регистры под какие цели зарезервированы/используются; Как следует правильно выделять память на стеке и как она используется. Так что если программа не соблюдает ABI, то это проблема самой программы.
Интересно, что мешает Microsoft делать cld каждый раз в своих функциях при необходимости и просто заявить, что DF не сохраняется (как для eax, ecx, edx и т.д.)...
Если cld будет делаться в каждой функции, это дополнительные накладные траты на процессорное время. Да, пусть они ничтожно малы, но вкупе могут отъесть 1-2% процессорного времени. А это тоже деньги: стоимость CPU и потребляемая электроэнергия (кВт * ч).
FeD, goto #13 pushf/popf в каждой функции - не профайл. А есчо если это использовать возможен новый тип атак OP. Изменение регистра флагов, перезапись произвольным значением. > просто заявить, что DF не сохраняется Оно наверно чётко указано, но я не помню где. Это нужно поднимать wrk доки или искать на мсдн. Обычно эта инфа заложена в компилер, вам не нужно знать про cpu-спец вещи. Те кто на асме кодит или реализует компилер знают сабж.
Зачем в каждой функции ??? только перед строковыми инструкциями (они как правило идут группой так что одну на группу)устанавливать нужное направление, по умолчанию считать его неопределенным - во всяком случае так у Пильщикова в книге было написано.
Rockphorr, ну давайте такой пример рассмотрим Код (Text): for (....) { if (!strcmp(...)) { strcpy(...); strcat(...); some_bogus_function(); // Устанавливает DF } } Что имеем? А то, что cld из цикла не выоптимизировать. Получаем на каждую *str-функцию CLD-команду. Три лишних CLD в цикле.
Rockphorr, > Зачем в каждой функции ??? только перед строковыми инструкциями А зачем его сохранять, если установка не нужна, а если и нужна, то в очень редких случаях. Зачем вам вообще этот флаг так интересен. Не используется это в нт, такая архитектура - память растёт вверх, тоже копирование например снизу вверх. Если вам нужно его установить, то восстановите после возврата, есть инструкция для этого и не одна.