在vs2005下建立vc++的win32 控制台应用程序,设置stdafx.h不必要包含,设置多字符集,设置汇编输出/FAs。代码和asm解析如下:
#include <stdio.h>
struct X
{
int i,j,k;//0,4,8,12
};
class XXX
{
public:
int ipub;//0
X xpub;//4
int ipub3;//16
protected:
int ipro;//20
X xpro;//24
private:
int ipri;//36
X xpri;//40
public:
int ipub2;//52
X xpub2;//56
public:
int get_ipri(){return ipri;}
static void set_ipri(XXX &p, int i){p.ipri = i;}
};
#define PRINTF_OFFSET(TYPE, a) printf("offset of "#TYPE"."#a" = %d/n", &(((TYPE*)0)->a))
int main(int argc, char* argv[])
{
PRINTF_OFFSET(XXX,ipub);
PRINTF_OFFSET(XXX,xpub);
PRINTF_OFFSET(XXX,xpub.i);
PRINTF_OFFSET(XXX,xpub.k);
PRINTF_OFFSET(XXX,ipub3);
PRINTF_OFFSET(XXX,ipub2);
PRINTF_OFFSET(XXX,xpub2);
PRINTF_OFFSET(XXX,xpub2.j);
PRINTF_OFFSET(XXX,xpub2.k);
XXX t;
XXX::set_ipri(t, 1);
printf("t.ipri = %d/n", t.get_ipri());
*(((int*)(&t))+9) = 110;
printf("t.ipri = %d/n", t.get_ipri());
getchar();
return 0;
}
_TEXT SEGMENT
_t$ = -72 ; size = 68
_argc$ = 8 ; size = 4
_argv$ = 12 ; size = 4
_main PROC ; COMDAT
; 27 : {
push ebp
mov ebp, esp
sub esp, 268 ; 0000010cH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-268]
mov ecx, 67 ; 00000043H
mov eax, -858993460 ; ccccccccH
rep stosd
; 28 : PRINTF_OFFSET(XXX,ipub);
mov esi, esp
push 0;XXX中变量的地址在编译期确定
push OFFSET ??_C@_0BJ@DEEPAIAO@offset?5of?5XXX?4ipub?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 29 : PRINTF_OFFSET(XXX,xpub);
mov esi, esp
push 4;XXX中变量的地址在编译期确定
push OFFSET ??_C@_0BJ@FLDHBDAF@offset?5of?5XXX?4xpub?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 30 : PRINTF_OFFSET(XXX,xpub.i);
mov esi, esp
push 4;XXX中自定义变量中的变量的地址也在编译期确定
push OFFSET ??_C@_0BL@NHCPLOO@offset?5of?5XXX?4xpub?4i?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 31 : PRINTF_OFFSET(XXX,xpub.k);
mov esi, esp
push 12 ; 0000000cH;XXX中自定义变量中的变量的地址也在编译期确定
push OFFSET ??_C@_0BL@EPFHPMJD@offset?5of?5XXX?4xpub?4k?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 32 : PRINTF_OFFSET(XXX,ipub3);
mov esi, esp
push 16 ; 00000010H
push OFFSET ??_C@_0BK@KPHJBKLN@offset?5of?5XXX?4ipub3?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 33 : PRINTF_OFFSET(XXX,ipub2);
mov esi, esp
push 52 ; 00000034H
push OFFSET ??_C@_0BK@GDNDBKCD@offset?5of?5XXX?4ipub2?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 34 : PRINTF_OFFSET(XXX,xpub2);
mov esi, esp
push 56 ; 00000038H
push OFFSET ??_C@_0BK@PEGOLLLA@offset?5of?5XXX?4xpub2?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 35 : PRINTF_OFFSET(XXX,xpub2.j);
mov esi, esp
push 60 ; 0000003cH
push OFFSET ??_C@_0BM@MCECCCHD@offset?5of?5XXX?4xpub2?4j?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 36 : PRINTF_OFFSET(XXX,xpub2.k);
mov esi, esp
push 64 ; 00000040H;XXX中自定义变量中的变量的地址也在编译期确定
push OFFSET ??_C@_0BM@OOICCON@offset?5of?5XXX?4xpub2?4k?7?$DN?7?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 37 : XXX t;
; 38 : XXX::set_ipri(t, 1);
push 1
lea eax, DWORD PTR _t$[ebp];引用参数的传递,实际是地址值
push eax
call ?set_ipri@XXX@@SAXAAV1@H@Z ; XXX::set_ipri
add esp, 8
; 39 : printf("t.ipri = %d/n", t.get_ipri());
lea ecx, DWORD PTR _t$[ebp]
call ?get_ipri@XXX@@QAEHXZ ; XXX::get_ipri
mov esi, esp
push eax
push OFFSET ??_C@_0N@CDKCAMPO@t?4ipri?5?$DN?5?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 40 : *(((int*)(&t))+9) = 110;
mov DWORD PTR _t$[ebp+36], 110 ; 0000006eH;强行访问private变量也是可行的,说明private修饰符只在编译期有效,实际运行时刻没有所谓的private
; 41 : printf("t.ipri = %d/n", t.get_ipri());
lea ecx, DWORD PTR _t$[ebp]
call ?get_ipri@XXX@@QAEHXZ ; XXX::get_ipri
mov esi, esp
push eax
push OFFSET ??_C@_0N@CDKCAMPO@t?4ipri?5?$DN?5?$CFd?6?$AA@
call DWORD PTR __imp__printf
add esp, 8
cmp esi, esp
call __RTC_CheckEsp
; 42 : getchar();
mov esi, esp
call DWORD PTR __imp__getchar
cmp esi, esp
call __RTC_CheckEsp
; 43 : return 0;
xor eax, eax
; 44 : }
push edx
mov ecx, ebp
push eax
lea edx, DWORD PTR $LN5@main
call @_RTC_CheckStackVars@8
pop eax
pop edx
pop edi
pop esi
pop ebx
add esp, 268 ; 0000010cH
cmp ebp, esp
call __RTC_CheckEsp
mov esp, ebp
pop ebp
ret 0
npad 2
$LN5@main:
DD 1
DD $LN4@main
$LN4@main:
DD -72 ; ffffffb8H
DD 68 ; 00000044H
DD $LN3@main
$LN3@main:
DB 116 ; 00000074H
DB 0
_main ENDP
; Function compile flags: /Odtp /RTCsu /ZI
_TEXT ENDS
; COMDAT ?get_ipri@XXX@@QAEHXZ
_TEXT SEGMENT
_this$ = -8 ; size = 4
?get_ipri@XXX@@QAEHXZ PROC ; XXX::get_ipri, COMDAT
; _this$ = ecx
; 22 : int get_ipri(){return ipri;}
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
push ecx
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
pop ecx
mov DWORD PTR _this$[ebp], ecx
mov eax, DWORD PTR _this$[ebp]
mov eax, DWORD PTR [eax+36]
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
?get_ipri@XXX@@QAEHXZ ENDP ; XXX::get_ipri
; Function compile flags: /Odtp /RTCsu /ZI
_TEXT ENDS
; COMDAT ?set_ipri@XXX@@SAXAAV1@H@Z
_TEXT SEGMENT
_p$ = 8 ; size = 4
_i$ = 12 ; size = 4
?set_ipri@XXX@@SAXAAV1@H@Z PROC ; XXX::set_ipri, COMDAT
; 23 : static void set_ipri(XXX &p, int i){p.ipri = i;}
push ebp
mov ebp, esp
sub esp, 192 ; 000000c0H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-192]
mov ecx, 48 ; 00000030H
mov eax, -858993460 ; ccccccccH
rep stosd
mov eax, DWORD PTR _p$[ebp]
mov ecx, DWORD PTR _i$[ebp]
mov DWORD PTR [eax+36], ecx
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
?set_ipri@XXX@@SAXAAV1@H@Z ENDP ; XXX::set_ipri
_TEXT ENDS
END