|
1.2 Функции Min/Max
Задачата е: Имаме две беззнакови числа в два регистъра да кажем eax и ebx. На изхода, в eax трябва да е по-малкото/по-голямото от двете числа. Задачата да се реши без преходи. Ето го и решението с използване на един допълнителен регистър: CODE
Как работи: След първата инструкция, в ebx имаме разликата между двете числа (тоест това е числото, което трябва да прибавим към eax, за да получим числото в ebx) Флагът CF = 1 ако ebx<eax или CF=0 ако ebx>eax. Втората инструкция нулира ecx, ако CF=0 и запълва ecx с 1-ци (ecx=-1) ако CF=1 (напомням, че инструкцията sbb op1, op2 извършва следната операция: op1 = op1 - op1 - CF) Третата инструкция вкарва в ecx стойността на разликата (ebx) но само ако ecx = (-1). Иначе ecx си остава 0 ( and със 0 = 0 ) И накрая последната инструкция или събира eax със 0 (ако ecx e 0, тоест ако ebx>eax на входа) или събира eax с разликата (ebx-eax) ако ecx = (ebx-eax), тоест ако на входа ebx < eax. Но eax+(ebx-eax) е точно равно на ebx -> тоест на изхода eax ще е равно на входното ebx. За да приспособим този код за функцията max, трябва само да инвертираме (not) стойността на ecx след инструкцията sbb. Тогава ще имаме ecx = -1 ако CF=0 (ebx>eax) и съответно ecx=0 ако CF=1 (ebx<eax). Ето го и пълният код: CODE
Смятам, че работата на този код не се нуждае от пояснения. Само ще добавя, че за постигане на максимална скорост, инструкциите трябва да се сдвоят правилно с други инструкции за паралелно изпълнение. Оригинала на кода за функцията min е на Агнер Фог. Модификацията за изпълнение на max е на автора на тази статия.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||









