运行时检查失败#0。忘记了如何使用CDECL

时间:2019-03-02 18:56:35

标签: c++ assembly

有人要求我更改一些__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。抱歉,有些混乱的注释行,我一直在尝试各种尝试以使其正常工作。

1 个答案:

答案 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参数。