Hey guys. I've been screwing around with inline asm in VC++ and I was having a bit of fun with calling and stack manipulation, even using dll API without even calling the dll.
Anyways, I recently finished a project, and built it as release. It was working fine in debug mode so I thought it'd be fine, so I run the exe from its folder and I get an access violation error..?
It didn't take long to realise that the compiler was removing what it thought was scrap data. You see I'm calling asm functions using "call", it's very similar to "goto" if you aren't aware of it. So I'm calling data I put into inaccesable if(0) statements and that way it won't get read unless I call it.
But I've figured the compiler thinks that because theres an if(0) there, the data in the brackets will never be used, and is therefore ignored.
So if any of you out there know: how can I fool the compiler into letting me keep this 'dummy data?'
That'd be great.
wildfrog
March 6th, 2006, 07:19 AM
You can use the optimize (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/pragm_21.asp) pragma to override the compier optimization settings:
#pragma optimize("", off)
void test()
{
return;
int d = 4;
int e = 5;
}
#pragma optimize("", on)
- petter
Mike Harnad
March 6th, 2006, 09:35 AM
Keep in mind, Debug builds will initialize variables and pointers for you. This will not happen in release build. These are typical symptoms of an "access violation". For more ideas, look here (http://www.codeguru.com/forum/showthread.php?t=269905) .
TiMBuS
March 7th, 2006, 05:41 PM
Keep in mind, Debug builds will initialize variables and pointers for you. This will not happen in release build. These are typical symptoms of an "access violation". For more ideas, look here (http://www.codeguru.com/forum/showthread.php?t=269905) .
Thanks for the heads up, but it was as I thought, the data was being dumped. I even tried tricking the compiler into keeping the data by using an if(DummyVar), and setting the dummy variable in different spots in the program, but the compiler still somehow knew it was "useless data"
Odd that it doesn't realise the label in there. Oh well, with optimision off it works just fine. Thanks!
ovidiucucu
March 8th, 2006, 06:36 AM
That's it. Compilers become smarter and smarter and harder to be fooled, except if you kindly say "please, please, don't make optimizations!" ;)
VladimirF
March 8th, 2006, 01:02 PM
I would try:volatile bool b(false);
if(b)
; // your code here
TiMBuS
March 8th, 2006, 05:40 PM
volatile hey?
I'll try it when I get home, tell you if it works..
TiMBuS
March 9th, 2006, 12:52 AM
Works! Woohoo!
VladimirF, collect 10 points.
VladimirF
March 9th, 2006, 01:48 AM
Works! Woohoo!
VladimirF, collect 10 points.
Cool. 10 you said??? Hmmm... :)
ovidiucucu
March 9th, 2006, 03:46 AM
Works! Woohoo!
VladimirF, collect 10 points.
Yeah, declaring volatile is yet another way to tell compiler "please, do not optimize this!".
However, I would preffer the #pragma optimize way stated by wildfrog (I hope you gave him at least a 5 ;)) because shows clearer what's the intention there.
But if you want to make a code already tricky even more tricky, it's your choice.
BTW. Was it a quiz?
VladimirF
March 9th, 2006, 10:21 PM
...I would preffer the #pragma optimize way stated by wildfrog (I hope you gave him at least a 5 ;)) because shows clearer what's the intention there.
But if you want to make a code already tricky even more tricky, it's your choice.
Tricky? Here is from MSDN:
The volatile type qualifier declares an item whose value can legitimately be changed by something beyond the control of the program in which it appears, such as a concurrently executing thread.
The compiler assumes that, at any point in the program, a volatile variable can be accessed by an unknown process that uses or modifies its value. Therefore, regardless of the optimizations specified on the command line, the code for each assignment to or reference of a volatile variable must be generated even if it appears to have no effect.
The volatile type specifier can be used to provide reliable access to special memory locations. Use volatile with data objects that may be accessed or altered by signal handlers, by concurrently executing programs, or by special hardware such as memory-mapped I/O control registers.
TiMBuS
March 9th, 2006, 10:42 PM
Lol, no it wasn't a quiz =P
I find volatile much better than the "optimise off" method, simply because it still allows the rest of the code to be compacted. If I have assembly language in main, for instance, I have to turn optimise off for the whole main function. You can't 'call' outside of a function (Well you can but C won't recognise the label, so its not favourable at all.) So you need anything you call to inside that function as well. So no unoptimised dummy functions.
You're right. Wildfrog gets 5 points too lol. XD
ovidiucucu
March 10th, 2006, 03:54 AM
Tricky? Here is from MSDN:
The volatile type qualifier [...]
Yeah, tricky code meaning a code that works, does something, but makes everyone else scraping on the head to get the point.
However, can be avoided that, if it's well commented, of course including huge quotes above from MSDN about "volatile". :D ;)
VladimirF
March 10th, 2006, 12:50 PM
Yeah, tricky code meaning a code that works, does something, but makes everyone else scraping on the head to get the point.
However, can be avoided that, if it's well commented, of course including huge quotes above from MSDN about "volatile". :D ;)
C'mon now! "Volatile" is one of only 32 C-language keywords, and one of TWO its type qualifiers – the other one is “const”.
In the spirit of equality, I promise to comment all of my volatile keywords when you comment all of your const’s ;) :wave:
wildfrog
March 12th, 2006, 09:43 PM
The compiler assumes that, at any point in the program, a volatile variable can be accessed by an unknown process that uses or modifies its value. Therefore, regardless of the optimizations specified on the command line, the code for each assignment to or reference of a volatile variable must be generated even if it appears to have no effect.
volatile bool b(false);
if(b)
; // your code here
Ok, Timbus got the correct results, but still I got some doubts conserning your code sample. I've did some tests, with and without optimizations, and it seems that even if b is volatile or not, the 'your code here' part is optimized away if it 'appears to have no effect'.
This code:
volatile bool b(false);
if (b)
{
int a = 5;
a += 5;
}
would generate something like this (no optimizations)
volatile bool b(false);
mov byte ptr [b],0
if (b)
movzx eax,byte ptr [b]
test eax,eax
je a+22h
{
int a = 5;
mov dword ptr [a],5
a += 5;
mov ecx,dword ptr [a]
add ecx,5
mov dword ptr [a],ecx
}
And with optimizations:
volatile bool b(false);
mov byte ptr [b],0
if (b)
mov al,byte ptr [b]
{
int a = 5;
a += 5;
}
Looking at the last result, the only thing that's left of the if-statement and its following then-clause is mov al,byte ptr [b]. It simply loads the value if b into a register and don't even bother to test its value. To me it's just a waste of clock cycles...
- petter
VladimirF
March 13th, 2006, 12:33 AM
Ok, Timbus got the correct results, but still I got some doubts conserning your code sample. I've did some tests, with and without optimizations, and it seems that even if b is volatile or not, the 'your code here' part is optimized away if it 'appears to have no effect'...
He was doing inline asm; I don't think it gets optimized...
Looking at the last result, the only thing that's left of the if-statement and its following then-clause is mov al,byte ptr [b]. It simply loads the value if b into a register and don't even bother to test its value. To me it's just a waste of clock cycles...
Not sure about that... May be they want to keep the result of if() in EAX for some reason?
ovidiucucu
March 13th, 2006, 05:22 AM
[ Redirected thread ]
/let's see also the opinion of assembly guys. ;)
wildfrog
March 13th, 2006, 10:59 AM
Not sure about that... May be they want to keep the result of if() in EAX for some reason?
Maybe... but then I tried this piece of code:
__declspec(noinline) void test()
{
volatile long a, b, c, d;
int x;
if (a) x = 1;
if (b) x = 2;
if (c) x = 3;
if (d) x = 4;
}
Here I'm using long (instead of bool).
The non-optimized result looks like this:
__declspec(noinline) void test()
{
push ebp
mov ebp,esp
sub esp,14h
volatile long a, b, c, d;
int x;
if (a) x = 1;
cmp dword ptr [a],0
je test+13h
mov dword ptr [x],1
if (b) x = 2;
cmp dword ptr [b],0
je test+20h
mov dword ptr [x],2
if (c) x = 3;
cmp dword ptr [c],0
je test+2Dh
mov dword ptr [x],3
if (d) x = 4;
cmp dword ptr [d],0
je test+3Ah
mov dword ptr [x],4
}
mov esp,ebp
pop ebp
ret
The optimized result looks like this:
__declspec(noinline) void test()
{
push ecx
volatile long a, b, c, d;
int x;
if (a) x = 1;
mov eax,dword ptr [a]
if (b) x = 2;
mov ecx,dword ptr [b]
if (c) x = 3;
mov edx,dword ptr [c]
if (d) x = 4;
mov eax,dword ptr [d]
}
pop ecx
ret
Again you see that all that is left of the if-statements are some simple mov instructions moving the volatile variable into a register. At closer look you'll also see that the eax register is used twice, both by if(a) and if(d), thus the latter one renders the first one useless. The same is happening with mov ecx and pop ecx. It is tempting to believe that this is some processor cache flushing stuff, but as far as I know you'll need interlocked operations to do that.
So,
May be they want to keep the result of if() in EAX for some reason?Apparently not... In my oppinion the movs are just a waste of time.
He was doing inline asm; I don't think it gets optimized...
You're right about that, inlined asm is not optimized; see Optimizing Inline Assembly (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core_Optimizing_Inline_Assembly.asp). But my understanding of the OPs situation was that he was accessing c++ code from inlined assembly, and that it was the c++ code that was optimized away. Ofcourse in his case it was due to a enclosing if(0), but on a more general level the code might be thrown away for all kinds of reasons.
So, my conclusion so far is that if(volatile) won't help you much when it comes to avoiding optimizations; except if it's used instead of if(const). In any case, the then-clause is optimized (and possibly thrown away).
- petter
VladimirF
March 13th, 2006, 01:03 PM
... But my understanding of the OPs situation was that he was accessing c++ code from inlined assembly, and that it was the c++ code that was optimized away. Ofcourse in his case it was due to a enclosing if(0), but on a more general level the code might be thrown away for all kinds of reasons.
So, my conclusion so far is that if(volatile) won't help you much when it comes to avoiding optimizations; except if it's used instead of if(const). In any case, the then-clause is optimized (and possibly thrown away).
- petter
Petter, I agree with your analysis.
You are right, the optimized compiler appears to be "confused" by volatile variables, leaving unneeded code.
However, my understanding of OP's original question is that he wanted to preserve otherwise meaningful code that was thrown out by compiler simply because of condition that evaluated to false.
If that was the case, my solution offers a benefit of actually optimizing code inside that if() statement (that was mentioned somewhere above in this thread).
Looks like we took different guesses at what OP wanted to do... Guess, we will never know... :cry:
codeguru.com
Copyright WebMediaBrands Inc., All Rights Reserved.