how to set labels in inline assembly? - visual-c++

how in c++ visual can i set labels for when i need to use inline assembly, so it would look like something like this for example...
__asm
{
PUSH EAX
PUSH VAR1
MOV ECX,DWORD PTR DS:[VAR2]
CALL DWORD PTR DS:[VAR3]
JMP VAR4
}
where the VAR varables link to a value or address?
i have tried the following
DWORD VAR2 = 0x991770; //0x991770 is the location of the function
__asm
{
..code
MOV ECX,DWORD PTR DS:[VAR2]
..code
}
but then the app crashes, how is this done?

Use offset variableName to access variables from inline assembly. See reference here.
Example:
char format[] = "%s %s\n";
char hello[] = "Hello";
char world[] = "world";
int main( void )
{
__asm
{
mov eax, offset world
push eax
mov eax, offset hello
push eax
mov eax, offset format
push eax
call printf
//clean up the stack so that main can exit cleanly
//use the unused register ebx to do the cleanup
pop ebx
pop ebx
pop ebx
}
}

C variable names are visible in inline assembly. So if you need data access, just write the var name:
int var2 = 3;
__asm
{
mov ecx, var2
That will compile to the appropriate memory access statement.
For code labels - you just declare them, like in real assembly:
Label1:
mov ecx, 0
jmp Label1
External functions are seen as labels, too. Name mangling applies, though.
If you need the numeric value of the current IP as a general purpose register, there's no direct command, but a very simple workaround is available:
call Next
Next:
pop eax ; eax now is the value of IP at the current point
Oh, and forget about the ds: stuff. You're in Flatland now - check your segment registers at the door.

Related

Loading a value from an array without its address

I have this code:
int arr[] = { 299, 3190, 4892, 256};
__asm
{
MOV EAX, DWORD PTR[arr] // EAX will be our number.
MOV EAX, [EAX] // Setting EAX to where it's pointing.
}
I need EAX to be the first number in the array, but I don't want this to be in 2 lines of code (obviously if there's another way, it'll be better.)
I'm no amateur in ASM, but I forgot it mostly, and I need some refreshments. Is there a way to do this in a single line of code? Thanks!
EDIT:
The compiler is MASM x86, the one given in Visual Studio.
Just remove your second line of assembly code :
int arr[] = { 299, 3190, 4892, 256};
__asm
{
MOV EAX, DWORD PTR[arr] // ◄■■■ HERE EAX GETS THE FIRST ARRAY VALUE.
MOV EAX, [EAX] // ◄■■■ UNNECESSARY!
}
When you move DWORD PTR[arr] into EAX, you are actually moving the first value of the array into EAX. You don't need the address because arr already points to its first value.

(VC++) Runtime Check for Uninitialized Variables: How is the test Implemented?

I'm trying to understand what this test does exactly. This toy code
int _tmain(int argc, _TCHAR* argv[])
{
int i;
printf("%d", i);
return 0;
}
Compiles into this:
int _tmain(int argc, _TCHAR* argv[])
{
012C2DF0 push ebp
012C2DF1 mov ebp,esp
012C2DF3 sub esp,0D8h
012C2DF9 push ebx
012C2DFA push esi
012C2DFB push edi
012C2DFC lea edi,[ebp-0D8h]
012C2E02 mov ecx,36h
012C2E07 mov eax,0CCCCCCCCh
012C2E0C rep stos dword ptr es:[edi]
012C2E0E mov byte ptr [ebp-0D1h],0
int i;
printf("%d", i);
012C2E15 cmp byte ptr [ebp-0D1h],0
012C2E1C jne wmain+3Bh (012C2E2Bh)
012C2E1E push 12C2E5Ch
012C2E23 call __RTC_UninitUse (012C10B9h)
012C2E28 add esp,4
012C2E2B mov esi,esp
012C2E2D mov eax,dword ptr [i]
012C2E30 push eax
012C2E31 push 12C5858h
012C2E36 call dword ptr ds:[12C9114h]
012C2E3C add esp,8
012C2E3F cmp esi,esp
012C2E41 call __RTC_CheckEsp (012C1140h)
return 0;
012C2E46 xor eax,eax
}
012C2E48 pop edi
012C2E49 pop esi
012C2E4A pop ebx
012C2E4B add esp,0D8h
012C2E51 cmp ebp,esp
012C2E53 call __RTC_CheckEsp (012C1140h)
012C2E58 mov esp,ebp
012C2E5A pop ebp
012C2E5B ret
The 5 lines emphasized are the only ones removed by properly initializing the variable i. The lines 'push 12C2E5Ch, call __RTC_UninitUse' call the function that display the error box, with a pointer to a string containing the variable name ("i") as an argument.
What I can't understand are the 3 lines that perform the actual test:
012C2E0E mov byte ptr [ebp-0D1h],0
012C2E15 cmp byte ptr [ebp-0D1h],0
012C2E1C jne wmain+3Bh (012C2E2Bh)
It would have seemed the compiler is probing the stack area of i (setting a byte to zero and immediately testing whether it's zero), just to be sure it isn't initialized somewhere it couldn't see during build. However, the probed address, ebp-0D1h, has little to do with the actual address of i.
Even worse, it seems if there were such an external (other thread?) initialization that did initialize the probed address but to zero, this test would still shout about the variable being uninitialized.
What's going on? Maybe the probe is meant for something entirely different, say to test if a certain byte is writable?
[ebp-0D1h] is a temporary variable used by the compiler to track "initialized" status of variables. If we modify the source a bit, it will be more clear:
int _tmain(int argc, _TCHAR* argv[])
{
int i, j;
printf("%d %d", i, j);
i = 1;
printf("%d %d", i, j);
j = 2;
return 0;
}
Produces the following (irrelevant parts skipped):
mov DWORD PTR [ebp-12], -858993460 ; ccccccccH
mov DWORD PTR [ebp-8], -858993460 ; ccccccccH
mov DWORD PTR [ebp-4], -858993460 ; ccccccccH
mov BYTE PTR $T4694[ebp], 0
mov BYTE PTR $T4693[ebp], 0
In prolog, variables are filled with 0xCC, and two tracking variables (one for i and one for j) are set to 0.
; 7 : printf("%d %d", i, j);
cmp BYTE PTR $T4693[ebp], 0
jne SHORT $LN3#main
push OFFSET $LN4#main
call __RTC_UninitUse
add esp, 4
$LN3#main:
cmp BYTE PTR $T4694[ebp], 0
jne SHORT $LN5#main
push OFFSET $LN6#main
call __RTC_UninitUse
add esp, 4
$LN5#main:
mov eax, DWORD PTR _j$[ebp]
push eax
mov ecx, DWORD PTR _i$[ebp]
push ecx
push OFFSET $SG4678
call _printf
add esp, 12 ; 0000000cH
This corresponds roughly to:
if ( $T4693 == 0 )
_RTC_UninitUse("j");
if ( $T4694 == 0 )
_RTC_UninitUse("j");
printf("%d %d", i, j);
Next part:
; 8 : i = 1;
mov BYTE PTR $T4694[ebp], 1
mov DWORD PTR _i$[ebp], 1
So, once i is intialized, the tracking variable is set to 1.
; 10 : j = 2;
mov BYTE PTR $T4693[ebp], 1
mov DWORD PTR _j$[ebp], 2
Here, the same is happening for j.
Here is my guess: the compiler probably allocates flags in memory showing the initialization status of variables. In your case for variable i this is a single byte at [ebp-0D1h]. The zeroing of this byte means i is not initialized. I assume if you initialize i this byte will be set to non-zero. Try something run-time like this: if (argc > 1) i = 1; This should generate code instead of omitting the whole check. You can also add another variable, and see if you get two different flags.
The zeroing of the flag and the testing just happen to be consecutive in this case, but that might not always be the case.
C7060F000055 mov dword ptr [esi],5500000Fh
C746048BEC5151 mov dword ptr [esi+0004],5151EC8Bh
b. And one of its later generations:
BF0F000055 mov edi,5500000Fh
893E mov [esi],edi
5F pop edi
52 push edx
B640 mov dh,40
BA8BEC5151 mov edx,5151EC8Bh
53 push ebx
8BDA mov ebx,edx
895E04 mov [esi+0004],ebx
c. And yet another generation with recalculated ("encrypted") "constant" data:
BB0F000055 mov ebx,5500000Fh
891E mov [esi],ebx
5B pop ebx
51 push ecx
B9CB00C05F mov ecx,5FC000CBh
81C1C0EB91F1 add ecx,F191EBC0h ; ecx=5151EC8Bh

Replace a character in a string using assembly code in MASM

So my program is very simple. I have a string "Hello World" and I want to replace 'H' with 'A'. So here is my assembly code for MASM.
char* name = "Hello World";
_asm
{
mov eax, name;
mov ebx, 'A';
mov [eax], ebx;
}
printf("%s", name);
Visual Studio cannot compile this. It alerts me that this program is not working. I suspect my syntax for mov[eax], ebx might be wrong. All comments are appreciated. Thanks!
Here is the image of the alert: https://www.dropbox.com/s/e5ok96pj0mxi6sa/test%20program%20not%20working.PNG
"Hello World" is a literal, i.e a non-writeable constant string. 'name' is a pointer which points to that literal. You can instead define an array, which has to be populated with that literal, i.e. the literal is copied into the array:
#include <stdio.h>
int main (void)
{
char name[] = "Hello World";
_asm
{
lea eax, name; // EAX = address of name
mov ebx, 'A';
mov [eax], bl;
}
printf("%s", name);
return 0;
}
The original code works, if you use the C89-Compiler of MSVC (file-extension .c or command line option /TC), but that does not really meet the standard.
First Character
mov eax, _name; // EAX = address of name
mov bl, 'A';
mov byte[eax], bl;
Second Character
mov eax, _name; // EAX = address of name
mov bl, 'A';
mov byte[eax+1], bl;
MOVS
MOVS - This instruction moves 1 Byte, Word or Doubleword of data from memory location to another.
LODS
LODS - This instruction loads from memory. If the operand is of one byte, it is loaded into the AL register, if the operand is one word, it is loaded into the AX register and a doubleword is loaded into the EAX register.
STOS
STOS - This instruction stores data from register (AL, AX, or EAX) to memory.
CMPS
CMPS - This instruction compares two data items in memory. Data could be of a byte size, word or doubleword.
SCAS
SCAS - This instruction compares the contents of a register (AL, AX or EAX) with the contents of an item in memory.

Inline assembly operand size conflict

I am working on this for class, and as per the instructors guidelines we have to do the program using inline c++. The purpose of the program is to take a string of any length and reverse it. The error I'm getting is an operand size conflict and from what I can tell it's in the first line of the __asm block, there could be other issues but the only one that shows up in visual studio is the conflict. Here is my asm block
int _tmain(int argc, _TCHAR* argv[])
{
char string[] = "Hi There!";
__asm
{ // reverse a string of any length
lea ecx, string
lea eax, string
mov esi, eax // esi points to start of string
add eax, ecx
mov edi, eax
dec edi // edi points to end of string
shr ecx, 1 // ecx is count (length/2)
jz done // if string is 0 or 1 characters long, done
reverseLoop:
mov al, [esi] // load characters
mov bl, [edi]
mov [esi], bl // and swap
mov [edi], al
inc esi // adjust pointers
dec edi
dec ecx // and loop
jnz reverseLoop
done:
}
printf(string);
return 0;
}
I made the changes now I am getting this: Unhandled exception at 0x00e71416 in String Reverse.exe: 0xC0000005: Access violation reading location 0x0087ef6f. Based on other suggestions I have tried I have still not be able to get it to run properly. I think the issue might be in the registers I'm referencing or the add eax line, but I'm not really sure.
mov ecx, [string]
"string" is an array of char, you are trying to move 8 bits into a 32-bit register. If is was a global variable you'd use the offset keyword. But it is not, it is stored on the stack. Which requires you to use the LEA instruction (load effective address), like this:
lea ecx,string
which the compiler automatically translates into something like:
lea ecx,[ebp-20]
with the -20 adjustment depending on where it is located on the stack. The ECX register now points to the first char in the string.

Inline assembly crashs?

I have problems with inline assembly in visual c++ 2010 Ultimate (Windows 7 Professional). All my inline assemblies don't work, when I use chars, DWORD strings etc etc... So I copied this code from MSDN in my console application:
// InlineAssembler_Calling_C_Functions_in_Inline_Assembly.cpp
// processor: x86
#include <stdio.h>
char format[] = "%s %s\n";
char hello[] = "Hello";
char world[] = "world";
int main( void )
{
__asm
{
mov eax, offset world
push eax
mov eax, offset hello
push eax
mov eax, offset format
push eax
call printf
//clean up the stack so that main can exit cleanly
//use the unused register ebx to do the cleanup
pop ebx
pop ebx
pop ebx
}
}
I have nothing except those lines in my application, result: The string doesn't get printed and the application crashs. Any ideas why this happens?
Project + Properties, C/C++, Code Generation, select /MTd. Repeat for the Release configuration, select /MT.
If you want to make it work with the non-static version of the CRT then you'll need to write the call like this:
call dword ptr printf
Exports from a DLL need to be called indirectly.
I am assuming that popping into ebx is the reason. It is Your responsibility to maintain the integrity of all registers, excluding eax. Try popping into eax instead.

Resources