cdecl and std call - how to make my code conventional - c++

__asm { //
push eax //
push ecx //
movsx ecx, temp_char //
lea eax, EKey //
call encryptX // encrypt the character
mov temp_char, al //
pop ecx //
pop eax //
}
EChars[i] = temp_char; // Store encrypted char in the encrypted chars array
}
return;
// ---------------------------- start of ASM code ---------------------------------------------------------------encryptX: push ecx //push to manipulate
xchg eax, ecx //exchange values in eax and ecx / eax holds old ecx
neg al //twos complement least most eax byte (old ecx)
ror al, 1 //rotate right least most byte by 1 of eax
xor al, byte ptr[ecx] //exlcusive or least most byte against ecx value being pointed at
push edx //push edx onto stack for manipulatio
mov edx, eax //move eax into edx
xchg eax, ecx //swap values of ecx and eax
rol byte ptr[eax], 3 //rotate left the byte being pointed at 3 times
xor dl, byte ptr[eax] //xor the least byte by pointed value in eax
rol dl, 2 //rotate left the least byte in edx by 2
mov eax, edx //move edx value into eax
pop edx //pop values out
pop ecx //pop values out
ret //return
}
i have the task of implementing a standard call in this code - be that cdecl or std call
'mov eax, [ebp+8] // get first parameter that was pushed'
i understand the idea of pushing the pointers location but i am unsure of where i would tell the pointer to look.
be that mov eax, [ebp+4/8/12] or what have you
any help in telling me how i would do this would be greatly appreciated, similarly if one of you kind folk do solve this could an explanation be added
Thanks

Related

Assembly: Write into a character array passed as a parameter from C++

I am writing an assembly function callable from C++ that will read the CPU Vendor ID. Here is the function signature:
extern "C" void GetVendorID(const char* id);
Here is how I am calling it:
char vendorID[13];
GetVendorID(vendorID);
vendorID[12] = '\0';
Here is the important parts of the assembly:
global GetVendorID
GetVendorID:
push ebp
mov ebp, esp
push eax
push ebx
push ecx
push edx
mov eax, 0
cpuid ; <- this instruction moves the vendor id into ebx, edx, ecx
mov eax, [ebp + 8] ; <- move the value of the char pointer parameter into eax
; I have verified that this instruction works by returning eax and comparing it to the
; address of the vendorID array
; start with ebx
mov byte [eax], bl ; <- move a character into the char array
inc eax ; <- increment the pointer
shl ebx, 8 ; <- shift ebx to get the next character in its least significant bits
mov byte [eax], bl ; <- repeat
inc eax
shl ebx, 8
mov byte [eax], bl
inc eax
shl ebx, 8
mov byte [eax], bl
inc eax
shl ebx, 8
; above is repeated for edx and ecx
pop edx
pop ecx
pop ebx
pop eax
mov esp, ebp
pop ebp
ret
The way the string is stored in the registers is weird. The first character is stored in the least significant byte of ebx, the next is stored in the second least significant byte, and so on. That is why I am doing the left shifts.
I have verified that ebx, edx, ecx do contain the correct values by returning them from the function and printing them out. They contain "GenuineIntel". However, the char array remains unchanged. It is full of zeroes after the function returns.
I am not really sure why this isn't working. Am I accessing the parameter incorrectly?

Run-Time Check Failure #0. Lost as to how to use CDECL

I've been asked with changing some __asm code so that it implements a C++ calling convention. I've tried using cdecl but I keep getting this error
Run-Time Check Failure #0: The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
The code is used to encrypt a string one character at a time using a for loop. The function encrypt_1 encodes the character that is passing through the for loop at the time.
I've attempted to use cdecl by assigning different values to the base pointer (ebp) and the stack pointer (esp) for both the for loop and the function but I'm continuously getting Run-Time Check Failure #0, and every attempt I've made to tweak it results in the program breaking. I've been stressing over this for a couple of days, can anybody give me a hint as to where I may be going wrong?
The Body:
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
// Each character in the string will be encrypted individually
__asm
{ //
push eax // Stores a backup of the location of eax to be used later
push ecx // Stores a backup of the charcter to be encrypted in the stack for later use
push edx // Stores a backup of the location for the encrypted character in the stack for later use
//
movzx ecx, temp_char // Places the character (8 bits) to be encrypted in the ecx register (32 bits) and replaces any extraneous bits with 0 as they are not being used.
lea eax, EKey // places the Ekey in the eax register for later use. Registers are fast than calling variables?
push ebp
mov ebp, esp
// sub esp, 4
push ecx // Parameter for encrypt1. - Temporary Character
push eax // Parameter for encrypt1. - Address for the key.
call encrypt_1 // Begins the Encryption Function
mov temp_char, dl // Stores the encrypted character in the temp_char variable to be reconstruced later
add esp, 8
pop eax // Restoring eax to previous location before parameter call
pop ecx // Restores Temporary Character location before parameter call
pop edx // Restores the edx register to its original value, ready for the next character
pop ecx // Restores the ecx register to its original value, ready for the next character
pop eax // Restores the eax register to its original value, ready for the next character
mov esp, ebp
pop ebp
// ret
}
EChars[i] = temp_char; // Store encrypted char in the Encrypted Chars array
}
return;
The Function:
__asm
{
encrypt_1:
push ebp //Saves the present value of ebp on the stack for later use
mov ebp, esp //Places the stack pointer where the base pointer is so variables can be stored
mov ecx, [ebp +08h]
mov edx, [ebp +0Ch]
push ecx // Stores the original character on the top of the stack
movzx ecx, byte ptr[eax] // Moves the Ekey (8-bit) into the ecx register (32-bit), changing all extraneous bits to 0 so it can be rotated
add cl, 0x01 // Adds 1 to Ekey
rol cl, 1 // Rotates the binary value of Ekey to the left 6 times for further security
rol cl, 1 // Could have just used "rol cl, 6"
rol cl, 1
rol cl, 1
rol cl, 1
rol cl, 1
mov edx, ecx // Move the encrypted Ekey to edx, freeing the ecx register for the original character to be used later.
mov byte ptr[eax], dl // Move byte pointer to the left side of eax
pop ecx // Retrieves the original character to be encrypted
x1 : rol cl, 1 // Rotate the original character one place to the left , encrypting it
dec edx // Decrease the rotated Ekey by one, acting as a counter to continue decrypting the original character
jnz x1 // Jump back to x1 unless the Ekey = 0, which dictates that the encryption is complete
add ecx, 0x20 // Add 32 bits to the encrypted character, filling the register
mov edx, ecx // Place the encrypted character in the edx register, ready to be returned
mov esp, ebp
pop ebp
//add esp, 8
ret // Return the encrypted character
}
//--- End of Assembly code
}
PS. Sorry for some of the messy commented out lines, I've been trying various things trying to get it to work.
There's no reason to write the call in assembly. You should change the calling code to:
EChars[i] = encrypt_1(&EKey, OChars[i]);
If for some reason you feel that you must write it in assembly, then you could write:
temp_char = OChars[i];
__asm
{
movzx ecx, temp_char
lea eax, EKey
push ecx // Second param: character to encrypt
push eax // First param: address of EKey.
call encrypt_1
mov temp_char, al
}
EChars[i] = temp_char;
The Function:
__asm
{
encrypt_1:
push ebp
mov ebp, esp
mov eax, [ebp+08h] // first param: address of EKey
mov dl, [ebp+0Ch] // second param: character to encrypt
mov cl, byte ptr [eax] // get value of EKey
add cl, 0x01
rol cl, 6
mov byte ptr [eax], cl // store updated value of EKey
rol dl, cl
add dl, 0x20
movzx eax, dl // Return encrypted character in eax
mov esp, ebp
pop ebp
ret
}
Other than simplification, the only things that I fixed were:
1. Use of eax without loading it within the function.
2. Reversed order of the function parameters.
3. The EKey parameter to the function wasn't used at all.

C++ assembler conversion problems

little bit of a problem here, tried to create assembly code which converts strings to integers. Unfortunately, I cannot find the reason why it "breaks", I input 54321 and it converts to 543418. All goes OK till 2 and then it prints random numbers instead of printing the same 54321. I already spent an hour debugging, but cannot find the cause of this problem, maybe I'm blind?
#include <stdio.h>
#include <string.h>
#include "stdlib.h"
int main(int argc, char** argv)
{
int result;
char* argv1 = argv[1];
if (argc < 2)
{
printf("Parameter is not provided*/\n");
return(0);
}
__asm
{
push eax
push ebx
push ecx
mov ecx, argv1 // 54321 --> 5 *10+4=54 *10+3=543 *10+2=5432 *10+1=54321
mov ebx, 10 // register in which i put value
mov al, byte ptr[ecx] // byte of string to al
sub al, '0'
loop_begins:
mov dl, byte ptr [ecx] // byte of string to dl
cmp dl, 0 // compare to zero (string end)
je loop_ends // if zero byte (string end)
// here we make char out of int
xor edx, edx // zero edx
mul ebx // edx: eax = eax * ebx
inc ecx // ecx points to next char in string
mov dl, byte ptr [ecx] // dl - edx part, other register
sub dl, '0' // same, but other element
add eax, edx // addition (here we get 54)
xor edx, edx // zero edx
jmp loop_begins // and loop to next char
loop_ends:
mov [result], eax // answer to variable result
pop ecx
pop ebx
pop eax
};
printf("Answer is %d\n", result);
system("PAUSE");
}
I made a few modifications (<mod> in comments) to your code keeping the spirit (also according to my weak and unused for a long time asm knowledge ):
__asm
{
push eax // current value / result
push ebx // 10
push ecx // string
xor eax, eax // <mod> : reset eax
mov ebx, 10 // register in which i put value
mov ecx, argv1 // 54321 --> 5 *10+4=54 *10+3=543 *10+2=5432 *10+1=54321
// <mod> : unnecessary
// mov al, byte ptr[ecx] // byte of string to al
// sub al, '0'
loop_begins:
mov dl, byte ptr [ecx] // byte of string to dl
cmp dl, 0 // compare to zero (string end)
je loop_ends // if zero byte (string end)
// here we make char out of int
// xor edx, edx // zero edx // <mod> : unnecessary
mul ebx // edx: eax = eax * ebx
mov dl, byte ptr [ecx] // dl - edx part, other register
sub dl, '0' // same, but other element
add eax, edx // addition (here we get 54)
// xor edx, edx // zero edx // <mod> : unnecessary
inc ecx // ecx points to next char in string // <mod> moved as suggested in comments
jmp loop_begins // and loop to next char
loop_ends:
mov [result], eax // answer to variable result
pop ecx
pop ebx
pop eax
};

C/C++ Inline asm improper operand type

I have the following code, that is supposed to XOR a block of memory:
void XorBlock(DWORD dwStartAddress, DWORD dwSize, DWORD dwsKey)
{
DWORD dwKey;
__asm
{
push eax
push ecx
mov ecx, dwStartAddress // Move Start Address to ECX
add ecx, dwSize // Add the size of the function to ECX
mov eax, dwStartAddress // Copy the Start Address to EAX
crypt_loop: // Start of the loop
xor byte ptr ds:[eax], dwKey // XOR The current byte with 0x4D
inc eax // Increment EAX with dwStartAddress++
cmp eax,ecx // Check if every byte is XORed
jl crypt_loop; // Else jump back to the start label
pop ecx // pop ECX from stack
pop eax // pop EAX from stack
}
}
However, the argument dwKey gives me an error. The code works perfectly if for example the dwKey is replaced by 0x5D.
I think you have two problems.
First, "xor" can't take two memory operands (ds:[eax] is a memory location and dwKey is a memory location); secondly, you've used "byte ptr" to indicate you want a byte, but you're trying to use a DWORD and assembly can't automatically convert those.
So, you'll probably have to load your value into an 8-bit register and then do it. For example:
void XorBlock(DWORD dwStartAddress, DWORD dwSize, DWORD dwsKey)
{
DWORD dwKey;
__asm
{
push eax
push ecx
mov ecx, dwStartAddress // Move Start Address to ECX
add ecx, dwSize // Add the size of the function to ECX
mov eax, dwStartAddress // Copy the Start Address to EAX
mov ebx, dwKey // <---- LOAD dwKey into EBX
crypt_loop : // Start of the loop
xor byte ptr ds : [eax], bl // XOR The current byte with the low byte of EBX
inc eax // Increment EAX with dwStartAddress++
cmp eax, ecx // Check if every byte is XORed
jl crypt_loop; // Else jump back to the start label
pop ecx // pop ECX from stack
pop eax // pop EAX from stack
}
}
Although, it also looks like dwKey is uninitialized in your code; maybe you should just "mov bl, 0x42". I'm also not sure you need to push and pop the registers; I can't remember what registers you are allowed to clobber with MSVC++ inline assembler.
But, in the end, I think Alan Stokes is correct in his comment: it is very unlikely assembly is actually faster than C/C++ code in this case. The compiler can easily generate this code on its own, and you might find the compiler actually does unexpected optimizations to make it run even faster than the "obvious" assembly does (for example, loop unrolling).

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!