在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