当前位置:网站首页>Use of keywords const, volatile and pointer; Assembly language and view of register status

Use of keywords const, volatile and pointer; Assembly language and view of register status

2022-07-24 15:01:00 It's Xiaoguang a~

keyword const、volatile Use of pointer ; Assembly language and register status check :

Let's start with an example , In order to prevent inconsistent results caused by compiler optimization, we prohibit compiler optimization here ( Actually, it has nothing to do with compiler optimization ):
Patients with a (const Inconsistent with the result caused by the use of pointers ):

#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
    

    #pragma optimize("", off) // Prohibit the compiler from optimizing the following code 
    const int a = 10;
    printf("%d\n",a);
    int *p = (int*)&a;
    *p = 100;
    printf("%p\n%p\n",&a,p);  // The address is the same 
    printf("%d,%d\n",a,*p);  // Values are not the same 
    return 0;
    #pragma optimize("", on)
}


result:
 Insert picture description here
reason :

	int *p = (int*)&a;
    *p = 100;

The code here does correct the content of the address part , however a First defined as const Variable , So the compiler thinks a It won't change in the future , So when the program is compiled , Just put variables a The value of the beginning 10 In the register , Read directly from the register when accessing later ; Therefore, although the actual value in memory is modified when executing the above code fragment , But the value in the register is not modified , Output a When , Or read from the register , The value of the register is still 10, Therefore, the read value does not match the actual value .
Example 2 ( adopt volatile Achieve consistency of results ):

#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
    
    volatile const int a = 10;  // See if the qualifier is added volatile, If you add it, the result value is the same , On the contrary, it is different 
    // If the variable is added  volatile  modification , The contents will be reloaded from memory , Instead of copying content directly from registers . 
    //const int a = 10;
    printf("%d\n",a);
    int *p = (int*)&a;
    *p = 100;
    printf("%p\n%p\n",&a,p);  // The address is the same 
    printf("%d,%d\n",a,*p);  // Values are not the same 
    return 0;
}

Join in volatile After keyword , The system always rereads data from its memory , Even if its previous instruction just read data from there , And the read data is immediately saved . Therefore use volatile Keyword avoids inconsistency errors between reading registers and reading memory .
result:
 Insert picture description here
The above two examples can also illustrate const It's not absolutely safe ,const Keywords do not guarantee that constant values are modified ( You can modify the address value directly through the pointer ).
Of course, in the above example, we can further draw a conclusion by observing the assembly code and register state during debugging , Those who have the foundation of assembly language can try it by themselves .

Patients with a ( Assembly code ):

#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
    
00007FF63C1C18F0  push        rbp  
00007FF63C1C18F2  push        rdi  
00007FF63C1C18F3  sub         rsp,128h  
00007FF63C1C18FA  lea         rbp,[rsp+20h]  
00007FF63C1C18FF  mov         rdi,rsp  
00007FF63C1C1902  mov         ecx,4Ah  
00007FF63C1C1907  mov         eax,0CCCCCCCCh  
00007FF63C1C190C  rep stos    dword ptr [rdi]  
00007FF63C1C190E  mov         rax,qword ptr [__security_cookie (07FF63C1CC008h)]  
00007FF63C1C1915  xor         rax,rbp  
00007FF63C1C1918  mov         qword ptr [rbp+0F8h],rax  
00007FF63C1C191F  lea         rcx,[[email protected] (07FF63C1D1026h)]  
00007FF63C1C1926  call        __CheckForDebuggerJustMyCode (07FF63C1C108Ch)  
    //volatile const int a = 10; // See if the qualifier is added volatile, If you add it, the result value is the same , On the contrary, it is different 
    const int a = 10;
00007FF63C1C192B  mov         dword ptr [a],0Ah  
    printf("%d\n",a);
00007FF63C1C1932  mov         edx,0Ah  
00007FF63C1C1937  lea         rcx,[string "%d\n" (07FF63C1C9CA4h)]  
00007FF63C1C193E  call        printf (07FF63C1C11E0h)  
    int *p = (int*)&a;
00007FF63C1C1943  lea         rax,[a]  
00007FF63C1C1947  mov         qword ptr [p],rax  
    *p = 100;
00007FF63C1C194B  mov         rax,qword ptr [p]  
00007FF63C1C194F  mov         dword ptr [rax],64h  
    printf("%p\n%p\n",&a,p);  // The address is the same 
00007FF63C1C1955  mov         r8,qword ptr [p]  
00007FF63C1C1959  lea         rdx,[a]  
00007FF63C1C195D  lea         rcx,[string "%p\n%p\n" (07FF63C1C9CA8h)]  
00007FF63C1C1964  call        printf (07FF63C1C11E0h)  
    printf("%d,%d\n",a,*p);  // Values are not the same 
00007FF63C1C1969  mov         rax,qword ptr [p]  
00007FF63C1C196D  mov         r8d,dword ptr [rax]  
00007FF63C1C1970  mov         edx,0Ah  
00007FF63C1C1975  lea         rcx,[string "%d,%d\n" (07FF63C1C9CB0h)]  
00007FF63C1C197C  call        printf (07FF63C1C11E0h)  
    return 0;
00007FF63C1C1981  xor         eax,eax  
}
00007FF63C1C1983  mov         edi,eax  
00007FF63C1C1985  lea         rcx,[rbp-20h]  
}
00007FF63C1C1989  lea         rdx,[__xt_z+1E0h (07FF63C1C9C80h)]  
00007FF63C1C1990  call        _RTC_CheckStackVars (07FF63C1C1343h)  
00007FF63C1C1995  mov         eax,edi  
00007FF63C1C1997  mov         rcx,qword ptr [rbp+0F8h]  
00007FF63C1C199E  xor         rcx,rbp  
00007FF63C1C19A1  call        __security_check_cookie (07FF63C1C10DCh)  
00007FF63C1C19A6  lea         rsp,[rbp+108h]  
00007FF63C1C19AD  pop         rdi  
00007FF63C1C19AE  pop         rbp  
00007FF63C1C19AF  ret 

Example 2 ( Assembly code ):

#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
    
00007FF7D37E18F0  push        rbp  
00007FF7D37E18F2  push        rdi  
00007FF7D37E18F3  sub         rsp,128h  
00007FF7D37E18FA  lea         rbp,[rsp+20h]  
00007FF7D37E18FF  mov         rdi,rsp  
00007FF7D37E1902  mov         ecx,4Ah  
00007FF7D37E1907  mov         eax,0CCCCCCCCh  
00007FF7D37E190C  rep stos    dword ptr [rdi]  
00007FF7D37E190E  mov         rax,qword ptr [__security_cookie (07FF7D37EC008h)]  
00007FF7D37E1915  xor         rax,rbp  
00007FF7D37E1918  mov         qword ptr [rbp+0F8h],rax  
00007FF7D37E191F  lea         rcx,[[email protected] (07FF7D37F1026h)]  
00007FF7D37E1926  call        __CheckForDebuggerJustMyCode (07FF7D37E108Ch)  
    volatile const int a = 10;  // See if the qualifier is added volatile, If you add it, the result value is the same , On the contrary, it is different 
00007FF7D37E192B  mov         dword ptr [a],0Ah  
    printf("%d\n",a);
00007FF7D37E1932  mov         edx,dword ptr [a]  
00007FF7D37E1935  lea         rcx,[string "%d\n" (07FF7D37E9CA4h)]  
00007FF7D37E193C  call        printf (07FF7D37E11E0h)  
    int *p = (int*)&a;
00007FF7D37E1941  lea         rax,[a]  
00007FF7D37E1945  mov         qword ptr [p],rax  
    *p = 100;
00007FF7D37E1949  mov         rax,qword ptr [p]  
00007FF7D37E194D  mov         dword ptr [rax],64h  
    printf("%p\n%p\n",&a,p);  // The address is the same 
00007FF7D37E1953  mov         r8,qword ptr [p]  
00007FF7D37E1957  lea         rdx,[a]  
00007FF7D37E195B  lea         rcx,[string "%p\n%p\n" (07FF7D37E9CA8h)]  
00007FF7D37E1962  call        printf (07FF7D37E11E0h)  
    printf("%d,%d\n",a,*p);  // Values are not the same 
00007FF7D37E1967  mov         rax,qword ptr [p]  
00007FF7D37E196B  mov         r8d,dword ptr [rax]  
00007FF7D37E196E  mov         edx,dword ptr [a]  
00007FF7D37E1971  lea         rcx,[string "%d,%d\n" (07FF7D37E9CB0h)]  
00007FF7D37E1978  call        printf (07FF7D37E11E0h)  
    return 0;
00007FF7D37E197D  xor         eax,eax  
}
00007FF7D37E197F  mov         edi,eax  
00007FF7D37E1981  lea         rcx,[rbp-20h]  
}
00007FF7D37E1985  lea         rdx,[__xt_z+1E0h (07FF7D37E9C80h)]  
00007FF7D37E198C  call        _RTC_CheckStackVars (07FF7D37E1343h)  
00007FF7D37E1991  mov         eax,edi  
00007FF7D37E1993  mov         rcx,qword ptr [rbp+0F8h]  
00007FF7D37E199A  xor         rcx,rbp  
00007FF7D37E199D  call        __security_check_cookie (07FF7D37E10DCh)  
00007FF7D37E19A2  lea         rsp,[rbp+108h]  
00007FF7D37E19A9  pop         rdi  
00007FF7D37E19AA  pop         rbp  
00007FF7D37E19AB  ret  

VS Debug the way assembly code is generated :
Add breakpoints first , Then debug , And then in “ debugging ”->“ window ”->“ Disassembly ”. In this way, you can see the disassembly options . If you don't add breakpoints, you can't see . Check register 、 Memory is the same .
 Insert picture description here
Of course, it can also be cmd Directly output the de assembled code in the form of command line :
example ( Pay attention to the generated .s The detailed address shall be indicated in the document , use txt Open the text file format ):

C:\Users\Administrator>g++ -S C:\\Users\\Administrator\\Desktop\\testc++.cpp  -o C:\\Users\\Administrator\\Desktop\\ La la la .s

 Insert picture description here
Of course, we can also view the disassembly code and output results through the online compiler :
Recommend two websites ( There are actually many online compilers , Only those with distinctive features are selected here ( It's not necessarily the best , Only the right one is the best )):
C++ Shell
C++ Shell The system uses GCC 4.9.2, with Boost 1.55. It has syntax 、 Error prompt and other functions . Besides , It also supports some additional options , image C++ Standard selection (C++98/C++11/C++14)、 Warning level 、 Optimization level 、 Standard input, etc .
Although there are relatively many shortcomings , For example, lack of intelligent tips 、 create a file / project 、 Download code 、 Custom settings and other functions , And the execution speed is also slow , But the warning level 、 Optimization level function is still OK Of .
 Insert picture description here

Compiler Explorer
Compiler Explorer Is an interactive compiler , Editable C/C++、Go、Swift( And more ) Code , On the right is the assembly output after compiling the code , It is more suitable for viewing assembly code . It has code highlighting 、 Custom Settings 、 Error message 、 Assembly output 、 preservation 、 Sharing and other functions .
Its disadvantage is that there is no intelligent prompt , And there are a lot of functions , Dazzling ! But the functions of checking assembly language are very OK.
 Insert picture description here

原网站

版权声明
本文为[It's Xiaoguang a~]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/203/202207211609108954.html