Как я могу реорганизовать этот C ++ для удаления меток / gotos? - PullRequest
2 голосов
/ 18 апреля 2011

Моя проблема на самом деле не проблема, но я хочу, чтобы этот код выглядел немного более элегантно, чем сейчас. У него есть код спагетти.

Вот небольшой пример того, что я получил.

 int func(...) {
  if ( ... )
  {
    v6 = ESI_1C;
    EBP = 1;
    v5 = 0;
    v21 = 0;
    v19 = 0;
    v25 = ESI_1C;
    if ( packetSize > 1 )
    {
      v26 = (unsigned __int8)initialCryptAnswer;
      v10 = v8 - v6;
      v11 = v6 + 4;
      for ( i = v8 - v6; ; v10 = i )
      {
        v12 = *(DWORD *)(v10 + v11);
        v21 += v12;
        cryptAnswer = (unsigned __int8)cryptTable[(2 * (unsigned __int8)v26)+1];
        v13 = EBP & 3;
        if ( !(EBP & 3) )
          break;
        if ( v13 == 1 ) {
          v16 = cryptAnswer >> 1;
          *(DWORD *)v11 = v12 - v16;
        } else if ( v13 == 2 ) {
          *(DWORD *)v11 = v12 + 2 * cryptAnswer;
        } else if ( v13 == 3 ) {
          v16 = cryptAnswer >> 2;
          *(DWORD *)v11 = v12 - v16;
        }
LABEL_19:
        v17 = *(DWORD *)v11 + v19;
        ++EBP;
        v11 += 4;
        v19 = v17;
        ++v26;
        if ( EBP >= packetSize )
        {
          ESI = v24;
          v5 = v17;
          v6 = v25;
          goto LABEL_22; //kinda like break it's much more because it's instead of a for loop too.
        }
      }
      *(DWORD *)v11 = v12 + 4 * cryptAnswer;
      goto LABEL_19; //this is a looper
    }
LABEL_22:
    result = 1;
  } else {
    result = 0;
  }
  return result;
}

Что я могу сделать, чтобы избавиться от меток, не испортив поток кода, поскольку это очень важная часть функции шифрования?

Ответы [ 3 ]

2 голосов
/ 18 апреля 2011

Второй ответ, так как вопрос сильно изменился.

Исходный код выглядит после удаления всего лишнего:

for (... ; ; ...)
{
  ...
  if (...)
  {
    break;
  }
  ABC
LABEL_19:
  DEF
}
XYZ;
goto LABEL_19;

Это точно так же, как:

for (... ; ; ...)
{
  ...
  if (...)
  {
    XYZ;
  }
  else
  {
    ABC
  }

  DEF
}

Как только вы выполните эту перезапись, вы можете заменить goto LABEL_22 на простой break.

РЕДАКТИРОВАТЬ: Или более явно:

for (... ; ; ...)
{
  ...
  if (! (ESP & 3) )
  {
    // This line used to be located after the loop.
    *(DWORD *)v11 = v12 + 4*cryptAnswer;  // 111
  }
  else
  {
    if (v13 == 1)
    {
      ...
    }
    else if (v13 == 2)
    {
      ...
    }
    else if (v13 == 3)
    {
      ...
    }
  }

  // This is where LABEL_19 used to be.

  v17 = ...      // 222
}

Эмпирическое правило, когда вы переписываете код следующим образом: код должен выполнять те же действия в том же порядке, что и раньше. Вы просто не можете перемещать код вслепую, и чтобы сделать это, вы должны понимать поток кода. В этом случае, когда берется первый if, сначала выполняется строка, помеченная // 111, затем строка // 222, ничего больше.

1 голос
/ 18 апреля 2011

Было бы лучше, если бы вы вырезали и вставили код, чтобы мы могли вырезать и вставить его в редактор, но в основном строка перед goto Label_19 должна идти там, где находится строка разрыва. Оператор if после перерыва должен стать оператором if if, а метка goto 22 может стать перерывом (или переместить условное выражение, которое приводит к метке goto 22 в цикл for, как в моем предыдущем ответе) в цикл for.

PS: ваш секрет не является секретом для тех, у кого есть исполняемый файл

1 голос
/ 18 апреля 2011

goto LABEL_1 никогда не выполняется, поскольку выхода из цикла for нет.

После того, как это будет удалено, вы можете заменить goto LABEL_2 на break или дажелучше просто return 1; (или result = 1; return 1;, если return не является локальной переменной.)

...