有人要求我更改一些__asm代码,以便它实现C ++调用约定。我尝试使用cdecl,但我一直收到此错误
运行时检查失败#0:ESP的值未在函数调用中正确保存。这通常是由于使用一种调用约定声明的函数和使用另一种调用约定声明的函数指针进行调用的结果。
该代码用于使用for循环一次对一个字符加密一个字符串。函数encrypt_1
对当时通过for循环传递的字符进行编码。
我试图通过为for循环和函数将不同的值分配给基本指针(ebp
)和堆栈指针(esp
)使用cdecl,但是我一直在不断获取运行时检查失败#0,而我进行的任何尝试调整都导致程序中断。我一直在强调这几天,有人可以给我提示我可能出问题的地方吗?
身体:
void encrypt_chars (int length, char EKey)
{
char temp_char; // Character temporary store
for (int i = 0; i < length; i++) // Encrypt characters one at a time
{
temp_char = OChars[i]; // Get the next char from Original Chars array
// Each character in the string will be encrypted individually
__asm
{ //
push eax // Stores a backup of the location of eax to be used later
push ecx // Stores a backup of the charcter to be encrypted in the stack for later use
push edx // Stores a backup of the location for the encrypted character in the stack for later use
//
movzx ecx, temp_char // Places the character (8 bits) to be encrypted in the ecx register (32 bits) and replaces any extraneous bits with 0 as they are not being used.
lea eax, EKey // places the Ekey in the eax register for later use. Registers are fast than calling variables?
push ebp
mov ebp, esp
// sub esp, 4
push ecx // Parameter for encrypt1. - Temporary Character
push eax // Parameter for encrypt1. - Address for the key.
call encrypt_1 // Begins the Encryption Function
mov temp_char, dl // Stores the encrypted character in the temp_char variable to be reconstruced later
add esp, 8
pop eax // Restoring eax to previous location before parameter call
pop ecx // Restores Temporary Character location before parameter call
pop edx // Restores the edx register to its original value, ready for the next character
pop ecx // Restores the ecx register to its original value, ready for the next character
pop eax // Restores the eax register to its original value, ready for the next character
mov esp, ebp
pop ebp
// ret
}
EChars[i] = temp_char; // Store encrypted char in the Encrypted Chars array
}
return;
功能:
__asm
{
encrypt_1:
push ebp //Saves the present value of ebp on the stack for later use
mov ebp, esp //Places the stack pointer where the base pointer is so variables can be stored
mov ecx, [ebp +08h]
mov edx, [ebp +0Ch]
push ecx // Stores the original character on the top of the stack
movzx ecx, byte ptr[eax] // Moves the Ekey (8-bit) into the ecx register (32-bit), changing all extraneous bits to 0 so it can be rotated
add cl, 0x01 // Adds 1 to Ekey
rol cl, 1 // Rotates the binary value of Ekey to the left 6 times for further security
rol cl, 1 // Could have just used "rol cl, 6"
rol cl, 1
rol cl, 1
rol cl, 1
rol cl, 1
mov edx, ecx // Move the encrypted Ekey to edx, freeing the ecx register for the original character to be used later.
mov byte ptr[eax], dl // Move byte pointer to the left side of eax
pop ecx // Retrieves the original character to be encrypted
x1 : rol cl, 1 // Rotate the original character one place to the left , encrypting it
dec edx // Decrease the rotated Ekey by one, acting as a counter to continue decrypting the original character
jnz x1 // Jump back to x1 unless the Ekey = 0, which dictates that the encryption is complete
add ecx, 0x20 // Add 32 bits to the encrypted character, filling the register
mov edx, ecx // Place the encrypted character in the edx register, ready to be returned
mov esp, ebp
pop ebp
//add esp, 8
ret // Return the encrypted character
}
//--- End of Assembly code
}
PS。抱歉,有些混乱的注释行,我一直在尝试各种尝试以使其正常工作。
答案 0 :(得分:1)
没有理由在汇编中编写调用。您应该将调用代码更改为:
EChars[i] = encrypt_1(&EKey, OChars[i]);
如果由于某种原因您认为必须 用汇编语言编写,则可以编写:
temp_char = OChars[i];
__asm
{
movzx ecx, temp_char
lea eax, EKey
push ecx // Second param: character to encrypt
push eax // First param: address of EKey.
call encrypt_1
mov temp_char, al
}
EChars[i] = temp_char;
功能:
__asm
{
encrypt_1:
push ebp
mov ebp, esp
mov eax, [ebp+08h] // first param: address of EKey
mov dl, [ebp+0Ch] // second param: character to encrypt
mov cl, byte ptr [eax] // get value of EKey
add cl, 0x01
rol cl, 6
mov byte ptr [eax], cl // store updated value of EKey
rol dl, cl
add dl, 0x20
movzx eax, dl // Return encrypted character in eax
mov esp, ebp
pop ebp
ret
}
除了简化之外,我修复的唯一内容是:
1.使用eax而不将其加载到函数中。
2.功能参数颠倒顺序。
3.根本没有使用该函数的EKey参数。