Zoijar schreef op 23 augustus 2004 @ 11:38:
[...]
offtopic:
Voor zover ik weet doet msvc dat zelf. De compiler kan prima zelf kijken welke registers je gebruikt, en welke je clobbered etc. In ieder geval had ik laatst een asm stukje, en vc7 en gcc maakten er exact dezelfde (optimized) code van. Alleen moest ik in gcc helemaal nadenken welke registers ik op moest geven, en deed vc dat helemaal zelf.
offtopic:
Bij simpele ASM code is dat inderdaad mogelijk. Echter zodra je via (bijvoorbeeld) een call een ander blok code aanroept, kan de compiler nooit achterhalen welke registers gewijzigd worden. Tevens zijn stack-frame modificaties al helemaal lastig te achterhalen, bovendien kun je run-time dingen doen die compile-time niet te achterhalen zijn. Als laatste ontbreekt ook nog de functionaliteit van volatile, dus heb je weinig controle over de optimalisatie van je ASM code.
Ok, hier een klein voorbeeldje van hoe GCC en MSVC hun assembly optimaliseren. Dit is een stukje code dat het CR0 register uitleest, vooral handig voor kernel freaks

Beide compilers krijgen de opdracht hun code maximaal te optimaliseren (dus ook microsoft's compiler) behalve door functies te inlinen (dan wordt de ASM zo'n zootje

)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| #include <iostream>
void output(int val)
{
std::cout << "output: " << val << std::endl;
}
int main(void)
{
int value;
#ifdef _MSC_VER
__asm
{
MOV EAX, CR0
MOV value, EAX
}
#else
asm volatile ("mov %%cr0, %%eax \n\t"
: "=a" (value)
:
);
#endif
output(value);
return 0;
} |
Bij GCC wordt "MOV value, EAX" vervangen door ""=a" (value)"
Dit is wat GCC er van maakt (3 instucties):
code:
1
2
3
4
5
6
| /APP
mov %cr0, %eax
/NO_APP
movl %eax, (%esp)
call __Z6outputi |
CR0 wordt in EAX geplaatst, hierna wordt EAX op de stacktop geplaatst ("movl %cr0, (%esp)" is geen geldige instructie). Dan wordt de functie output aangeroepen.
En dit is wat MSVC er van maakt (6 instucties, 2x zoveel dus!):
code:
1
2
3
4
5
6
7
8
9
| ; Line 15
mov eax, cr0
; Line 16
mov DWORD PTR _value$[ebp], eax
; Line 25
mov eax, DWORD PTR _value$[ebp]
push eax
call ?output@@YAXH@Z ; output
add esp, 4 |
CR0 wordt in EAX geplaatst, hierna wordt EAX in de variable value opgeslagen. Dan wordt de variabele value weer in EAX gezet

en daarna op de stack gepushed. Dan wordt de functie output aangeroepen, en in tegenstelling tot GCC de stack weer vrijgemaakt.