cmpq $'Q',(%rdi)
- сравнение ключевых слов .ZF будет установлен только в том случае, если 8 байтов, на которые указывает RDI, равны
0x51 00 00 00 00 00 00 00
(x86 имеет младший порядок и 'Q' = 0x51
).
Вы можете cmpl $'QUER', (%rdi)
проверить первые 4совпадение байтов.(Вы можете использовать до 32-битного непосредственного, но не 64-битного, кроме как с mov
для регистра.)
Но не забудьте проверить завершающий байт 0
, илив конечном итоге вы увидите segfault, если не обнаружите совпадение до того, как зациклиться в не отображенной памяти.
Или другой вариант - требовать, чтобы совпадение начиналось в начале строки, поэтому вы прекращаете поиск, как тольковы обнаружите несоответствие.
Ваши циклы также действительно неуклюжи, с 2 ветвями вместо 1, когда вы проверяете только одно условие.
Qloop:
inc %rdi
cmpb $'Q', -1(%rdi) # check the first char
jne Qloop # keep looping until we find a 'Q'
# falls through on a match: RDI pointing at (hopefully) a 'U'
Или для проверки нулевого байта:
Qloop:
movzbl (%rdi), %eax # load a byte into a register (zero-extending to fill RAX to avoid partial-register false dependencies)
test %eax,%eax
jz end_of_string
cmp $'Q', %al
jne Qloop
Конечно, это действительно неэффективный способ реализации strcmp.Вы определенно хотите сравнивать несколько байтов одновременно, используя SSE2 pcmpeqb
.Или, если это memcmp и вам не нужно искать нулевые байты, тогда это проще.См. https://code.woboq.org/userspace/glibc/sysdeps/x86_64/memcmp.S.html для примера оптимизированного memcmp.(Не так много комментариев, и помните, что он должен возвращать результат -, 0 или + вместо просто равного или не равного.) См. Также https://code.woboq.org/userspace/glibc/sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S.html для интересной стратегии bswap
для небольших входных данных, которая избегает ответвлений,(В ней больше комментариев.)
strcmp glibc отличается от memcmp