How to convert for loop in c++ to assembler? - c++

I am trying to convert the procedure encrypt_chars to assembler. I already have some x86 in assembly in the for loop, however I am trying to convert the remainder of the procedure into assembler. I'd be appreciative if you could help me
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]; //
__asm { //
push eax // save register values on stack to be safe
push ecx //
//
movzx ecx,temp_char // set up registers (Nb this isn't StdCall or Cdecl)
lea eax,EKey //
call encrypt12 // encrypt the character
mov temp_char,al //
//
pop ecx // restore original register values from stack
pop eax //
}
EChars [i] = temp_char; // Store encrypted char in the encrypted chars array
}

Next is the code for the "for" statement converted into assembler, register EDI is used as the control variable "i", if EDI is been changed by "encrypt21", just push it before and pop it after "call encrypt21" to preserve-restore its value. I changed the parameter "length" by "len" because the name gave me problems :
void encrypt_chars(int len, char EKey)
{ char temp_char;
__asm { mov edi, 0 ;FOR ( EDI = 0;
fori:
;GET CURRENT CHAR.
mov al, OChars[edi]
mov temp_char, al
;ENCRYPT CURRENT CHAR.
push eax // save register values on stack to be safe
push ecx
movzx ecx,temp_char // set up registers (Nb this isn't StdCall or Cdecl)
lea eax,EKey
call encrypt12 // encrypt the character
mov temp_char,al
pop ecx // restore original register values from stack
pop eax
;STORE ENCRYPTED CHAR.
mov al, temp_char
mov EChars[ edi ], al
;FOR STATEMENT : FOR ( EDI = 0; EDI < LEN, EDI++ )
inc edi ;EDI++.
cmp edi, len
jb fori ;IF ( EDI < LEN ) JUMP.
}
return;
}

Related

X86 assembly cdecl confusion

Morning, I've implemented a cdecl call method into the following 'encryption' routine. However whilst my method works, it's not following the recommended (uni and other sources) exactly.
Advise appreciated (Some comments may be 'wrong' cdecl related functs have be marked for)
My confusion is that I've been told that for each parameter pushed (in this case 2) I must push before the call, push again inside the funct, then do mov [ebp+n] for each additional push - before the main body.
However if I follow the logic of : do a mov ebp shift for every push - without adding additional pushes, all works fine. But this could well be an error.
If required I can post some of reference docs.
code extract:
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
// Note the lamentable lack of comments below!
__asm { //
push eax //making a copy of char to be encrypted index
push ecx //making a copy of the char to be encrypted
//
movzx ecx,temp_char //padding out temp_char
lea eax,EKey //moving Ekey adress to eax, for function to use, eax contents acting as perameter
call encrypt6 //Doing the encryption
add esp, 8 //cdecl added stack pointer baxk
mov temp_char,al //Move the encrypted result into temp_char
pop ecx //resetting registers to before call
pop eax //
}
EChars [i] = temp_char; // Store encrypted char in the Encrypted Chars array
}
return;
// Encrypt subroutine. You should paste in the encryption routine you've been allocated from Bb and
// overwrite this initial, simple, version. Ensure you change the ‘call’ above to use the
// correct 'encryptnn' label where nn is your encryption routine number.
// 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 {
encrypt6:
push ebp //cdecl Making a copy of base pointer
mov ebp, esp //cdecl storing the point at which the base pointer has shifted the stack
// push ecx //cdecl
// push eax //cdecl
// mov ecx, [ebp + 12] // cdecl storing Ekey adress
// mov eax, [ebp + 8] //cdecl storing temp_char data
ror byte ptr[eax], 1 //Rotating the EKey data right 6 times
ror byte ptr[eax], 1 //
ror byte ptr[eax], 1 //
ror byte ptr[eax], 1 //
ror byte ptr[eax], 1 //
push ecx //Making a copy of ecx
mov ecx, [ebp + 8] // cdecl ,
not byte ptr[eax] //Inverting the Ekey data
movzx edx, byte ptr[eax] //making a copy of the ekey data with leading zero's
pop eax //restoring register to thet temp_char ascii value
xor eax, edx //XORing original temp_char with encrypted temp_Char
ror al, 1 //Rotating the Ekey adreses 8 bit component right twice (To edit)
ror al, 1 //
not al // Inverting the result
add eax, 0x20 // adding a space (32) to result
pop ebp //cdecl ,pop ebp
ret //cdecl
//----
}

High Level to ASM conversion

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
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!

Converting this C++ for loop into assembly language [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Basically what I am trying to do is convert this block of c++ & assembly into purely assembly, I am a bit confused as to how to conver the for loop and the rest into assembly, if anyone could let me know where I am going wrong that would be great.
This is the original
void encrypt_chars (int length, char EKey) // Encryption Function.
{ char temp_char; // Char temporary store.
for (int i = 0; i < length; i++) // Encrypt characters one at a time.
{
temp_char = OChars [i]; // Orignal Chars.
__asm { // Switch to inline assembly.
push eax
push ecx
movzx ecx,temp_char
push ecx
lea eax,EKey
push eax
call encrypt4 // Call the encryption subroutine
add esp, 8
mov temp_char,al
pop ecx
pop eax
}
EChars [i] = temp_char; // Store encrypted char in the encrypted chars array.
}
return;
Then this is my attempt at convering the c++ parts into assembly which is what I am stuggling with and would appreciate some pointers -
void encrypt_chars(int lengths, char EKey) // Encryption Function.
{
char temp_char;
__asm {
mov dword ptr[i], 0
jmp encrypt_chars
mov eax, dword ptr[i]
add eax, 1
mov dword ptr[i], eax
mov eax, dword ptr[i]
cmp eax, dword ptr[lengths]
jge encrypt_chars
mov eax, dword ptr[i]
mov cl, byte ptr[eax]
mov byte ptr[temp_char], cl
push eax
push ecx
movzx ecx,temp_char
push ecx
lea eax,EKey
push eax
call encrypt4 // Call the encryption subroutine
add esp, 8
mov temp_char,al
pop ecx
pop eax
mov eax, dword ptr[i]
mov cl, byte ptr[temp_char]
mov byte ptr[eax], cl
}
return;
Here is an assembly example of a for loop:
mov R1, #5 ; This is the limit of the loop
mov R0, #0 ; R0 is the loop index, initialize the loop index variable.
loop:
cmp R0, R1 ; Part of the compare expression in for loop.
bge loop_exit;
;
; The statement block for the for loop.
inc R0 ; The increment part of the for loop
b loop ; Loop around to the compare part of the loop.
; First statement after the for loop
loop_exit:

Creating loop in x86 assembly and use of arrays? [duplicate]

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.
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.
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?

Assembly encryption decryption program

The following program compiles and works.
However I cannot figure out what to write for the decryption section.
Can anybody please help me write the corresponding decrypt_chars() routine?
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];
__asm {
push eax // save register values on stack to be safe
push ecx //
movzx ecx, temp_char //
lea eax, EKey
call encrypt // encrypt the character
mov temp_char, al
pop ecx // restore original register values from stack
pop eax //
}
EChars[i] = temp_char; // Store encrypted char in the encrypted chars array
}
return;
// --- Start of Assembly code
__asm {
// 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).
encrypt5: push eax
mov al, byte ptr[eax]
push ecx
and eax, 0x7C
ror eax, 1
ror eax, 1
inc eax
mov edx, eax
pop ecx
pop eax
mov byte ptr[eax], dl
xor edx, ecx
mov eax, edx
rol al, 1
ret
encrypt:
mov eax, ecx // get character
inc eax
ret
}
//--- End of Assembly code
}
// end of encrypt_chars function
void decrypt_chars(int length, char EKey)
{
/* needs to be written */
return;
}
As it stands right now, it appears that decryption is almost ridiculously trivial. Although the encrypt5 code attempts to do something rather more elaborate, all that seems to actually be used here is the encrypt routine, which simply increments each input (ignoring the key completely), so A becomes B, B becomes C, and so on.
As such, the decryption routine can be equally trivial:
void decrypt(char *data, int length) {
for (int i=0; i<length; i++)
--data[i];
}
If you really insist on doing this in assembly language, the core would look something like this:
_asm {
mov eax, ecx
dec eax
ret
}
Then you'd do like with the encryption, and invoke that once for each character in the input string.
When/if the encryption is fixed to do something more than just incrementing each input character, the decryption will need to be updated to match. Of course, as it stands right now this encryption doesn't deserve the name "encryption" at all--since it has no key, it offers precisely zero security.