Даны 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). Безбранчевый код. Оптимизация по размеру (интересна также оптимизация по количеству инструкций). Вобще могут быть интересны разные варианты, т.к. тут несмотря на скромность условий задачи широкое поле для использования преобразования неравенств для понимания связей, сумм и разностей, флагов и т.п. для получения нужного результата. Вобщем как и в остальных задачках главное - прояснение связей и как следствие нахождение возможностей.
По инструкциям наверно оптимальный вариант, только вот приходится С два раза считывать, и imul есть. Код (Text): sub eax,[b] add eax,[c] sbb edx,edx imul edx add eax,[c]
IMUL если логику кода оставить, получается заменить тремя базовыми инструкциями (xor,sub,and) или двумя (neg,and) Код (Text): sub eax,[b] add eax,[c] sbb edx,edx ;-----3 вместо IMUL--- sub eax,edx ;+1 xor eax,edx ;not = -(eax) при CF and eax,edx ;бросить слогаемое в 0 если не CF ;---------- ;-- альтернатива 2е вместо IMUL но с neg ;neg eax ;предпологаем в минус если было положительное ;and eax,edx ;обнуляем слогаемое если не CF (т.е. было отр.) ;--- конец альтернативы add eax,[c] Есть ли путь покороче?
Я подумал, что правомерно будет чуть изменить задачу. Дать дополнительную маленькую свободу, т.к. это учит организовывать расположение аргументов при диффиците ресурсов. Маленькая дополнительная свобода заключается в том что в eax можно расположить любую из переменных а,b,c. Остальные остаются в памяти. Условия те же - eax должен вернуть то, что уже описанно. Переменные в памяти портится не должны. А вот какую из переменных выгодней поместить в регистр - решайте сами.
eax=b Код (Text): sub eax,[a] sub eax,[c] sbb edx,edx and eax,edx add eax,[c] Но от двух обращений к C всё равно не спасает.