汇编 8086 - 在 x86 中减去

问题描述

我正在开发一个使用 Vigenère 密码加密/解密数据的程序。除了解密部分,一切都很好。

加密和计算密钥背后的逻辑是:

  • 输入:“qwerty”

  • Key : "asd" = 计算出的键是 "asdasd"

  • 密码:“catdxn”

  • 对于加密,我使用以下算法:

  • 结果[i] = (输入[i]+key[i]) % 26

  • 结果[i] += 3dH ;转换为asci数

  • 密码[i] += 结果[i] 问题在于解密:

解密算法应该是

  • 结果[i] = (INPUT[i] - KEY[i]) % 26

  • IN CASE INPUT[i] - KEY[i] = NEGATIVE NUMBER = 添加 26,所以公式变为

  • 结果[i] = (INPUT[i] - KEY[i] + 26)% 26

  • 结果[i] += 3dH

  • 密码[i] += 结果[i] ;获取结果字符串

预期的结果应该是“qwerty”,但我得到的是“usgtrm”。

所以按照上面描述的算法,我有以下代码

;inputKey           = KEY,;inputWORD          = Input,;cipherText         = Result    
;inputWORDLENGTH    = length of input = CX
XOR DI,DI
vigDECLOOP:
    cmp di,cx
    JNB DONELOOPDEC 
    PUSH CX
    mov si,offset inputWORD
    ADD SI,DI
    XOR DX,DX
    MOV DL,DS:[SI]         ; DL = INPUT[I]
    xor SI,SI
    MOV SI,OFFSET inputKEY
    ADD SI,DI
    XOR CX,CX
    MOV CL,DS:[SI]         ; CL = KEY[I]
    SUB DL,CL
    ; ========
    ; Here in case is negative number I somehow need to add 26 to DL (result of DIV )
    ; IT 2:  61- 73 = EE in DL and should be -18,I kNow is something about the signed bit 
    ; but I dont kNow what to read and where about this.
    ; ========
    mov ax,cx              ; Store in AX the result of subtracting
    mov bx,26              ; add in bx 26 
    div bx                  ; To obtain the reminder from % 26 
    ; ========
    ; ========
    add dl,3Dh             ; add 3dH to DL(reminder of DIV) to get the asci        
    xor si,si   
    mov si,offset cipherText
    add si,di
    xor dh,dh
    add dl,DS:[si]
    mov DS:[si],dl
    INC DI
    POP CX
    jmp vigDECLOOP
DONELOOPDEC:    
    RET

问题在于减去数字,我对这个主题完全是菜鸟。 让我们说“catdxn”这个词。 63、61、74、64、78、6E 和关键 'asdasd' 61,73,64,61,64 在第二次迭代中,我们有 61 - 73 ( SUB DL,CL ) = 结果是 FFFF FFFF FFFF FFEE 或 - 18。 发生这种情况时,我需要将 26 添加到结果中,但我无法理解: SUB DL,CL STORES IN DL = EE 的结果这是十进制的 238,我如何添加 26 十进制或 (1A Hex) 到一个正数......它应该是'61h - 73h = -18d + 26d 或 1Ah = 8'。可能真的错了。

解决方法

问题在于解密

没有。连加密都错了!正如 Jester 所指出的,您正在使用 ASCII 代码,您应该使用字母表中字母的偏移量 [0,25]。

这是原始的 Vigenère 编码,减去/添加 97 来转换小写字母:

CIPHER[i] = ((INPUT[i]-97 + KEY[i]-97) % 26) + 97

INPUT  : "qwerty"
KEY    : "asdasd"
CIPHER : "qohrlb"

解密算法应该是

RESULT[i] = (INPUT[i] - KEY[i]) % 26

如何使用 INPUT 进行解密?这就是解密试图找出的东西!


您当前代码中的一些错误包括:

  • 您在 DL 中有减法的结果,您想将其除以 26,但您改为将 CX 除以 26
  • 您使用字大小的除法,但忘记事先将 DX 归零

接下来使用字节大小的除法可以纠正以下几个错误:

  sub dl,cl
  mov ax,dx              ; Store in AX the result of subtracting
  mov bl,26
  div bl                  ; To obtain the reminder from % 26 
  add ah,3Dh             ; add 3Dh to AH (remainder of DIV) to get the ascii
  mov si,offset cipherText
  add si,di
  add [si],ah

为什么你认为加上 3Dh(十进制 61)会产生 ASCII ?


您当前的加密是这样做的:

        113 119 101 114 116 121  INPUT[]  : "qwerty"
         97 115 100  97 115 100  KEY[]    : "asdasd"
        --- --- --- --- --- ---     
        210 234 201 211 231 221  INPUT[]+KEY[]
          2   0  19   3  23  13  (INPUT[]+KEY[]) % 26
cipher   63  61  80  64  84  74  (INPUT[]+KEY[]) % 26 + 3Dh

          ?   =   P   @   T   J  CIPHER[] : "catdxn" ???

我不知道您从哪里获得密码。难道你把数字 63、61 和 64 解释为十六进制?那些确实代表“c”、“a”和“d”。


关于减法本身的问题。这完全取决于您如何查看编码后的数字。如果 DL 包含位模式 11101110b (EEh) 并且您以无符号方式查看它,那么它代表 238,但如果您以有符号方式查看它 ,那么它代表-18。
只需将其视为有符号数字并添加所需的 26。您最终会得到一个范围为 [0,25] 的数字。

  sub dl,cl              ; DH = 0
  jns IsPositive
  add dl,26
IsPositive:
  mov ax,dx              ; Store in AX the result of subtracting