Сборка - Строка запроса - PullRequest
       7

Сборка - Строка запроса

0 голосов
/ 04 декабря 2018

В моей среде есть строка запроса, для которой я пытаюсь прочитать параметры.Например, я пытаюсь прочитать QUERY_STRING=m1=5&m2=60, который находится в% rdi.Я написал код и пытаюсь добраться до параметров (5,60).Я не уверен, что то, что я написал, верно до сих пор, так как на DDD у меня уходит так много времени, чтобы добраться до первых 2 букв QU.Может ли кто-нибудь проверить, правильно ли это или есть ошибки?Имейте в виду, я загружаю только часть цикла кода.Большое спасибо

Qloop:
cmpq $'Q',(%rdi)        #the query string is in RDI, and Comparing the first character Q
je Qloop1               #if its not equal, go back to Qloop
incq %rdi               #incrementing RDI
jmp Qloop1
Qloop1:
incq %rdi
cmpb $'U',(%rdi)        #compare the next character in RDI, which is U
je findnum              
jmp Qloop               #once increments go back to Qloop1
findnum:
incq %rdi 
cmpb $'m',(%rdi)        #this is for m1
jne findnum
jmp Qloop3  
Qloop3:
incq %rdi
cmpb $'=',(%rdi)        #next letter is =
jne Qloop3
jmp Qloop4

Qloop4:
incq %rdi 
cmpb $'m',(%rdi)        #this is for m2
jne Qloop4
jmp Qloop5          #if its not equal, go back to Qloop2
Qloop5:
incq %rdi
cmpb $'=',(%rdi)        #next letter is =
jne Qloop5

1 Ответ

0 голосов
/ 05 декабря 2018

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

...