现在的位置: 首页 > 综合 > 正文

[利用asm代码学习c++语法]--union、位域、switch、构造函数

2013年12月02日 ⁄ 综合 ⁄ 共 8873字 ⁄ 字号 评论关闭

在vs2005下建立vc++的win32 控制台应用程序,设置stdafx.h不必要包含,设置多字符集,设置汇编输出/FAs。代码和asm解析如下:

#include <stdio.h>
union XXX
{
 struct
 {
  unsigned int H:4;
  unsigned int G:7;
  unsigned int F:6;
  unsigned int E:5;
  unsigned int D:4;
  unsigned int C:3;
  unsigned int B:2;
  unsigned int A:1;
 }; 
 unsigned int i;
 XXX():i(0){}
 XXX(unsigned int t):i(t){}
 XXX(char c, unsigned int t):i(0)
 {
  switch(c)
  {
  case 'A': A = t;break;
  case 'B': B = t;break;
  case 'C': C = t;break;
  case 'D': D = t;break;
  case 'E': E = t;break;
  case 'F': F = t;break;
  case 'G': G = t;break;
  case 'H': H = t;break;
  default:  i = t;break;
  };
 }
};
int main(int argc, char* argv[])
{
 printf("size of XXX = %d/n", sizeof(XXX));
 printf("X = 0x%08x/n", XXX('A', 1).i);
 printf("X = 0x%08x/n", XXX('B', 1).i);
 printf("X = 0x%08x/n", XXX('C', 1).i);
 printf("X = 0x%08x/n", XXX('D', 1).i);
 printf("X = 0x%08x/n", XXX('E', 1).i);
 printf("X = 0x%08x/n", XXX('F', 1).i);
 printf("X = 0x%08x/n", XXX('G', 1).i);
 printf("X = 0x%08x/n", XXX('H', 1).i);
 getchar();
 return 0;
}
/*
XXX的位结构
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
A    B        C              D                    E                          F                                G                                    H
i:31-------------------------------------------------------------------------------------------------------------------------------00
*/ 

asm代码如下,解释前一篇不同的地方:

 .686P
 .XMM
 include listing.inc
 .model flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@ ; `string'
PUBLIC ??0XXX@@QAE@DI@Z    ; XXX::XXX
PUBLIC ??_C@_0BC@CHOOHCKK@size?5of?5XXX?5?$DN?5?$CFd?6?$AA@ ; `string'
PUBLIC _main
EXTRN __imp__getchar:PROC
EXTRN __imp__printf:PROC
EXTRN __RTC_CheckEsp:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC
CONST SEGMENT
??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@ DB 'X = 0x%08x', 0aH, 00H ; `string';相同字符串合并
CONST ENDS
CONST SEGMENT
??_C@_0BC@CHOOHCKK@size?5of?5XXX?5?$DN?5?$CFd?6?$AA@ DB 'size of XXX = %d'
 DB 0aH, 00H     ; `string'
CONST ENDS
rtc$TMZ SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ ENDS
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
rtc$IMZ ENDS
; COMDAT _main
_TEXT SEGMENT
$T3748 = -284      ; size = 4;栈内的临时对象地址定义,相对于进入main函数时的栈顶
$T3749 = -272      ; size = 4
$T3750 = -260      ; size = 4
$T3751 = -248      ; size = 4
$T3752 = -236      ; size = 4
$T3753 = -224      ; size = 4
$T3754 = -212      ; size = 4
$T3755 = -200      ; size = 4
_argc$ = 8      ; size = 4;描述main函数的参数
_argv$ = 12      ; size = 4
_main PROC      ; COMDAT

; 35   : {

 push ebp
 mov ebp, esp
 sub esp, 288    ; 00000120H
 push ebx
 push esi
 push edi
 lea edi, DWORD PTR [ebp-288]
 mov ecx, 72     ; 00000048H
 mov eax, -858993460    ; ccccccccH
 rep stosd

; 36   :  printf("size of XXX = %d/n", sizeof(XXX));

 mov esi, esp
 push 4;sizeof操作在编译期求值。
 push OFFSET ??_C@_0BC@CHOOHCKK@size?5of?5XXX?5?$DN?5?$CFd?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 37   :  printf("X = 0x%08x/n", XXX('A', 1).i);

 push 1;从右向左,参数入栈
 push 65     ; 00000041H
 lea ecx, DWORD PTR $T3748[ebp];临时对象的地址,ebp存的是进入本函数时的栈顶
 call ??0XXX@@QAE@DI@Z   ; XXX::XXX;调用构造函数,前面三个是此函数的三个参数,返回值是this指针,放在eax寄存器中
 mov esi, esp
 mov eax, DWORD PTR [eax];通过XXX临时对象的地址取它的值
 push eax;参数入栈
 push OFFSET ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@;字符串地址,函数参数
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 38   :  printf("X = 0x%08x/n", XXX('B', 1).i);

 push 1
 push 66     ; 00000042H
 lea ecx, DWORD PTR $T3749[ebp]
 call ??0XXX@@QAE@DI@Z   ; XXX::XXX
 mov esi, esp
 mov eax, DWORD PTR [eax]
 push eax
 push OFFSET ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 39   :  printf("X = 0x%08x/n", XXX('C', 1).i);

 push 1
 push 67     ; 00000043H
 lea ecx, DWORD PTR $T3750[ebp]
 call ??0XXX@@QAE@DI@Z   ; XXX::XXX
 mov esi, esp
 mov eax, DWORD PTR [eax]
 push eax
 push OFFSET ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 40   :  printf("X = 0x%08x/n", XXX('D', 1).i);

 push 1
 push 68     ; 00000044H
 lea ecx, DWORD PTR $T3751[ebp]
 call ??0XXX@@QAE@DI@Z   ; XXX::XXX
 mov esi, esp
 mov eax, DWORD PTR [eax]
 push eax
 push OFFSET ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 41   :  printf("X = 0x%08x/n", XXX('E', 1).i);

 push 1
 push 69     ; 00000045H
 lea ecx, DWORD PTR $T3752[ebp]
 call ??0XXX@@QAE@DI@Z   ; XXX::XXX
 mov esi, esp
 mov eax, DWORD PTR [eax]
 push eax
 push OFFSET ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 42   :  printf("X = 0x%08x/n", XXX('F', 1).i);

 push 1
 push 70     ; 00000046H
 lea ecx, DWORD PTR $T3753[ebp]
 call ??0XXX@@QAE@DI@Z   ; XXX::XXX
 mov esi, esp
 mov eax, DWORD PTR [eax]
 push eax
 push OFFSET ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 43   :  printf("X = 0x%08x/n", XXX('G', 1).i);

 push 1
 push 71     ; 00000047H
 lea ecx, DWORD PTR $T3754[ebp]
 call ??0XXX@@QAE@DI@Z   ; XXX::XXX
 mov esi, esp
 mov eax, DWORD PTR [eax]
 push eax
 push OFFSET ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 44   :  printf("X = 0x%08x/n", XXX('H', 1).i);

 push 1
 push 72     ; 00000048H
 lea ecx, DWORD PTR $T3755[ebp]
 call ??0XXX@@QAE@DI@Z   ; XXX::XXX
 mov esi, esp
 mov eax, DWORD PTR [eax]
 push eax
 push OFFSET ??_C@_0M@BOKFPBIA@X?5?$DN?50x?$CF08x?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 45   :  getchar();

 mov esi, esp
 call DWORD PTR __imp__getchar
 cmp esi, esp
 call __RTC_CheckEsp

; 46   :  return 0;

 xor eax, eax

; 47   : }

 pop edi
 pop esi
 pop ebx
 add esp, 288    ; 00000120H
 cmp ebp, esp
 call __RTC_CheckEsp
 mov esp, ebp;栈顶地址复原
 pop ebp;ebp值复原
 ret 0;返回
_main ENDP
; Function compile flags: /Odtp /RTCsu /ZI
_TEXT ENDS
; COMDAT ??0XXX@@QAE@DI@Z
_TEXT SEGMENT
tv65 = -208      ; size = 4;XXX构造函数定义,此处是栈内临时对象定义
_this$ = -8      ; size = 4;this指针参数在最左边
_c$ = 8       ; size = 1
_t$ = 12      ; size = 4
??0XXX@@QAE@DI@Z PROC     ; XXX::XXX, COMDAT
; _this$ = ecx

; 19   :  {

 push ebp
 mov ebp, esp
 sub esp, 208    ; 000000d0H
 push ebx
 push esi
 push edi
 push ecx
 lea edi, DWORD PTR [ebp-208]
 mov ecx, 52     ; 00000034H
 mov eax, -858993460    ; ccccccccH
 rep stosd
 pop ecx
 mov DWORD PTR _this$[ebp], ecx
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], 0

; 20   :   switch(c)

 movsx eax, BYTE PTR _c$[ebp];Move with Sign Extend 
 mov DWORD PTR tv65[ebp], eax
 mov ecx, DWORD PTR tv65[ebp]
 sub ecx, 65     ; 00000041H;switch语句的优化,
 mov DWORD PTR tv65[ebp], ecx
 cmp DWORD PTR tv65[ebp], 7
 ja $LN1@XXX;大于7就跳转,因为有8个case(0~7),大于7就是default那个case
 mov edx, DWORD PTR tv65[ebp]
 jmp DWORD PTR $LN14@XXX[edx*4];根据c-'A'的值edx直接获得跳转地址
$LN9@XXX:

; 21   :   {
; 22   :   case 'A': A = t;break;

 mov eax, DWORD PTR _t$[ebp];位操作开始
 and eax, 1
 shl eax, 31     ; 0000001fH
 mov ecx, DWORD PTR _this$[ebp]
 mov edx, DWORD PTR [ecx]
 and edx, 2147483647    ; 7fffffffH
 or edx, eax
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], edx;edx中是位运算后的XXX,eax中是XXX的地址
 jmp $LN12@XXX
$LN8@XXX:

; 23   :   case 'B': B = t;break;

 mov eax, DWORD PTR _t$[ebp]
 and eax, 3
 shl eax, 29     ; 0000001dH
 mov ecx, DWORD PTR _this$[ebp]
 mov edx, DWORD PTR [ecx]
 and edx, -1610612737   ; 9fffffffH
 or edx, eax
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], edx
 jmp $LN12@XXX
$LN7@XXX:

; 24   :   case 'C': C = t;break;

 mov eax, DWORD PTR _t$[ebp]
 and eax, 7
 shl eax, 26     ; 0000001aH
 mov ecx, DWORD PTR _this$[ebp]
 mov edx, DWORD PTR [ecx]
 and edx, -469762049    ; e3ffffffH
 or edx, eax
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], edx
 jmp $LN12@XXX
$LN6@XXX:

; 25   :   case 'D': D = t;break;

 mov eax, DWORD PTR _t$[ebp]
 and eax, 15     ; 0000000fH
 shl eax, 22     ; 00000016H
 mov ecx, DWORD PTR _this$[ebp]
 mov edx, DWORD PTR [ecx]
 and edx, -62914561    ; fc3fffffH
 or edx, eax
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], edx
 jmp SHORT $LN12@XXX
$LN5@XXX:

; 26   :   case 'E': E = t;break;

 mov eax, DWORD PTR _t$[ebp]
 and eax, 31     ; 0000001fH
 shl eax, 17     ; 00000011H
 mov ecx, DWORD PTR _this$[ebp]
 mov edx, DWORD PTR [ecx]
 and edx, -4063233    ; ffc1ffffH
 or edx, eax
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], edx
 jmp SHORT $LN12@XXX
$LN4@XXX:

; 27   :   case 'F': F = t;break;

 mov eax, DWORD PTR _t$[ebp]
 and eax, 63     ; 0000003fH
 shl eax, 11     ; 0000000bH
 mov ecx, DWORD PTR _this$[ebp]
 mov edx, DWORD PTR [ecx]
 and edx, -129025    ; fffe07ffH
 or edx, eax
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], edx
 jmp SHORT $LN12@XXX
$LN3@XXX:

; 28   :   case 'G': G = t;break;

 mov eax, DWORD PTR _t$[ebp]
 and eax, 127    ; 0000007fH
 shl eax, 4
 mov ecx, DWORD PTR _this$[ebp]
 mov edx, DWORD PTR [ecx]
 and edx, -2033    ; fffff80fH
 or edx, eax
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], edx
 jmp SHORT $LN12@XXX
$LN2@XXX:

; 29   :   case 'H': H = t;break;

 mov eax, DWORD PTR _t$[ebp]
 and eax, 15     ; 0000000fH
 mov ecx, DWORD PTR _this$[ebp]
 mov edx, DWORD PTR [ecx]
 and edx, -16    ; fffffff0H
 or edx, eax
 mov eax, DWORD PTR _this$[ebp]
 mov DWORD PTR [eax], edx
 jmp SHORT $LN12@XXX
$LN1@XXX:

; 30   :   default:  i = t;break;

 mov eax, DWORD PTR _this$[ebp]
 mov ecx, DWORD PTR _t$[ebp]
 mov DWORD PTR [eax], ecx;此处直接就将t的值付给XXX
$LN12@XXX:

; 31   :   };
; 32   :  }

 mov eax, DWORD PTR _this$[ebp]
 pop edi
 pop esi
 pop ebx
 mov esp, ebp
 pop ebp
 ret 8;Return From Procedure
 npad 2;未知
$LN14@XXX:
 DD $LN9@XXX
 DD $LN8@XXX
 DD $LN7@XXX
 DD $LN6@XXX
 DD $LN5@XXX
 DD $LN4@XXX
 DD $LN3@XXX
 DD $LN2@XXX
??0XXX@@QAE@DI@Z ENDP     ; XXX::XXX
_TEXT ENDS
END

抱歉!评论已关闭.