High Level to ASM conversion

蹲街弑〆低调 提交于 2019-12-25 18:35:19

问题


I'm learning assembly programming and I've been tasked with converting a for loop (along with any array use) into assembly within my program.

The program simply takes an encryption key (EKey) and uses it to encrypt an array of letters (hello for example).

Here is the loop in C++:

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
}

I've looked at the disassembly code and used that to rewrite the ASM code. I typed in the disassembly code as follows however it gives the following errors: http://gyazo.com/3b6875c9e1207df61df4e95506af7ed6

Here is my code:

void encrypt_chars(int length, char EKey)
{
    char temp_char;

    __asm
    {
        mov     DWORD PTR[rbp - 4], 0
        jmp     L2

    L3:
        mov     eax, DWORD PTR[rbp - 4]
        cdqe
        cltq   

// ERROR HERE ^ above: error C2400: inline assembler syntax error in 'opcode'; found 'newline'  
        movzx   eax, BYTE PTR EChars[rax] 

// ERROR HERE ^ above: error C2400: inline assembler syntax error in 'opcode'; found 'newline'  
// another error ^ above: error C2424: '[' : improper expression in 'second operand'

        mov     BYTE PTR[rbp - 5], al

        // OG code
        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    encrypt4
        add     esp, 8              // Clean parameters of stack
        mov     temp_char, al       // Move the temp character into a register    

        pop     ecx
        pop     eax

        // end of OG code

        mov     eax, DWORD PTR[rbp - 4]
        cdqe
        movzx   edx, BYTE PTR[rbp - 5] // ERROR HERE: error C2400: inline assembler syntax error in 'opcode'; found 'newline'   
        mov     BYTE PTR DChars[rax], dl // ERROR HERE: error C2424: '[' : improper expression in 'first operand'

    L2:
        mov     eax, DWORD PTR[rbp - 4]
        cmp     eax, DWORD PTR[rbp - 20]
        jl      L3

    }
    return;

    __asm
    {
    encrypt4:
            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
}

Would anyone be able to point out where I'm going wrong please? I'm finding this relatively difficult so step-by-step explanations are most welcome. Please let me know where I'm going wrong. Thanks x

EDIT:

My full code: http://pastebin.com/tP9Dgvpn


回答1:


Try this:

void encrypt_chars(int length, char EKey, char *Msg)
{
    int InLength = length;
    int counter;

    __asm
    {
        push eax        // Counter
        mov eax, 0      // Zero counter
        push ebx        // Value
        mov ebx, InLength
        jmp     L2

L3:
        mov counter, EAX
        call    encrypt4
        inc eax         // Increment counter.

    L2:
        cmp     eax, ebx
        jl      L3      // Jump if we haven't reached our count.
        pop ebx
        pop eax
    }
    return;

    __asm
    {
    encrypt4:
            push    eax
            push    ebx
            push    edi

            mov     ebx, counter
            add     ebx, Msg
            mov     al, [ebx]      // Move character into al
            CBW                         // Make word.
            CWDE                        // Make Dword.


            not     byte ptr[EKey]       // Negation
            add     byte ptr[EKey], 0x04 // Adds hex 4 to EKey
            movzx   edi, byte ptr[EKey]  // Moves value of EKey into EDI using zeroes

            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 [ebx], al
            pop     ebx
            pop     eax
            ret
    }

    //--- End of Assembly code
}

I call it with this snippet:

EKey = 'i';

sprintf(OChars, "hello");

printf("%s\n", OChars);
encrypt_chars(sizeof(OChars), EKey, OChars);
printf("%s\n", OChars);

My output looks like this: hello

╧4▀↑█⌐

This matches your output but all except the first character. I am convinced the algorithm looks correct and I can't spend any more time on it. I believe it can be differences in character sets. Try it out.

Good luck!



来源:https://stackoverflow.com/questions/29921422/high-level-to-asm-conversion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!