程序集 8086 - x86 中的减法

Assembly 8086 - Subtracting in x86

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

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

解密算法应该是

预期的结果应该是“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, 73, 64 在第 2 次迭代中,我们有 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'。可能真的错了。

The problem is at decrypt

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

这是原始的Vigenère编码,subtracting/adding97转from/to小写字母:

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

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

The decrypt algorithm should be

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" ???

我不知道你从哪里得到你的 CIPHER。难道你将数字 63、61 和 64 解释为十六进制?这些确实代表“c”、“a”和“d”。


以及关于减法本身的问题。这完全取决于您如何查看编码数字。如果 DL 包含位模式 11101110b (EEh) 并且您以 无符号方式查看它 ,则它代表 238,但如果您以 有符号方式查看它way,则代表-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