在 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
我正在尝试通过根据某个密钥向左或向右旋转消息的每 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