在 Visual Studio 中无法使此组装过程正常工作

Having trouble making this assembly procedure work in Visual Studio

我正在尝试通过根据某个密钥向左或向右旋转消息的每 10 个字节的位来解决这个要我加密消息的问题,例如:

key BYTE -2, 4, 1, 0, -3, 5, 2, -4, -4, 6

其中符号表示旋转方向,负向左,正向右。数字表示旋转的大小。所以消息的第一个字节将向左旋转两次,第二个向右旋转 4 次,依此类推,我们对第 11 和第 12 个字节执行相同操作,依此类推,直到消息结束。

当我调用这个过程时,存储在内存中的消息没有任何变化,但是:

EncryptR PROC USES ebx ecx esi,
ptrkey: PTR BYTE, ; pointer to the key array
ptrmessage: PTR BYTE, ; pointer to the plaintext message
mlength: DWORD ; length of the message array
; -----------------------------------------------------------------------------

mov ecx, mlength 
    inc ecx
    mov edx, [ptrkey+10]
    ; mov edi, ptrmessage
    L2:
    mov esi, ptrkey 
    dec ecx 
    cmp ecx, 0 
    je endloop
    L1:
    push ecx
    mov cl, [esi]
    cmp cl,0
    ja Skip1
    neg cl
    rol [ptrmessage], cl
    jmp Skip2
    Skip1: 
    ror [ptrmessage], cl
    Skip2: 
    pop ecx 
    inc esi 
    inc ptrmessage
    cmp [esi], edx
    je L2
    LOOP L1

    endloop:
    ret

我试过使用 edi 指向消息,但根据旋转指令的语法,它显然不起作用。我现在直接使用 ptrmessage 以避免构建错误。我正在使用 invoke 调用该过程,并且已经使用 PROTO 指令声明了它。我已经尝试过这样做,一旦它越界,消息指针继续前进,就会将键数组的指针重置为第一个元素。

MOV edx, offset Message1 
    call Strlength
    Invoke EncryptR, ADDR key, addr Message1, eax

我不确定是什么问题,有可能过早地跳到 endloop 标签,这可以解释它,但很明显第一次不会发生这种情况。我使用轮换指令的方式有问题吗?

有几个问题。首先 ja 用于无符号比较,因此它不适用于检测 <0 的值。使用 jg(如果更大则跳转)。

当您使用 Invoke MASM 时,会为您准备一个框架并通过堆栈传递参数,这些在方法内部可用,但是如果您在 VS 外部的调试器中看到这些 ptrmessage,这些将是指向堆栈地址而不是消息内容的指针。

00401036 d3450c     rol     dword ptr [ebp+0Ch], cl

这就是为什么您看不到 rol 的影响,因为它 rol 不是字节而是指针。不确定 MASM 是否具有以正确方式执行此操作的语法,但您始终可以将地址获取到寄存器(比如 edi)并对其进行操作。在这种情况下,您还必须指定数据的大小 (byte ptr)。

考虑到以下因素,我会写 EncryptR 类似的东西(用 ;* 制作的更改行)

EncryptR PROC USES ebx ecx esi,
  ptrkey: PTR BYTE, ; pointer to the key array
  ptrmessage: PTR BYTE, ; pointer to the plaintext message
  mlength: DWORD ; length of the message array
; -----------------------------------------------------------------------------
  mov ecx, mlength 
  inc ecx
  mov edx, ptrkey
  add edx, 10           ;*
  mov edi, ptrmessage ;*
L2:
  mov esi, ptrkey 
  dec ecx 
  cmp ecx, 0 
  je endloop
L1:
  push ecx
  mov cl, [esi]
  cmp cl,0
  ja Skip1               ;*
  neg cl
  rol byte ptr [edi], cl ;*
  jmp Skip2
Skip1: 
  ror byte ptr [edi], cl ;*
Skip2: 
  pop ecx 
  inc esi 
  inc edi
  cmp esi, edx
je L2
  LOOP L1

endloop:
  ret
EncryptR ENDP