Мелкие задачки для крупных мозгов №19

Тема в разделе "WASM.A&O", создана пользователем The Svin, 3 май 2006.

  1. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    Даны a,b,c. Принадлежат 32bit Unsign Integers.

    По определению a < b.

    Задача

    if b-a < c

    a <- (b-a)

    else

    a <- c

    Для тех кто интересуется прикладным значениям "задачек",

    подобный код встречается на каждом шагу, например в "окнах" отображения или буфферах для обработки.

    Например вы выводите в пользовательское окно какой-то участок массива. При этом есть ограничения окна (сколько вообще там может быть отражено) тогда пусть a - это индекс с какого места выводить массив, b - общий размер массива,

    с - сколько элементов массива максимально "влезет" в окно.

    В а вернётся значения сколько элементов можно отображать.

    Тоже касается и различных буфферных по частям обработок (использованию кеша, участков памяти под DMA и т.п.) "а" скажет сколь нужно\можно грузить.



    Теперь дополнительные условия.

    Во первых пояснения почему не cmovcc. По странному обстоятельству в настоящее время инструкции типа sbb и adc выполняются медленно на современнных x86. Можно спекулировать об этом долго (то ли засилье в этой области HLL и ламерски написанных компиляторов повергло Intel к такой архитектуре то ли что ещё). Однако инструкции эти являются базовыми для не только мощных процессоров но и для простых микроконтроллерах, и выполняются обычно так же или чуть-чуть медленнее как такая база как логика и + -.

    Таким образом код написанный с их использованием для x86 очень легко переносится на целую группу процессоров и микроконтроллеров, для которых cmovcc как раз является экзотической инструкцией.

    Относительно самой задачи

    пусть a находится в eax

    b и с адресуются как переменные в памяти и [c].

    Портить их не разрешается. Адресацию их будет считать условно "оптимальной" так что там оптимизировать нечего.

    кроме eax разрешается использовать ещё один регистр (пусть edx). Безбранчевый код. Оптимизация по размеру (интересна также оптимизация по количеству инструкций). Вобще могут быть интересны разные варианты, т.к. тут несмотря на скромность условий задачи широкое поле для использования преобразования неравенств для понимания связей, сумм и разностей, флагов и т.п. для получения нужного результата.

    Вобщем как и в остальных задачках главное - прояснение связей и как следствие нахождение возможностей.
     
  2. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    По инструкциям наверно оптимальный вариант, только вот приходится С два раза считывать, и imul есть.
    Код (Text):
    1.     sub eax,[b]
    2.     add eax,[c]
    3.     sbb edx,edx
    4.     imul edx
    5.     add eax,[c]
     
  3. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    IMUL если логику кода оставить, получается заменить тремя базовыми инструкциями (xor,sub,and) или двумя (neg,and)
    Код (Text):
    1.  
    2. sub eax,[b]
    3. add eax,[c]
    4. sbb edx,edx
    5.  
    6. ;-----3 вместо IMUL---
    7. sub eax,edx ;+1
    8. xor eax,edx ;not = -(eax) при CF
    9. and eax,edx ;бросить слогаемое в 0 если не CF
    10. ;----------
    11. ;-- альтернатива 2е вместо IMUL но с neg
    12. ;neg eax ;предпологаем в минус если было положительное
    13. ;and eax,edx ;обнуляем слогаемое если не CF (т.е. было отр.)
    14. ;--- конец альтернативы
    15.  
    16. add eax,[c]
    17.  




    Есть ли путь покороче?
     
  4. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    Я подумал, что правомерно будет чуть изменить задачу.

    Дать дополнительную маленькую свободу, т.к. это учит организовывать расположение аргументов при диффиците ресурсов.

    Маленькая дополнительная свобода заключается в том что в eax можно расположить любую из переменных а,b,c. Остальные остаются в памяти. Условия те же - eax должен вернуть то, что уже описанно. Переменные в памяти портится не должны.

    А вот какую из переменных выгодней поместить в регистр - решайте сами.
     
  5. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    eax=b
    Код (Text):
    1.     sub eax,[a]
    2.     sub eax,[c]
    3.     sbb edx,edx
    4.     and eax,edx
    5.     add eax,[c]


    Но от двух обращений к C всё равно не спасает.