Ошибка проверки времени выполнения # 0.Потерял, как использовать CDECL - PullRequest
0 голосов
/ 02 марта 2019

Меня попросили изменить некоторый код __asm, чтобы он реализовал соглашение о вызовах C ++.Я пытался использовать cdecl, но получаю эту ошибку

Ошибка проверки времени выполнения # 0: значение ESP не было должным образом сохранено при вызове функции.Обычно это является результатом вызова функции, объявленной с одним соглашением о вызовах, с указателем функции, объявленным с другим соглашением о вызовах.

Код используется для шифрования строки по одному символу за раз, используя дляпетля.Функция encrypt_1 кодирует символ, проходящий через цикл for в то время.

Я попытался использовать cdecl, присвоив разные значения базовому указателю (ebp) и указателю стека (esp) как для цикла for, так и для функции, но я постоянно получаю ошибку проверки времени выполнения # 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 голосов
/ 03 марта 2019

Нет причин писать вызов в сборке.Вы должны изменить код вызова на:

    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 для функции вообще не использовался.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...