CMPXCHG (Сравнить и заменить) использует три операнда : операнд-источник в регистре, операнд назначения в регистре или в памяти и аккумулятор (т.е. регистр AL, AX или EAX в зависимости от размерности операндов). Если значения в приемнике и в накопителе равны, операнд назначения заменяется на источник. В противном случае исходное значение операнда назначения загружается в накопитель. Флаги отражают результат, который получается при вычитании операнда назначения из аккумулятора. Флаг ZF устанавливается, если значения операнда назначения и накопителя равны, в противном случае флаг очищается.
Команда CMPXCHG полезна при тестировании и модификации семафоров. Она выполняет проверку, чтобы посмотреть, свободен ли семафор и есть ли такая отметка, в противном случае команда получает идентификатор текущего владельца в одной непрерываемой операции. В системах с одним процессором она исключает необходимость переключения на уровень 0 для блокировки прерываний для выполнения многократных команд. Для многопроцессорных систем команда CMPXVHG может быть объединена с командой LOCK для выполнения всех циклов шины автоматически. Смотри введение в раздел 3.11 относительно использования команды CMPXCHG на процессоре 386.
+--------------------------------------------------------------+| || $title ('ASCII сложение/вычитание с использованием BSWAP') || || name ASCII_arith || || code segment er public use32 || ; || ; Сложить 4 десятичных цифры в ASCII-строке все вместе || ; Старшим полубайтом ДОЛЖЕН быть 3 || ; DS:[ESI] указывает на операнд 1 || ; DS:[EBX] указывает на операнд 2 || ; DS:[EDI] указывает на операнд назначения || ; || || add10 proc near || || ; || ; Выполняет ASCII сложение с использованием команды BSWAP на || ; процессоре i486 || ; || || mov eax,[esi] ; получает младшие четыре цифры || ; первого операнда || bswap eax ; преобразует в форму big-endian || add eax,96969696H ; выравнивает для сложения || mov ecx,[ebx] ; получает четыре младшие цифры || ; второго операнда || bswap ecx ; преобразует в форму big-endian || add eax,ecx ; выполняет сложение с внутрираз- || ; рядным переносом || rcr ch,1 ; сохраняет флаг переноса || mov edx,eax ; сохраняет значение || and eax,0F0F0F0F0H ; извлекает старший полубайт || sub edx,eax ; заполняет нулями старший || ; полубайт каждого байта || shr eax,4 ; подготавливает для фиксации || and eax,0A0A0A0AH ; если ненулевой старший полу- || ; байт, то сформоровать 10 как || ; выравнивающее значение для || ; младшего полубайта || add eax,edx ; формируется выровненное значе- || ; ние младшего полубайта, старшие || ; полубайты могут быть 1 из || ; выравнивания || or eax,30303030H ; преобразовать обратно в ASCII || bswap eax ; обратно в форму little-endian || mov [edi],eax ; установить значение приемника | | rcl ch,1 ; восстановить флаг перенос || ret || || add10 endp || || ; || ; Вычесть 4 десятичных цифры в ASCII-строке все вместе || ; Старшим полубайтом ДОЛЖЕН быть 3 || ; DS:[ESI] указывает на операнд 1 || ; DS:[EBX] указывает на операнд 2 [ESI]-[EBX] || ; DS:[EDI] указывает на операнд назначения || ; || || sub10 proc near || || ; || ; Выполняет ASCII вычитание с использованием команды BSWAP на|| ; процессоре i486 || ; || || mov eax,[esi] ; получает младшие четыре цифры || ; первого операнда || bswap eax ; преобразует в форму big-endian || mov ecx,[ebx] ; получает четыре младшие цифры || ; второго операнда || bswap ecx ; преобразует в форму big-endian || sub eax,ecx ; выполняет вычитание с исполь- || ; зованием внутриразрядного заема || ; единицы || rcr ch,1 ; сохраняет флаг переноса || mov edx,eax ; сохраняет значение || and eax,0F0F0F0F0H ; извлекает старший полубайт, F, || ; если возникает заем единицы || sub edx,eax ; заполняет нулями старший || ; полубайт каждого байта || shr eax,4 ; подготавливает для фиксации || and eax,0A0A0A0AH ; если ненулевой старший полу- || ; байт, то сформоровать 10 как || ; выравнивающее значение для || ; младшего полубайта || add eax,edx ; формируется выровненное значе- || ; ние младшего полубайта, старшие || ; полубайты могут быть 1 из || ; выравнивания || or eax,30303030H ; преобразовать обратно в ASCII || bswap eax ; обратно в форму little-endian || mov [edi],eax ; установить значение приемника || rcl ch,1 ; восстановить флаг заема единицы || ret || || sub10 endp || || code ends || end || |+--------------------------------------------------------------+Рисунок 3-24. ASCII арифметика с использованием команды BSWAP