对volatile认识
from MSDN:
The volatile keyword is a type qualifier used to declare that an object can be modified in the program by something other than statements, such as the operating system, the hardware, or a concurrently executing thread.
The following example declares a volatile integer nVint whose value can be modified by external processes:
int volatile nVint;
Objects declared as volatile are not used in optimizations because their value can change at any time. 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.
One use of the volatile qualifier is to provide access to memory locations used by asynchronous processes such as interrupt handlers.
This means a value that can automatically change at any given instance. This is usually in reference to a hardware register that often has a different value ever time you read it. Specifically, it is useful to define some values as volatile so that a C compiler will not cache that value, but rather, get a fresh copy every time you request it's value. Otherwise, the compiler may return values which are inaccurate because it doesn't realized the value can change.
C:\tmp>type honor_volatile.c
#if !defined(VOLATILE)
#error
#endif
void test_one()
{
VOLATILE int x = 5;
}
void test_two(VOLATILE int x)
{
x = 5;
}
C:\tmp>cl -O2 -c -Fa -DVOLATILE= honor_volatile.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 17.00.40308 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
honor_volatile.c
C:\tmp>type honor_volatile.asm
; Listing generated by Microsoft (R) Optimizing Compiler Version 17.00.40308.0
TITLE C:\tmp\honor_volatile.c
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC _test_one
PUBLIC _test_two
; Function compile flags: /Ogtpy
; COMDAT _test_two
_TEXT SEGMENT
_x$ = 8 ; size = 4
_test_two PROC ; COMDAT
; File c:\tmp\honor_volatile.c
; Line 15
ret 0
_test_two ENDP
_TEXT ENDS
; Function compile flags: /Ogtpy
; COMDAT _test_one
_TEXT SEGMENT
_test_one PROC ; COMDAT
; File c:\tmp\honor_volatile.c
; Line 10
ret 0
_test_one ENDP
_TEXT ENDS
END
C:\tmp>cl -O2 -c -Fa -DVOLATILE=volatile honor_volatile.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 17.00.40308 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
honor_volatile.c
C:\tmp>type honor_volatile.asm
; Listing generated by Microsoft (R) Optimizing Compiler Version 17.00.40308.0
TITLE C:\tmp\honor_volatile.c
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC _test_one
PUBLIC _test_two
; Function compile flags: /Ogtpy
; COMDAT _test_two
_TEXT SEGMENT
_x$ = 8 ; size = 4
_test_two PROC ; COMDAT
; File c:\tmp\honor_volatile.c
; Line 14
mov DWORD PTR _x$[esp-4], 5
; Line 15
ret 0
_test_two ENDP
_TEXT ENDS
; Function compile flags: /Ogtpy
; COMDAT _test_one
_TEXT SEGMENT
_x$ = -4 ; size = 4
_test_one PROC ; COMDAT
; File c:\tmp\honor_volatile.c
; Line 8
push ecx
; Line 9
mov DWORD PTR _x$[esp+4], 5
; Line 10
pop ecx
ret 0
_test_one ENDP
_TEXT ENDS
END
And this is assembly code from VS:
#include <stdio.h>
void main()
{
volatile int i=10;
int a = i;
printf("i= %d\n",a);
__asm {
mov dword ptr [ebp-4], 20h
}
int b = i;
printf("i= %d\n",b);
}
Release:
009C1002 in al,dx
009C1003 push ecx
009C1004 push esi
volatile int i=10;
int a = i;
printf("i= %d\n",a);
009C1005 mov esi,dword ptr [__imp__printf (9C20A0h)]
009C100B mov dword ptr [i],0Ah
009C1012 mov eax,dword ptr [i]
009C1015 push eax
009C1016 push offset string "i= %d\n" (9C20F4h)
009C101B call esi
009C101D add esp,8
__asm {
mov dword ptr [ebp-4], 20h
009C1020 mov dword ptr [i],20h
}
int b = i;
009C1027 mov eax,dword ptr [i]
printf("i= %d\n",b);
009C102A push eax
009C102B push offset string "i= %d\n" (9C20F4h)
009C1030 call esi
009C1032 add esp,8
009C1035 pop esi
}
009C1036 mov esp,ebp
009C1038 pop ebp
009C1039 ret
Debug:
#include <stdio.h>
void main()
{
001B13B0 push ebp
001B13B1 mov ebp,esp
001B13B3 sub esp,0E4h
001B13B9 push ebx
001B13BA push esi
001B13BB push edi
001B13BC lea edi,[ebp-0E4h]
001B13C2 mov ecx,39h
001B13C7 mov eax,0CCCCCCCCh
001B13CC rep stos dword ptr es:[edi]
volatile int i=10;
001B13CE mov dword ptr [i],0Ah
int a = i;
001B13D5 mov eax,dword ptr [i]
001B13D8 mov dword ptr [a],eax
printf("i= %d\n",a);
001B13DB mov esi,esp
001B13DD mov eax,dword ptr [a]
001B13E0 push eax
001B13E1 push offset string "i= %d\n" (1B573Ch)
001B13E6 call dword ptr [__imp__printf (1B82D4h)]
001B13EC add esp,8
001B13EF cmp esi,esp
001B13F1 call @ILT+300(__RTC_CheckEsp) (1B1131h)
__asm {
mov dword ptr [ebp-4], 20h
001B13F6 mov dword ptr [ebp-4],20h
}
int b = i;
001B13FD mov eax,dword ptr [i]
001B1400 mov dword ptr [b],eax
printf("i= %d\n",b);
001B1403 mov esi,esp
001B1405 mov eax,dword ptr [b]
001B1408 push eax
001B1409 push offset string "i= %d\n" (1B573Ch)
001B140E call dword ptr [__imp__printf (1B82D4h)]
001B1414 add esp,8
001B1417 cmp esi,esp
001B1419 call @ILT+300(__RTC_CheckEsp) (1B1131h)
}
C:\Temp>type meow.cpp
#include <stdio.h>
int main() {
MEOW int i = 10;
int a = i;
printf("a: %d\n", a);
__asm {
mov dword ptr [ebp - 4], 20h
}
int b = i;
printf("b: %d\n", b);
}
C:\Temp>cl /EHsc /nologo /W4 /MTd /DMEOW= meow.cpp && meow
meow.cpp
a: 10
b: 32
C:\Temp>cl /EHsc /nologo /W4 /MT /O2 /DMEOW= meow.cpp && meow
meow.cpp
a: 10
b: 10
C:\Temp>cl /EHsc /nologo /W4 /MTd /DMEOW=volatile meow.cpp && meow
meow.cpp
a: 10
b: 32
C:\Temp>cl /EHsc /nologo /W4 /MT /O2 /DMEOW=volatile meow.cpp && meow
meow.cpp
a: 10
b: 32
Volatility inhibits optimizations, as expected.