我在上篇文章举了一个简单的C++程序非常简略的解释C++代码和汇编代码的对应关系,在后面的文章中我将按照不同的Topic来仔细介绍更多相关的细节。虽然我很想一开始的时候就开始直接介绍C++和汇编代码的对应关系,不过由于VC编译器会在代码中插入各种检查,SEH,C++异常等代码,因此我觉得有必要先写一下一些在阅读VC生成的汇编代码的时候常见的一些东西,然后再开始具体的分析C++代码的反汇编。这篇文章会首先涉及到运行时检查(Runtime Checking)
Runtime Checking
运行时检查是VC编译器提供了运行时刻的对程序正确性/安全性的一种动态检查,可以在项目的C++选项中打开Small Type Check和Basic Runtime Checks来启用Runtime Check。
同时,也可以使用/RTC开关来打开检查,/RTC后面跟c, u, s代表启用不同类型的检查。Smaller Type Check对应/RTCc, Basic Runtime Checks对应/RTCs和/RTCu。
/RTCc开关
RTCc开关可以用来检查在进行类型转换的保证没有不希望的截断(Truncation)发生。以下面的代码为例:
char ch = 0; short s = 0x101; ch = s; |
当VC执行到ch = s的时候会报告如下错误:
原因是0x101已经超过了char的表示范围。
之前会导致错误地的代码对应的汇编代码如下所示:
; 42 : char ch = 0;
mov BYTE PTR _ch$[ebp], 0
; 43 : short s = 0x101;
mov WORD PTR _s$[ebp], 257 ; 00000101H
; 44 : ch = s;
mov cx, WORD PTR _s$[ebp] call @_RTC_Check_2_to_1@4 mov BYTE PTR _ch$[ebp], al |
可以看到,赋值的时候,VC编译器先将s的值放到cx寄存器中,然后调用_RTC_Check_2_to_1@4函数来检查是否有数据截断的问题,结果放在al中,最后将al放到ch之中。_RTC_Check_2_to_1@4顾名思义是检查2个byte的数据被转换成1个byte的数据(short是2个byte,char是一个byte),代码如下:
_RTC_Check_2_to_1: 00411900 push ebp 00411901 mov ebp,esp 00411903 push ebx 00411904 mov ebx,ecx 00411906 mov eax,ebx 00411908 and eax,0FF00h 0041190D je _RTC_Check_2_to_1+24h (411924h) 0041190F cmp eax,0FF00h 00411914 je _RTC_Check_2_to_1+24h (411924h) 00411916 mov eax,dword ptr [ebp+4] 00411919 push 1 0041191B push eax 0041191C call _RTC_Failure (411195h) 00411921 add esp,8 00411924 mov al,bl 00411926 pop ebx 00411927 pop ebp 00411928 ret |
1.