程序集 ASCII 验证的意外行为

问题描述 投票:0回答:2

我对汇编非常陌生,目前正在尝试编写一个程序,该程序使用用户指定的密钥和用户指定的内容执行凯撒加密。密钥和内容必须是 a-z 或 A-Z,为了验证这一点,我构建了一个简单的算法来检查 ASCII 值是否在相应的范围内。问题是,即使给定普通字符 a-z 或 A-Z,它仍然返回 false。

这是我的算法的最小可重现示例。即使给算法提供了“a”,它仍然返回错误。我不知道为什么会这样,我已经检查了 ASCII 表和所有内容。

section .text
  global _start

_start:
cmp byte [char], 122
jg _error
cmp byte [char], 96
jg _success
cmp byte [char], 90
jg _error
cmp byte [char], 64
jg _success
jmp _error

_success:
  mov rax, 1
  mov rdi, 1
  mov rsi, success
  mov rdx, len_success
  syscall
  xor rbx, rbx
  jmp _exit

_error:
  mov rax, 1
  mov rdi, 2
  mov rsi, error
  mov rdx, len_error
  syscall
  mov rbx, 1
  jmp _exit

_exit:
  mov rax, 60
  mov rdi, rbx
  syscall

section _data
  char db 'a'
  error db "Error"
  len_error equ $ - error
  success db "Success"
  len_success equ $ - success

这只是一个例子,真正的算法是这样的:

_process_text_input:
  cmp byte [text_input], 10
  je _no_text_error
  xor rbx, rbx
  jmp _pti_loop
_pti_loop:
  cmp rbx, [len_text_input]
  jg _pti_end
  mov al, [text_input+rbx]
  cmp al, 97
  jl _process_capital_char
  cmp al, 122
  jg _bad_text_error
  add al, [key]
  cmp al, 122
  jg _fix_overhang
  mov byte [output+rbx], al
  inc rbx
  jmp _pti_loop
_process_capital_char:
  cmp byte [text_input+rbx], 90
  jg _bad_text_error
  cmp byte [text_input+rbx], 65
  jl _bad_text_error
  mov al, [text_input+rbx]
  add al, [key]
  cmp al, 90
  jg _fix_overhang
  mov byte [output+rbx], al
  inc rbx
  jmp _pti_loop
_fix_overhang:
  sub al, 26
  mov byte [output+rbx], al
  inc rbx
  jmp _pti_loop
_pti_end:
  ret
assembly x86-64 ascii nasm caesar-cipher
2个回答
2
投票

目前,这是我看到问题的地方,但我会继续寻找:

_process_text_input:
    cmp byte [text_input], 10
    je  _no_text_error
    xor rbx, rbx
    jmp _pti_loop

_pti_loop:
    cmp rbx, [len_text_input]
    jg  _pti_end ; of-by-one error -> should be `je`
    mov al, [text_input+rbx]
    cmp al, 97
    jl  _process_capital_char
    cmp al, 122
    jg  _bad_text_error
    add al, [key]
    cmp al, 122
    jg  _fix_overhang
    mov byte [output+rbx], al
    inc rbx
    jmp _pti_loop

_process_capital_char:
    cmp byte [text_input+rbx], 90
    jg  _bad_text_error
    cmp byte [text_input+rbx], 65
    jl  _bad_text_error
    ;   mov al, [text_input+rbx] -> not needed
    add al, [key]
    cmp al, 90
    jg  _fix_overhang
    mov byte [output+rbx], al
    inc rbx
    jmp _pti_loop

_fix_overhang:
    sub al, 26
    mov byte [output+rbx], al
    inc rbx
    jmp _pti_loop

_pti_end:
    ret

0
投票

差一错误

_pti_loop:
  cmp rbx, [len_text_input]
  jg _pti_end

在此循环开始时,RBX 仍为零,并且假设 len_text_input 是非负数,则 RBX 不可能大于 [0,maxint] 范围内的数字。因此,您的代码将无法捕获空字符串,并且通常它会处理过多的一个字符!如果您使用

jge
甚至
je
那就没问题了。

有符号与无符号错误

  add al, [key]
  cmp al, 122
  jg _fix_overhang

对于此凯撒加密,key 在 [0,25] 范围内。一旦确定要处理的是 [97,122] 范围内的 ASCII 小字符 a-z,就可以添加键。此加法的结果可高达 147。因为您使用的是有符号条件指令

jg
,其中 [128,255] 范围内的所有数字都被视为负数,所以更大的条件可能不适用,因此“悬垂”可能无法修复。

始终将 ASCII 视为无符号数字

下一个改进的解决方案还删除了一些冗余,例如多次从

[text_input + rbx]
重新加载。

_process_text_input:
  cmp   byte [text_input], 10
  je    _no_text_error
  xor   rbx, rbx
  cmp   [len_text_input], rbx
  je    _pti_end

_pti_loop:
  movzx eax, byte [text_input + rbx]
  mov   edx, 'Z'
  cmp   al, 'A'
  jb    _bad_text_error
  cmp   al, 'Z'
  jbe   _add_key
  cmp   al, 'a'
  jb    _bad_text_error
  cmp   al, 'z'
  ja    _bad_text_error
  or    edx, 32               ; -> EDX = 'z'
_add_key:
  add   al, [key]             ; key = [0,25]
  cmp   al, dl                ; DL = {'Z','z'}
  jbe   _store
  sub   al, 26                ; fix overhang
_store:
  mov   [output + rbx], al
  inc   rbx
  cmp   rbx, [len_text_input]
  jb    _pti_loop

_pti_end:
  ret
© www.soinside.com 2019 - 2024. All rights reserved.