【问题标题】:Trying to compare two strings in x86-64尝试比较 x86-64 中的两个字符串
【发布时间】:2022-01-17 21:54:09
【问题描述】:
global _start

section .data
    firstMsg: db "hello worms, please say the passcode", 10
    firstLen: equ $ - firstMsg
    secondMsg: db "Correct", 10
    secondLen: equ $ - secondMsg
    thirdMsg: db "Incorrect.", 10
    thirdLen: equ $ - thirdMsg
    password: db "Hello"

section .bss
    attempt RESB

section .data
_start:

;Print the first message
    mov rax, 1
    mov rdi, 1
    mov rsi, firstMsg
    mov rdx, firstLen
    syscall

;Read input
    mov rax, 0
    mov rdi, 0
    mov rsi, attempt
    mov rdx, 10
    syscall

;compare input to the password
    cmp attempt, password
    je L1
    jne L2
    syscall

;Display correct if correct
L1:
    mov rax, 1
    mov rdi, 1
    mov rsi, secondMsg
    mov rdx, secondLen
    jmp L3
    syscall

;display incorrect if incorrect
L2:
    mov rax, 1
    mov rdi, 1
    mov rsi, thirdMsg
    mov rdx, secondLen
    syscall

;exit the program
L3:
    mov rax, 60
    mov rdi, 1
    syscall

此代码返回此错误消息:

inout.asm:13: error: invalid combination of opcode and operands
inout.asm:33: error: invalid combination of opcode and operands

我在这里尝试做的是将用户输入作为字符串,然后将其与常量密码进行比较。如果它们相同,则打印“正确”,如果不是,则打印“不正确”并跳回第一个问题(尚未完成该部分)。

如果有人能帮我解决这个问题,那就太好了。

【问题讨论】:

  • cmp 的两个操作数都是 imm64s(在您的情况下为指针常量),这不是有效的(更不用说有意义的)比较。改为查看rep cmps。另外,在执行系统调用之前无条件跳转到L3 似乎不合逻辑。此外,您在 BSS 部分中对 attempt 的定义不完整,它缺少长度并且标签缺少后缀 :。最后,我认为将您的代码放入您的 data 部分是没有意义的......它应该放入.text

标签: linux assembly x86-64 nasm


【解决方案1】:

cmp 指令比较适合寄存器的两个值(8、16、32 或 64 位值),而不是两个字符串。您需要 cmpsb 来比较字符串的每个字符,并且可以使用 rep 与它一起比较整个字符串:

;compare input to the password
    mov rsi, attempt    ; first string
    mov rdi, password   ; second string
    mov rcx, 5          ; length of the password
    repe cmpsb          ; compare
    jne L2              ; no match
    cmp byte ptr [rsi], 10  ; \n to end the input
    jne L2              ; extra stuff in attempt
    jmp L1

请注意,您可以通过将'\n' 字符添加到预期密码并使用长度为 6 来简化此操作。这样您就不需要额外的 cmp/jne 检查输入的结尾。

【讨论】:

  • 或者密码输入缓冲区从零开始,单个 qword cmp qword [rel attempt], rax 指令可以检查是否相等。 (在寄存器中有一个值;不是立即数,因为字符串的非零部分超过 32 位)。
  • @PeterCordes:您需要将密码正确地填充到 8 个字节,但这可以工作。
  • 是的,这就是我所说的“缓冲区归零开始”的意思。原始来源有attempt RESB,它要么是语法错误,要么没有保留任何字节,因此无论如何都需要更改它,即使它碰巧有一个空的BSS,碰巧与一些未使用的内存上的那个符号地址链接。
  • rep 是可应用于任何字符串指令 (ins/outs/movs/lods/stos/) 的 REP 指令前缀 (rep/repe/repne/repz/repnz) 之一cmps/scas)。它是“repeat”的缩写,重复字符串指令,直到设置或清除 rcx = 0 或 ZF(取决于使用了 3 个可能的前缀中的哪一个)。
  • 即检查输入(尝试)密码结束后的下一个字符是否为换行符 - 从终端读取时,读取系统调用通常会读取(并包括)换行符.如前所述,可以通过将其包含在预期的密码字符串中来删除它。如果没有检查,输入HelloWorld 将匹配Hello 的密码
猜你喜欢
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 2015-12-07
相关资源
最近更新 更多