assembly - 组装 - 查询字符串
问题描述
我的环境变量中有一个查询字符串,我正在尝试读取其参数。例如,我正在尝试阅读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
解决方案
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 不同
推荐阅读
- android - 如何在 Jetpack 中的 ModelDrawer 布局中添加 FloatingActionButton 组合在 android
- asp.net-core - NewtonsoftJsonInputFormatter 在 .NET5 中不能用作 InputFormatter
- java - UNIX 无法读取 MyBatis 资源文件
- unit-testing - 在单元测试控制器 NestJs 中上传模拟文件
- ios - 如何将嵌套节点从 Firebase 实时数据库检索到 iOS 应用程序
- c++ - 为什么我的程序在使用 -fsanitize=leak 时不会停止?
- sql - 等待 x 秒后重试 SQL UPDATE 查询
- java - java - 如何在Java Swing中为非空布局组件设置绝对位置?
- spring - Spring Data JPA,如何将一个属性映射到两列?
- yaml - OpenAPI YAML 描述中的 |、> 和 >- 有什么区别?