-2

I am currently learning assembly programming as part of one of my university modules. I have a program written in C++ with inline x86 assembly which takes a string of 6 characters and encrypts them based on the encryption key.

Here's the full program: https://gist.github.com/anonymous/1bb0c3be77566d9b791d

My code fo the encrypt_chars function:

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
}

My questions are:

  • What is the best/ most efficient way to convert this for loop into assembly?
  • Is there a way to remove the call for encrypt and place the code directly in its place?
  • How can I optimise/minimise the use of registers and instructions to make the code smaller and potentially faster?
  • Is there a way for me to convert the OChars and EChars arrays into assembly?

If possible, would you be able to provide me with an explanation of how the solution works as I am eager to learn.

  • 1
    You're telling us what you want to do rather than asking us questions about what you want to do. What obstacle have you encountered trying to convert the loop into assembly language? What specifically do you not know how to do? – David Schwartz Apr 22 '15 at 09:07
  • @DavidSchwartz I know how to make a simple loop with jumps to labels however I am not quite sure on how to make the for loop. Any useful links/ information would be helpful. –  Apr 22 '15 at 09:11
  • @BorisSmith All loops are "simple loops with jumps to labels"; the `for` loop is no exception. You should be aware that `for(A;B;C){X;}` is the same as `A;while(B){X;C;}` – deviantfan Apr 22 '15 at 09:15
  • @deviantfan Okay thanks, that makes sense however, would you be able to give me an example of how I can set a local variable in assembly and compare it to the `int length` parameter? –  Apr 22 '15 at 09:24
  • to set use `mov`, to compare use `cmp` – phuclv Apr 22 '15 at 09:27
  • One way to find out how to make the loop in assembly is run the Visual Studio debugger, put a break point on your for loop. When the execution stops at the for loop, use Debug->Windows->Disassembly from the menu and look at what the compiler generated. – The Dark Apr 22 '15 at 09:31
  • @TheDark That's a very good suggestion, can't believe I've not thought about that. Thanks! –  Apr 22 '15 at 09:33
  • 2
    It seems to me you are trying to do something complicated (build a fast encryption scheme) without having mastered the basics of assembly language first (this question is pretty telling: "for example, how can I set a local variable in assembly?"). Master say, *Do Not Play Symphony on Day One*. *Do Finger Exercises first*. Go learn how to code in assembly first. With that mastered, this exercise gets a lot easier and you'll be able to answer most of your questions directly. – Ira Baxter Apr 22 '15 at 10:07
  • I'm voting to close this question as off-topic because it's homework crap and has 12 no-effort friends, all the same. – Martin James Jul 17 '15 at 20:08

2 Answers2

1

I would suggest to look into assembly code which is generated by compiler. You can change and optimize it later.

How do you get assembler output from C/C++ source in gcc?

Community
  • 1
  • 1
Bartlomiej Grzeskowiak
  • 1,009
  • 5
  • 16
  • 35
1

I can't help with optimization or the cryptography but i can show you a way to go about making a loop, if you look at the loop in this function:

void f()
{
        int a, b ;

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

The loop is essentially:

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

So the function in assembly would look something along these lines:

_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

Plus I show in the source how you make local variables;

  • subtract the space from the stack pointer.
  • and access them through the base pointer.

I tried to make the source as generic intel x86 assembly syntax as i could so my apologies if anything needs changing for your specific environment i was more aiming to give a general idea about how to construct a loop in assembly then giving you something you can copy, paste and run.

James
  • 1,009
  • 10
  • 11