简单的加密汇编程序 - 写入内存位置的访问冲突
Simple encryption Assembly Program - Access violation writing to memory location
我不得不在这个最初使用非标准化约定的程序中实现 cdecl 调用约定。据我所知,它看起来是正确的,但我收到一个未处理的异常错误,说 "Accress violation writing location 0x00000066, which seems to hit when the program gets down to the line "not byte ptr[eax]" 或至少是中断程序后箭头指向的位置。
谁能告诉我我的程序出了什么问题,我该如何解决?谢谢你。
void encrypt_chars (int length, char EKey)
{ char temp_char;
for (int i = 0; i < length; i++)
{
temp_char = OChars [i];
__asm {
push eax
movzx eax, temp_char
push eax
lea eax, EKey
push eax
call encrypt
mov temp_char, al
pop eax
}
EChars[i] = temp_char;
return;
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted (in the low 8-bit field, CL).
// Output: register EAX = the encrypted value of the source character (in the low 8-bit field, AL).
__asm {
encrypt:
push ebp
mov ebp, esp
mov ecx, 8[ebp]
mov eax, 12[ebp]
push edi
push ecx
not byte ptr[eax]
add byte ptr[eax], 0x04
movzx edi, byte ptr[eax]
pop eax
xor eax, edi
pop edi
rol al, 1
rol al, 1
add al, 0x04
mov esp, ebp
pop ebp
ret
}
经检查,加密函数的注释是错误的。请记住:堆栈增长向下,因此当参数被压入堆栈时,首先被压入的参数具有更高的地址,因此,与堆栈帧中的基指针的偏移量更大.
encrypt
的评论说:
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted
但是,您的调用顺序是:
movzx eax, temp_char ; push the char to encrypt FIRST
push eax
lea eax, EKey ; push the encryption key SECOND
push eax
call encrypt
所以这个角色是push first。所以要加密的字符但是 encrypt
正在以这种方式加载它们:
; On function entry, the old Instruction Pointer (4 bytes) is pushed onto the stack
; so now the EKey is +4 bytes from the stack pointer
; and the character is +8 bytes from the stack pointer
;
push ebp
mov ebp, esp
; We just pushed another 4 bytes onto the stack (the esp register)
; and THEN we put the stack pointer (esp) into ebp as base pointer
; to the stack frame.
;
; That means EKey is now +8 bytes off of the base pointer
; and the char to encrypt is +12 off of the base pointer
;
mov ecx, 8[ebp] ; This loads EKey pointer to ECX
mov eax, 12[ebp] ; This loads char-to-encrypt to EAX
代码然后继续尝试引用 EAX
作为指针(因为它认为那是 EKey
),这将导致访问冲突,因为这是您的角色第一次加密它试图将 EAX
引用为指针,它在这里:
not byte ptr[eax]
所以你的调试器指针是正确的! :)
你可以通过交换这两个寄存器来修复它:
mov eax, 8[ebp] ; This loads EKey pointer to EAX
mov ecx, 12[ebp] ; This loads char-to-encrypt to ECX
最后,您对加密的调用在完成后不会清除堆栈指针。由于您在调用 encrypt
之前将 8 个字节的数据压入堆栈,并且由于 encrypt
执行标准 ret
且没有堆栈清理,因此您需要在调用后进行清理:
...
call encrypt
add esp, 8
...
我不得不在这个最初使用非标准化约定的程序中实现 cdecl 调用约定。据我所知,它看起来是正确的,但我收到一个未处理的异常错误,说 "Accress violation writing location 0x00000066, which seems to hit when the program gets down to the line "not byte ptr[eax]" 或至少是中断程序后箭头指向的位置。
谁能告诉我我的程序出了什么问题,我该如何解决?谢谢你。
void encrypt_chars (int length, char EKey)
{ char temp_char;
for (int i = 0; i < length; i++)
{
temp_char = OChars [i];
__asm {
push eax
movzx eax, temp_char
push eax
lea eax, EKey
push eax
call encrypt
mov temp_char, al
pop eax
}
EChars[i] = temp_char;
return;
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted (in the low 8-bit field, CL).
// Output: register EAX = the encrypted value of the source character (in the low 8-bit field, AL).
__asm {
encrypt:
push ebp
mov ebp, esp
mov ecx, 8[ebp]
mov eax, 12[ebp]
push edi
push ecx
not byte ptr[eax]
add byte ptr[eax], 0x04
movzx edi, byte ptr[eax]
pop eax
xor eax, edi
pop edi
rol al, 1
rol al, 1
add al, 0x04
mov esp, ebp
pop ebp
ret
}
经检查,加密函数的注释是错误的。请记住:堆栈增长向下,因此当参数被压入堆栈时,首先被压入的参数具有更高的地址,因此,与堆栈帧中的基指针的偏移量更大.
encrypt
的评论说:
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted
但是,您的调用顺序是:
movzx eax, temp_char ; push the char to encrypt FIRST
push eax
lea eax, EKey ; push the encryption key SECOND
push eax
call encrypt
所以这个角色是push first。所以要加密的字符但是 encrypt
正在以这种方式加载它们:
; On function entry, the old Instruction Pointer (4 bytes) is pushed onto the stack
; so now the EKey is +4 bytes from the stack pointer
; and the character is +8 bytes from the stack pointer
;
push ebp
mov ebp, esp
; We just pushed another 4 bytes onto the stack (the esp register)
; and THEN we put the stack pointer (esp) into ebp as base pointer
; to the stack frame.
;
; That means EKey is now +8 bytes off of the base pointer
; and the char to encrypt is +12 off of the base pointer
;
mov ecx, 8[ebp] ; This loads EKey pointer to ECX
mov eax, 12[ebp] ; This loads char-to-encrypt to EAX
代码然后继续尝试引用 EAX
作为指针(因为它认为那是 EKey
),这将导致访问冲突,因为这是您的角色第一次加密它试图将 EAX
引用为指针,它在这里:
not byte ptr[eax]
所以你的调试器指针是正确的! :)
你可以通过交换这两个寄存器来修复它:
mov eax, 8[ebp] ; This loads EKey pointer to EAX
mov ecx, 12[ebp] ; This loads char-to-encrypt to ECX
最后,您对加密的调用在完成后不会清除堆栈指针。由于您在调用 encrypt
之前将 8 个字节的数据压入堆栈,并且由于 encrypt
执行标准 ret
且没有堆栈清理,因此您需要在调用后进行清理:
...
call encrypt
add esp, 8
...