Per il ciclo nell’assemblaggio x86 e nell’ottimizzazione del codice?

Attualmente sto imparando la programmazione di assemblaggi come parte di uno dei miei moduli universitari. Ho un programma scritto in C ++ con assembly inline x86 che accetta una stringa di 6 caratteri e li crittografa in base alla chiave di crittografia.

Ecco il programma completo: https://gist.github.com/anonymous/1bb0c3be77566d9b791d

Il mio codice per la funzione encrypt_chars :

 void encrypt_chars (int length, char EKey) { char temp_char; // char temporary store for (int i = 0; i < length; i++) // encrypt characters one at a time { temp_char = OChars [i]; // temp_char now contains the address values of the individual character __asm { push eax // Save values contained within register to stack push ecx movzx ecx, temp_char push ecx // Push argument #2 lea eax, EKey push eax // Push argument #1 call encrypt add esp, 8 // Clean parameters of stack mov temp_char, al // Move the temp character into a register pop ecx pop eax } EChars [i] = temp_char; // Store encrypted char in the encrypted chars array } 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 // Set stack mov ebp, esp // Set up the base pointer mov eax, [ebp + 8] // Move value of parameter 1 into EAX mov ecx, [ebp + 12] // Move value of parameter 2 into ECX push edi // Used for string and memory array copying push ecx // Loop counter for pushing character onto stack not byte ptr[eax] // Negation add byte ptr[eax], 0x04 // Adds hex 4 to EKey movzx edi, byte ptr[eax] // Moves value of EKey into EDI using zeroes pop eax // Pop the character value from stack xor eax, edi // XOR character to give encrypted value of source pop edi // Pop original address of EDI from the stack rol al, 1 // Rotates the encrypted value of source by 1 bit (left) rol al, 1 // Rotates the encrypted value of source by 1 bit (left) again add al, 0x04 // Adds hex 4 to encrypted value of source mov esp, ebp // Deallocate values pop ebp // Restore the base pointer ret } //--- End of Assembly code } 

Le mie domande sono:

  • Qual è il modo migliore / più efficace per convertire questo for loop in assembly?
  • C’è un modo per rimuovere la chiamata per encrypt e posizionare il codice direttamente al suo posto?
  • Come posso ottimizzare / minimizzare l’uso di registri e istruzioni per rendere il codice più piccolo e potenzialmente più veloce?
  • C’è un modo per me di convertire gli array OChars e EChars in assembly?

Se ansible, saresti in grado di fornirmi una spiegazione su come funziona la soluzione che sono desideroso di imparare.

Non posso aiutarti con l’ottimizzazione o la crittografia, ma posso mostrarti come creare un ciclo, se osservi il ciclo in questa funzione:

 void f() { int a, b ; for(a = 10, b = 1; a != 0; --a) { b = b << 2 ; } } 

Il ciclo è essenzialmente:

  for(/*initialize*/; /*condition*/; /*modify*/) { // run code } 

Quindi la funzione in assemblea sembrerebbe qualcosa di simile:

 _f: push ebp mov ebp, esp sub esp, 8 ; int a,b initialize: ; for mov dword ptr [ebp-4], 10 ; a = 10, mov dword ptr [ebp-8], 1 ; b = 1 mov eax, [ebp-4] condition: test eax, eax ; tests if a == 0 je exit runCode: mov eax, [ebp-8] shl eax, 2 ; b = b << 2 mov dword ptr [ebp-8], eax modify: mov eax, [ebp-4] sub eax, 1 ; --a mov dword ptr [ebp-4], eax jmp condition exit: mov esp, ebp pop ebp ret 

Inoltre mostro nel sorgente come si creano le variabili locali;

  • sottrarre lo spazio dal puntatore dello stack.
  • e accedervi tramite il puntatore di base.

Ho cercato di rendere la sorgente come syntax di assembly intel x86 generica come potrei quindi scusarmi se qualcosa dovesse essere necessario per il tuo ambiente specifico avrei avuto maggiori intenzioni di dare un'idea generale su come build un loop in assembly e darti qualcosa che puoi copiare , incolla e corri.

Suggerirei di esaminare il codice assembly generato dal compilatore. Puoi modificarlo e ottimizzarlo in seguito.

Come si ottiene l’output dell’assembler dalla sorgente C / C ++ in gcc?