首页 > 解决方案 > 组装 - 查询字符串

问题描述

我的环境变量中有一个查询字符串,我正在尝试读取其参数。例如,我正在尝试阅读QUERY_STRING=m1=5&m2=60%rdi 中的内容。我已经编写了代码,并且正在尝试获取参数(5,60)。我不确定到目前为止我所写的内容是否正确,因为在 DDD 上,我需要很长时间才能找到 QU 的前 2 个字母。有人可以验证这是否正确或是否有错误。请记住,我只是上传代码的循环部分。非常感谢

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

标签: assemblyx86-64

解决方案


cmpq $'Q',(%rdi)是一个qword比较
0x51 00 00 00 00 00 00 00只有当 RDI 指向的 8 个字节是(x86 是 little-endian,并且'Q' = 0x51)时,它才会设置 ZF 。

您可以cmpl $'QUER', (%rdi)检查前 4 个字节是否匹配。(您最多可以使用 32 位立即数,但不能使用 64 位,除非使用mov寄存器。)

但是不要忘记检查终止0字节,否则如果在循环到未映射的内存之前没有找到匹配项,最终会出现段错误。

或者另一种选择是要求匹配从字符串的开头开始,这样一发现不匹配就停止查找。

你的循环也很笨重,当你只检查一个条件时,有 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 并且您不必寻找零字节,那就更容易了。有关优化的 memcmp 的示例,请参见https://code.woboq.org/userspace/glibc/sysdeps/x86_64/memcmp.S.html 。(评论不多,记住它必须返回 -、0 或 + 结果,而不仅仅是等于或不等于。)另请参阅https://code.woboq.org/userspace/glibc/sysdeps/x86_64/multiarch /memcmp-avx2-movbe.S.html用于避免分支的小输入的有趣bswap策略。(它有更多评论。)

glibc 的 strcmp 与 memcmp 不同


推荐阅读