flat assembler
Message board for the users of flat assembler.

Index > Heap > HLLs suck!

Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next
Author
Thread Post new topic Reply to topic
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
Theoretically, _bar, _dummy and _foo could be changed from an external module - the compiler doesn't (and shouldn't) a source module specially just because it has a main() function. Link-time code generation could perform global analysis and determine that the pointers are never changed, though.

Adding the 'static' specifier to the function pointers lets the compiler know that the pointers can't be changed outside the current source module, but at least in the case of VC2008 this doesn't seem to help the optimizer - neither does LTCG. So perhaps there's some special reason why it doesn't optimize call-through-indirection, even if I can't think of a good reason.
Post 30 Nov 2009, 17:14
View user's profile Send private message Visit poster's website Reply with quote
Fanael



Joined: 03 Jul 2009
Posts: 168
Fanael
Ok, GCC 4.4.1 (with appropriate switches) now.
Code:
// slightly modified LocoDelAssembly's code
#include <stdio.h>

volatile int a = 1; 

void bar(void **p){ 

   if (a) 
      *p = (void*)&a; 
} 
void (*_bar)(void **) = bar; 

void dummy(int a, int b, int c){ 
} 
void (*_dummy)(int, int, int) = dummy; 

void *foo(void){ 
   void *p; 

   (_dummy)(1,2,3); 
   (*_bar)(&p); 
   return p; 
} 
void *(*_foo)(void) = foo; 


int main(void) 
{ 
   printf("%p", (*_foo)()); 
   
   return 0; 
}    


And result:
Code:
.text:00000040                 public _main
.text:00000040 _main           proc near
.text:00000040
.text:00000040 var_10          = dword ptr -10h
.text:00000040 var_C           = dword ptr -0Ch
.text:00000040
.text:00000040                 push    ebp
.text:00000041                 mov     ebp, esp
.text:00000043                 and     esp, 0FFFFFFF0h
.text:00000046                 sub     esp, 10h
.text:00000049                 call    ___main
.text:0000004E                 mov     [esp+10h+var_C], offset _a
.text:00000056                 mov     [esp+10h+var_10], offset unk_78
.text:0000005D                 mov     eax, _a ; superfluous
.text:00000062                 call    _printf
.text:00000067                 xor     eax, eax
.text:00000069                 leave
.text:0000006A                 retn
.text:0000006A _main           endp
    
Post 01 Dec 2009, 15:00
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Fanael, what switches did you use? The Assembly listing looks wrong, the line you marked superfluous is actually important but the isNonZero comparison was important too and was suppressed...

Oh wait, is that an IDA output? Then perhaps the compiler (or linker somehow?) takes advantage of the fact that the variable is not really residing in volatile memory (I mean more volatile than the RAM is of course) and then only honors the read as it could trigger some paging activity?
Post 01 Dec 2009, 16:17
View user's profile Send private message Reply with quote
Azu



Joined: 16 Dec 2008
Posts: 1160
Azu
LocoDelAssembly wrote:
the line you marked superfluous is actually important
Really? So _printf is using fastcall there?

_________________
Post 01 Dec 2009, 16:28
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
Fanael



Joined: 03 Jul 2009
Posts: 168
Fanael
LocoDelAssembly wrote:
Fanael, what switches did you use?
-O3 -march=native -fomit-frame-pointer -fprofile-use (of course I compiled and run this program with -fprofile-generate earlier) -mfpmath=sse -c. Yes, profile-guided optimizations.
Post 01 Dec 2009, 17:25
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
After profile using your code (except for the #include line):
Code:
int main(void) 
{ 
00401050  push        ecx  
   printf("%p", (*_foo)()); 
00401051  mov         eax,dword ptr [_foo (403024h)] 
00401056  cmp         eax,offset foo (401010h) 
0040105B  jne         __controlfp_s+45h (4018FDh) 
00401061  mov         eax,dword ptr [_dummy (403020h)] 
00401066  cmp         eax,offset dummy (401000h) 
0040106B  jne         __controlfp_s+24h (4018DCh) 
00401071  mov         eax,dword ptr [_bar (40301Ch)] 
00401076  cmp         eax,offset bar (4010B0h) 
0040107B  jne         __controlfp_s+34h (4018ECh) 
00401081  mov         eax,dword ptr [a (403018h)] 
00401086  test        eax,eax 
00401088  je          __controlfp_s+3Dh (4018F5h) 
0040108E  mov         eax,offset a (403018h) 
00401093  mov         dword ptr [esp],eax 
00401096  push        eax  
00401097  push        offset ___xi_z+34h (4020F4h) 
0040109C  call        dword ptr [__imp__printf (4020A0h)] 
   
   return 0; 
004010A2  xor         eax,eax 
}
.
.
.
_controlfp_s:
004018B8  jmp         dword ptr [__imp___controlfp_s (402068h)] 
004018BE  push        3    
004018C0  push        2    
004018C2  push        1    
004018C4  call        eax  
004018C6  add         esp,0Ch 
004018C9  jmp         foo+11h (401021h) 
004018CE  lea         ecx,[esp] 
004018D1  push        ecx  
004018D2  call        eax  
004018D4  add         esp,4 
004018D7  mov         eax,dword ptr [esp] 
004018DA  pop         ecx  
004018DB  ret              
004018DC  push        3    
004018DE  push        2    
004018E0  push        1    
004018E2  call        eax  
004018E4  add         esp,0Ch 
004018E7  jmp         main+21h (401071h) 
004018EC  lea         ecx,[esp] 
004018EF  push        ecx  
004018F0  call        eax  
004018F2  add         esp,4 
004018F5  mov         eax,dword ptr [esp] 
004018F8  jmp         main+46h (401096h) 
004018FD  call        eax  
004018FF  jmp         main+46h (401096h) 
    


Using plain release build produced the same code as previously posted (except for the getchar that now is not present).

Azu wrote:
Really? So _printf is using fastcall there?

Yes. No.


Last edited by LocoDelAssembly on 01 Dec 2009, 18:25; edited 1 time in total
Post 01 Dec 2009, 18:20
View user's profile Send private message Reply with quote
Azu



Joined: 16 Dec 2008
Posts: 1160
Azu
LocoDelAssembly wrote:

Azu wrote:
Really? So _printf is using fastcall there?

Yes. No.
If it's not fastcall why is eax important? Won't it just be ignored?

_________________
Post 01 Dec 2009, 18:24
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Accessing the variable "a" is important.
Post 01 Dec 2009, 18:28
View user's profile Send private message Reply with quote
Azu



Joined: 16 Dec 2008
Posts: 1160
Azu
LocoDelAssembly wrote:
Accessing the variable "a" is important.
I didn't mean it should never be accessed.

I just meant this one instance that he mentioned and that you replied to;
Quote:
Code:
.text:0000005D                 mov     eax, _a ; superfluous 
.text:00000062                 call    _printf     

_________________
Post 01 Dec 2009, 18:33
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
It is the only instance and since the HLL code accessed it once that access is important. Also, the original code triggered the access when printf is called with the function that actually access the variable so the position is not so exotic.
Post 01 Dec 2009, 18:43
View user's profile Send private message Reply with quote
Azu



Joined: 16 Dec 2008
Posts: 1160
Azu
Actually, even if it was fastcall, it still wouldn't matter. None of the standard calling conventions pass in arguments via eax. So it definitely is superfluous. Unless it's unreadable memory and triggers an exception.. but what would be the point of that? Why not just put a jmp there to whatever code you wanted ran?

_________________
Post 01 Dec 2009, 18:49
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
Fanael



Joined: 03 Jul 2009
Posts: 168
Fanael
LocoDelAssembly wrote:
The Assembly listing looks wrong
It doesn't - it will produce valid results, so it's correct.

Probably the compiler with PGO was able to discover that a never changes, so it optimized out the comparison involving two constants. The read is still there, though, because of a's volatileness. Marking that read as superfluous was my fault.
Post 01 Dec 2009, 18:51
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Quote:

It doesn't - it will produce valid results, so it's correct.

But the original code, due to the volatileness could theoretically print either p var's garbage or a's address. On the other hand it is true that a's address is a possible p's garbage value too Smile
Post 01 Dec 2009, 19:22
View user's profile Send private message Reply with quote
Azu



Joined: 16 Dec 2008
Posts: 1160
Azu
Fanael wrote:
LocoDelAssembly wrote:
The Assembly listing looks wrong
It doesn't - it will produce valid results, so it's correct.

Probably the compiler with PGO was able to discover that a never changes, so it optimized out the comparison involving two constants. The read is still there, though, because of a's volatileness. Marking that read as superfluous was my fault.
Confused

So what does it do then?

If I change _a and that mov eax,_a isn't there, will the program crash?

_________________
Post 01 Dec 2009, 19:28
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
Fanael



Joined: 03 Jul 2009
Posts: 168
Fanael
Actually it won't crash, nevertheless the read must be performed, as the programmer explicitly said "I need a read or write every time when I refer to that variable" to the compiler. Remove the volatile and that read will be optimized out.
Post 01 Dec 2009, 19:37
View user's profile Send private message Reply with quote
Borsuc



Joined: 29 Dec 2005
Posts: 2466
Location: Bucharest, Romania
Borsuc
What's the point with volatile access if you don't use it? I mean no matter what the variable's value may be, what's the point to access it if you don't use that value? (unknown to the compiler, since it's volatile)
Post 01 Dec 2009, 20:15
View user's profile Send private message Reply with quote
Azu



Joined: 16 Dec 2008
Posts: 1160
Azu
Fanael wrote:
Actually it won't crash, nevertheless the read must be performed, as the programmer explicitly said "I need a read or write every time when I refer to that variable" to the compiler. Remove the volatile and that read will be optimized out.
I thought volatile means it might change so it shouldn't be inlined statically.

Like if the value is used, then it should read it from the memory location (mov eax,[_al], rather then just putting whatever value it was defined as at compile-time(xor eax,eax inc eax).

But when it isn't being used, why should it put anything there at all? It does nothing.. Confused



On MSDN it just says
MSDN wrote:
indicates that a field can be modified in the program by something such as the operating system, the hardware, or a concurrently executing thread
and
Quote:
The system always reads the current value of a volatile object at the point it is requested, even if the previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment.


It doesn't say to read it when it isn't being used. It just says to read it every time it is used (as opposed to caching it in a register for later re-use, I guess)..



Maybe MSVC C++ works different than GCC C++? What is the GCC equivalent of MSDN?

_________________
Post 01 Dec 2009, 20:58
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
Borsuc wrote:
What's the point with volatile access if you don't use it? I mean no matter what the variable's value may be, what's the point to access it if you don't use that value? (unknown to the compiler, since it's volatile)
It could trigger memory-mapped IO, or generate an exception you depend on for whatever reason - the compiler can't and shouldn't know, so it has to generate the access even if it's useless in this example.

_________________
Image - carpe noctem
Post 02 Dec 2009, 00:00
View user's profile Send private message Visit poster's website Reply with quote
Azu



Joined: 16 Dec 2008
Posts: 1160
Azu
Azu wrote:
Unless it's unreadable memory and triggers an exception.. but what would be the point of that? Why not just put a jmp there to whatever code you wanted ran?

_________________
Post 02 Dec 2009, 00:40
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
Azu wrote:
Azu wrote:
Unless it's unreadable memory and triggers an exception.. but what would be the point of that? Why not just put a jmp there to whatever code you wanted ran?
Perhaps you need the exception unwinding mechanism to kick in, perhaps you're doing it to obfuscate your code - plenty of reasons.

Also, you seem to completely ignore the memory-mapped I/O part.

_________________
Image - carpe noctem
Post 02 Dec 2009, 00:44
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.