C ++ (opening part) 01 from the perspective of Assembly

Source: Internet
Author: User

[Disclaimer: All Rights Reserved. You are welcome to reprint it. Do not use it for commercial purposes. Contact Email: feixiaoxing @ 163.com]

Many of my friends, including myself, are not very familiar with many features of the C ++ language. Especially when I was looking for a job a few years ago, I often forced myself to remember some complex questions and answers to cope with exams from work units. But often time has passed, and everything is back to the origin. The problems that have not been clarified are still not understood, and everything has not changed. After a few years, when I accumulate experience in the coding process, I try to use the AssemblyCodeAnd memory data to explain some phenomena, it is not complicated to understand some things. Some may be afraid of assembly language, but it is not necessary. As long as you have some knowledge of C language and stack, you already have the basics of assembly language. In the next several blogs, we will introduce how x86 assembly, data types, data operation logic, pointers, Data, classes, and heavy-load operators are carried out in assembly, let's talk about some personal opinions. Next, we will conduct some small tests and explain them in assembly language. You can do it together.

 

(1) Char name [] and char * Name

[CPP] View plaincopy
  1. 1:
  2. 2:VoidProcess ()
  3. 3 :{
  4. 00401020 push EBP
  5. 00401021 mov EBP, ESP
  6. 00401023 sub ESP, 4ch
  7. 00401026 push EBX
  8. 00401027 push ESI
  9. 00401028 push EDI
  10. 00401029 Lea EDI, [ebp-4Ch]
  11. 0040102c mov ECx, 13 H
  12. 00401031 mov eax, 0 cccccccch
  13. 00401036 rep STOs dword ptr [EDI]
  14. 4:CharName_tmp [] = {"Hello"};
  15. 00401038 mov eax, [String"Hello"(0042201c)]
  16. 0040103d mov dword ptr [ebp-8], eax
  17. 00401040 mov CX, word PTR [String"Hello"+ 4 (00422020)]
  18. 00401047 mov word PTR [ebp-4], CX
  19. 5:Char* Name_glb ="Hello";
  20. 0040104b mov dword ptr [ebp-0Ch], offset string"Hello"(0042201c)
  21. 6 :}
  22. 00401052 pop EDI
  23. 00401053 pop ESI
  24. 00401054 pop EBX
  25. 00401055 mov ESP, EBP
  26. 00401057 pop EBP
  27. 00401058 RET

Through the above code, we can clearly see the difference between the two. The "hello" string is a global read-only variable with the spatial address 0x0042201c. Name_tmp is a char array within the number of functions. The four rows below the 4th line statement indicate that the global data "hello" is copied to name_tmp twice. The first time is DWORD and four bytes, the second time is word and two bytes. Therefore, name_tmp contains 6 bytes. In comparison, name_glb has nothing. It just points itself to a global variable, so it is just a pointer.

(2) Apple A () and Apple B

Assume that class apple is defined:

[CPP] View plaincopy
    1. ClassApple
    2. {
    3. Public:
    4. Apple (){}
    5. ~ Apple (){}
    6. };

So how did Apple A () and Apple B compile them separately?

[CPP] View plaincopy
  1. 9:VoidProcess ()
  2. 10 :{
  3. 00401020 push EBP
  4. 00401021 mov EBP, ESP
  5. 00401023 sub ESP, 44 h
  6. 00401026 push EBX
  7. 00401027 push ESI
  8. 00401028 push EDI
  9. 00401029 Lea EDI, [ebp-44h]
  10. 0040102c mov ECx, 11 h
  11. 00401031 mov eax, 0 cccccccch
  12. 00401036 rep STOs dword ptr [EDI]
  13. 11: Apple ();
  14. 12: Apple B;
  15. 00401038 Lea ECx, [ebp-4]
  16. 0040103b call @ ILT + 20 (Apple: Apple) (00401019)
  17. 13 :}
  18. 00401040 Lea ECx, [ebp-4]
  19. 00401043 call @ ILT + 10 (Apple ::~ Apple) (0040100f)
  20. 00401048 pop EDI
  21. 00401049 pop ESI
  22. 0040104a pop EBX
  23. 0040104b add ESP, 44 h
  24. 0040104e cmp ebp, ESP
  25. 00401050 call _ chkesp (004010b0)
  26. 00401055 mov ESP, EBP
  27. 00401057 pop EBP
  28. 00401058 RET

Why didn't apple a () Compile anything? The reason is simple, because the compiler regards apple a () as an extern function, and the return value is apple. The corresponding Apple B is the temporary variable actually defined in the function, because there are two apple functions-Apple constructor and Apple's destructor not far below.

(3) (Apple *) (0)-> Print ()

Here, class apple is defined as follows:

[CPP] View plaincopy
    1. ClassApple
    2. {
    3. IntValue;
    4. Public:
    5. Apple (){}
    6. ~ Apple (){}
    7. VoidPrint (){Return;}
    8. };

If 0 is set to Apple *, will the function print be accessed?

[CPP] View plaincopy
  1. 10:VoidProcess ()
  2. 11 :{
  3. 00401030 push EBP
  4. 00401031 mov EBP, ESP
  5. 00401033 sub ESP, 40 h
  6. 00401036 push EBX
  7. 00401037 push ESI
  8. 00401038 push EDI
  9. 00401039 Lea EDI, [ebp-40h]
  10. 0040103c mov ECx, 10 h
  11. 00401041 mov eax, 0 cccccccch
  12. 00401046 rep STOs dword ptr [EDI]
  13. 12: (Apple *) (0)-> Print ();
  14. 00401048 XOR ECx, ECx
  15. 0040104a call @ ILT + 0 (Apple: print) (00401005)
  16. 13 :}
  17. 0040104f pop EDI
  18. 00401050 pop ESI
  19. 00401051 pop EBX
  20. 00401052 add ESP, 40 h
  21. 00401055 cmp ebp, ESP
  22. 00401057 call _ chkesp (004010e0)
  23. 0040105c mov ESP, EBP
  24. 0040105e pop EBP
  25. 0040105f RET

By running the function, we find that no exception is generated. Why? Because we found that ECx is passed to the print function as 0, that is, the familiar this pointer is 0. But we found that the print function does not use the this pointer internally, because we did not access this-> value at all, just a return statement. This shows that the pointer as a class NULL pointer is not terrible, but it is terrible to use null to access data in the memory.

(4) int M = 1; int n = m ++ + m; what is n?

[CPP] View plaincopy
  1. 10:VoidProcess ()
  2. 11 :{
  3. 0040d4d0 push EBP
  4. 0040d4d1 mov EBP, ESP
  5. 0040d4d3 sub ESP, 48 h
  6. 0040d4d6 push EBX
  7. 0040d4d7 push ESI
  8. 0040d4d8 push EDI
  9. 0040d4d9 Lea EDI, [ebp-48h]
  10. 0040d4dc mov ECx, 12 h
  11. 0040d4e1 mov eax, 0 cccccccch
  12. 0040d4e6 rep STOs dword ptr [EDI]
  13. 12:IntM = 1;
  14. 0040d4e8 mov dword ptr [ebp-4], 1
  15. 13:IntN = m ++ + m;
  16. 0040d4ef mov eax, dword ptr [ebp-4]
  17. 0040d4f2 add eax, 1
  18. 0040d4f5 mov dword ptr [ebp-4], eax
  19. 0040d4f8 mov ECx, dword ptr [ebp-4]
  20. 0040d4fb add ECx, dword ptr [ebp-4]
  21. 0040d4fe mov dword ptr [ebp-8], ECx
  22. 0040d501 mov edX, dword ptr [ebp-4]
  23. 0040d504 add edX, 1
  24. 0040d507 mov dword ptr [ebp-4], EDX
  25. 14 :}
  26. 0040d50a pop EDI
  27. 0040d50b pop ESI
  28. 0040d50c pop EBX
  29. 0040d50d mov ESP, EBP
  30. 0040d50f pop EBP

Through the assembly code, we can see that [ebp-4] is the address of m in the stack, [ebp-8] is the address of N in the stack. There are a total of nine statements under int n = m ++ + M. We can analyze: the first three sentences indicate that M increases by 1, and the fourth sentence indicates ECx = m, that is, ECx = 2. The fifth sentence is the sum of ECx and M. The translation is ECx = ECx + M. In this case, ECx = 4. The sixth sentence indicates n = ECx. From the seventh to ninth sentences, M increases by 1. Why is there such a situation? In fact, the truth is very simple, mainly because our expressions are calculated from the right to the left. If you see this, you will understand that the first is ++ m, then n = m + M, and then M ++.

(5) What is the difference between * P ++ and (* P) ++?

[CPP] View plaincopy
  1. 10:VoidProcess ()
  2. 11 :{
  3. 0040d4d0 push EBP
  4. 0040d4d1 mov EBP, ESP
  5. 0040d4d3 sub ESP, 48 h
  6. 0040d4d6 push EBX
  7. 0040d4d7 push ESI
  8. 0040d4d8 push EDI
  9. 0040d4d9 Lea EDI, [ebp-48h]
  10. 0040d4dc mov ECx, 12 h
  11. 0040d4e1 mov eax, 0 cccccccch
  12. 0040d4e6 rep STOs dword ptr [EDI]
  13. 12:CharData ='A';
  14. 0040d4e8 mov byte PTR [ebp-4], 61 H
  15. 13:Char* P = & data;
  16. 0040d4ec Lea eax, [ebp-4]
  17. 0040d4ef mov dword ptr [ebp-8], eax
  18. 14: * P ++;
  19. 0040d4f2 mov ECx, dword ptr [ebp-8]
  20. 0040d4f5 add ECx, 1
  21. 0040d4f8 mov dword ptr [ebp-8], ECx
  22. 15: (* P) ++;
  23. 0040d4fb mov edX, dword ptr [ebp-8]
  24. 0040d4fe mov Al, byte PTR [edX]
  25. 0040d500 add Al, 1
  26. 0040d502 mov ECx, dword ptr [ebp-8]
  27. 0040d505 mov byte PTR [ECx], Al
  28. 16 :}
  29. 0040d507 pop EDI
  30. 0040d508 pop ESI
  31. 0040d509 pop EBX
  32. 0040d50a mov ESP, EBP
  33. 0040d50c pop EBP
  34. 0040d50d RET

First, create the local variable data. Then copy the data pointer to P. The Assembly Code clearly shows that * P ++ is equivalent to P ++; (* P) ++ first copies the pointer to EDX, then obtain the char data pointed to by the edX address and copy it to Al. Al increases by 1. At the same time, P address is copied to ECx, and Al is copied to the address pointed to by the ECX address, which is that simple.

 

There are many other similar problems. You may wish to give it a try:

(1) How is the following Union arranged in memory? When GCC and VC are compiled, is the allocated memory size the same?

[CPP] View plaincopy
    1. Typedef Union
    2. {
    3. CharM: 3;
    4. CharN: 7;
    5. IntData;
    6. } Value;

(2) are the following addresses consistent?

[CPP] View plaincopy
    1. CharValue1 [] = {"Hello"};
    2. CharValue2 [] = {"Hello"};
    3. Char* Pvalue1 = "hello ";
    4. Char* Pvalue2 ="Hello";
    5. Are the value1 and value2 addresses consistent? What about pvalue1 and pvalue2?

(3) Why is the following statement incorrect? Why is the memory leaked? How to modify it?

[CPP] View plaincopy
  1. ClassApple
  2. {
  3. Char* Pname;
  4. Public:
  5. Apple () {pname = (Char*) Malloc (10 );}
  6. ~ Apple (){If(Null! = Pname) Free (pname );}
  7. };
  8. VoidProcess ()
  9. {
  10. Apple A, B;
  11. A = B;
  12. }

(Full text)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.