Для сравнения строк из различных типов чисел в ассемблере NASM применяются инструкции
cmpsb: сравнивает строку байтов
cmpsw: сравнивает строку из слов
cmpsd: сравнивает строку из двойных слов
cmpsq: сравнивает строку из четверных слов
Процессор сравнивает значение, на которое ссылается регистр RDI, со значением, на которое указывает регистр RSI. RCX содержит количество элементов в исходной строке (не путать с количеством обрабатываемых байтов).
Вместе с этой инструкцией можно использовать ряд префиксов:
Префикс repe указывает повторять операцию до тех пор, пока сравнение равно, или до количества раз, указанного RCX (в основном применяется для сравнений символьных строк).
Префикс repne повторяет операцию, пока сравнение не равно, или до количества раз, указанного RCX
Без применения этих префиксов инструкции cmps
вычитают значение в RDI
из значения в RSI
и обновляет флаги в соответствии с результатом.
После сравнения двух чисел cmps
увеличивает или уменьшает регистры RSI и RDI на 1, 2, 4 или 8 (для cmpsb, cmpsw, cmpsd и cmpsq соответственно).
cmps
увеличивает регистры RSI и RDI, если флаг направления сброшен, и уменьшает их, если флаг установлен. Например, сравненим равные по длине массивы:
global _start section .data nums1 dw 10, 11, 12, 13, 14, 15, 16, 17 nums2 dw 10, 11, 12, 13, 14, 15, 16, 17 section .text _start: mov rsi, nums1 mov rdi, nums2 mov rcx, 8 ; 8 слов repe cmpsw ; сравниваем слова jz equal ; если строки равны, переход к метке equal mov rdi, 2 ; если строки не равны, RDI = 2 jmp exit equal: mov rdi, 4 ; если строки равны, RDI = 4 exit: mov rax, 60 syscall
Здесь сравниваем два массива чисел. Если они равны, помещаем в RDI число 4, если не равны - число 2.
Если строки имеют или могут иметь разную длину, то задача немного усложняется. Две строки равны, когда их длины равны и элементы в соответствующих позициях равны. Если одна из строк меньше другой, но все ее элементы равны соответствующим символам второй строки (то есть первая строка является подстрокой второй строки), то мы можем считать что первая строка меньше второй.
В этом случае в регистр RCX помещается длина наименьшей строки. Далее обе строки сравниваются как и вобщем случае. И если они равны, сравниваются их длины.
Пример сравнения двух строк:
global _start section .data str1 db "Hello World" str1_len equ $-str1 ; длина первой строки str2 db "Hello World" str2_len equ $-str2 ; длина второй строки section .text _start: mov rsi, str1 mov rdi, str2 mov rcx, str1_len cmp rcx, str2_len ; сравниваем длины строк jbe compare ; если длина str1 равна или меньше mov rcx, str2_len ; если длина str2 меньше compare: repe cmpsb ; сравниваем байты jnz notequal ; если не равны mov rcx, str1_len cmp rcx, str2_len ; если равны, сравниваем длины строк jnz notequal mov rdi, 16 ; если строки равны jmp exit notequal: mov rdi, 8 ; если строки не равны exit: mov rax, 60 syscall
Строки символов обычно сравниваются в алфавитном порядке. Поскольку символы фактически представлены их числовами кодами, то сравнение символов выливается в сравнение их числовых кодов (в данном случае для простоты считаем, что символы в разных регистрах - это разные символы).