关于C++: try...catch...的汇编实现

wonaixiaogang 2009-05-18 10:34:40

//这里是C++的源码
#include "stdafx.h"
void main()
{
int i;
try
{
i=0;
i++;
}
catch(...)
{
i++;
}
}


;这里是VC2008 输出的反汇编源码
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.21022.08

TITLE d:\VC++应用程序\test\test\test\test.cpp
.686P
.XMM
include listing.inc
.model flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC _main
EXTRN ___security_cookie:DWORD
EXTRN ___CxxFrameHandler3:PROC
EXTRN @__security_check_cookie@4:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC
; COMDAT xdata$x
; File d:\vc++应用程序\test\test\test\test.cpp
xdata$x SEGMENT
__catchsym$_main$2 DD 040H
DD 00H
DD 00H
DD FLAT:__catch$_main$0
__unwindtable$_main DD 0ffffffffH
DD 00H
DD 0ffffffffH
DD 00H
__tryblocktable$_main DD 00H
DD 00H
DD 01H
DD 01H
DD FLAT:__catchsym$_main$2
__ehfuncinfo$_main DD 019930522H
DD 02H
DD FLAT:__unwindtable$_main
DD 01H
DD FLAT:__tryblocktable$_main
DD 2 DUP(00H)
DD 00H
DD 01H
xdata$x ENDS
; COMDAT rtc$TMZ
rtc$TMZ SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ ENDS
; COMDAT rtc$IMZ
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ ENDS
; COMDAT _main
_TEXT SEGMENT
_i$ = -24 ; size = 4
__$EHRec$ = -16 ; size = 16
_main PROC ; COMDAT

; 7 : {

push ebp
mov ebp, esp
push -1
push __ehhandler$_main
mov eax, DWORD PTR fs:0
push eax
push ecx
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-220]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
mov eax, DWORD PTR ___security_cookie
xor eax, ebp
push eax
lea eax, DWORD PTR __$EHRec$[ebp+4]
mov DWORD PTR fs:0, eax
mov DWORD PTR __$EHRec$[ebp], esp

; 8 : int i;
; 9 : try
; 10 : {

mov DWORD PTR __$EHRec$[ebp+12], 0

; 11 : i=0;

mov DWORD PTR _i$[ebp], 0

; 12 : i++;

mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax

; 13 : }

jmp SHORT $LN4@main
__catch$_main$0:

; 14 : catch(...)
; 15 : {
; 16 : i++;

mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax

; 17 : }

mov DWORD PTR __$EHRec$[ebp+12], -1
mov eax, $LN2@main
ret 0
$LN4@main:
mov DWORD PTR __$EHRec$[ebp+12], -1
$LN2@main:

; 18 : }

xor eax, eax
mov ecx, DWORD PTR __$EHRec$[ebp+4]
mov DWORD PTR fs:0, ecx
pop ecx
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_TEXT ENDS
; COMDAT text$x
text$x SEGMENT
__ehhandler$_main:
mov edx, DWORD PTR [esp+8]
lea eax, DWORD PTR [edx+12]
mov ecx, DWORD PTR [edx-224]
xor ecx, eax
call @__security_check_cookie@4
mov eax, OFFSET __ehfuncinfo$_main
jmp ___CxxFrameHandler3
text$x ENDS
_main ENDP
END

求汇编源码每一行的详细解释,谢谢!!!!
...全文
895 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
amethystsnow 2009-09-28
  • 打赏
  • 举报
回复
DDK里的macro就有_TRY,,何必每次都自己...
三分001 2009-09-18
  • 打赏
  • 举报
回复
张口就是:
[Quote=引用楼主 wonaixiaogang 的回复:]

求汇编源码每一行的详细解释,谢谢!!!!

[/Quote]

楼主真够无耻的.
gp341 2009-08-26
  • 打赏
  • 举报
回复
看罗云斌的书里介绍的很详细
大熊猫侯佩 2009-08-21
  • 打赏
  • 举报
回复
seh包装,注意fs的读写
土豆 2009-08-21
  • 打赏
  • 举报
回复
顶一个
DarkChampion 2009-08-21
  • 打赏
  • 举报
回复
mark
gzgzlxg 2009-08-21
  • 打赏
  • 举报
回复
直接使用LIBC.LIB中的vc++的初始化函数。
回帖是一种美德。
  • 打赏
  • 举报
回复
汇编啊,汇编
wlg_linux 2009-08-18
  • 打赏
  • 举报
回复
#include "stdafx.h"
void main()
{
int i;
try
{
i=0;
i++;
}
catch(...)
{
i++;
}
}
在Linux平台上只需要执行命令gcc -S file.cpp就可以得到它的汇编形式。
Michael_g 2009-05-26
  • 打赏
  • 举报
回复
返回值说明:
错误处理函数的返回值只有两个。
EXCEPTION_CONTINUE_SEARCH = 1 不处理异常,转交系统处理
EXCEPTION_CONTINUE_EXECUTION = 0 修复错误,从异常发生处继续执行

其它关于 错误处理函数参数的信息参看 http://tieba.baidu.com/f?kw=waruqi 里的《SEH结构化异常处理》
Michael_g 2009-05-26
  • 打赏
  • 举报
回复
SEH 异常原理:
在 Windows 下,fs:[0] 指向一个SEH 数据结构,当发生异时,系统会调用 SEH结构指向的错误处理函数,所以我们中要改变 fs:[0]里的内容就行了。原理如下:
SEH结构:
{
DWORD NextSEH; 下个SEH结构
DWORD ErrProc; 错误处理函数
}
实现方法如下:

push Error_Handler ;压入错误处理函数地址
push fs:[0] ; 压入当SEH结构地址
mvo fs:[0],esp ;更新 SEH 链表,使其指向你的SEH

xor eax,eax
mov eax,dword ptr [eax];产生异常

...
...

恢复原SEH链表
pop dword ptr fs:[0]
pop eax



错误处理函数定义
Error_Handler proc uses ecx lpExceptRecord:DWORD, lpFrame:DWORD, lpContext:DWORD, lpDispatch:DWORD
...
...

ret
Error_Handler endp
Areslee 2009-05-25
  • 打赏
  • 举报
回复
try/throw/catch和SEH不同的
xiaopoy 2009-05-25
  • 打赏
  • 举报
回复
try/throw/catch在win下是包装的seh,正是LZ想知道的,不然问的该是c++的try/throw/catch如何实现。

   TITLE    d:\VC++应用程序\test\test\test\test.cpp
.686P
.XMM
include listing.inc
.model flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC _main
EXTRN ___security_cookie:DWORD
EXTRN ___CxxFrameHandler3:PROC
EXTRN @__security_check_cookie@4:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC
; COMDAT xdata$x
; File d:\vc++应用程序\test\test\test\test.cpp

此段类似于c.h文件,定义个样子。包括了目标object所用的指令系和内存模式,导入的头文件和库,导出的函数。

_i$ = -24                        ; size = 4
__$EHRec$ = -16 ; size = 16

全局变量定义

_main    PROC                        ; COMDAT

; 7 : {

push ebp
mov ebp, esp//保护上级函数的参数
push -1
push __ehhandler$_main
mov eax, DWORD PTR fs:0
push eax
push ecx
sub esp, 204 ; 000000ccH //划分要用的堆栈
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-220] // rep stosd,把edi指向的ecx*4字节的数据覆盖为eax.
//即将自己堆栈初始化为0xcccccccc,这特色的数字在溢出时有助于定位溢出code
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
mov eax, DWORD PTR ___security_cookie //cookie为vc带/GS保护堆栈参数时的产品。
//意为, 在缓冲区和返回地址间的"缓冲带"
//发生溢出则cookie会首先被覆盖,在函数结束调用返回地址前检查cookie若错误则已溢出停止执行,便阻止了对溢
//出的利用
xor eax, ebp
push eax
lea eax, DWORD PTR __$EHRec$[ebp+4] //初始化SEH结构
mov DWORD PTR fs:0, eax //fs:0为ETHREAD 结构,fs:[0]为当前函数的SEH结构指针
mov DWORD PTR __$EHRec$[ebp], esp//此处的__$EHRec$为__ehhandler$_main的别名
mov DWORD PTR __$EHRec$[ebp+12], 0
; 8 : int i; //所的对应c++code
; 9 : try
; 10 : {




; 11   :         i=0;

mov DWORD PTR _i$[ebp], 0

; 12 : i++;

mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax

i= 0;
i= i+1;
i= i;

; 13   :     }
jmp SHORT $LN4@main

执行至函数解释未出错则直接运行退出函数code

$LN4@main:
mov DWORD PTR __$EHRec$[ebp+12], -1
$LN2@main:

; 18 : }

xor eax, eax
mov ecx, DWORD PTR __$EHRec$[ebp+4] //恢复FS:0为上个函数的SEH结构
mov DWORD PTR fs:0, ecx
pop ecx
pop edi
pop esi
pop ebx
mov esp, ebp //整理堆栈。抛弃本函数的堆栈
pop ebp
ret 0 //返回上层函数
_TEXT ENDS
; COMDAT text$x
text$x SEGMENT



__catch$_main$0:

; 14 : catch(...)
; 15 : {
; 16 : i++;

mov eax, DWORD PTR _i$[ebp] //捕获到异常后执行 i= i+1; i= i;
add eax, 1
mov DWORD PTR _i$[ebp], eax

; 17 : }

mov DWORD PTR __$EHRec$[ebp+12], -1//置空本函数SEH callback的指针
mov eax, $LN2@main//返回给运行时库 下一步要执行的code
ret 0

catch为一个被运行时库调用的callback

__ehhandler$_main:
mov edx, DWORD PTR [esp+8]
lea eax, DWORD PTR [edx+12]
mov ecx, DWORD PTR [edx-224]
xor ecx, eax
call @__security_check_cookie@4
mov eax, OFFSET __ehfuncinfo$_main
jmp ___CxxFrameHandler3
text$x ENDS
_main ENDP
END

c++默认的异常处理流程:
检查cookie并在溢出时处理。不做任何异常的修复,直接反馈给上层SEH
huofen2005 2009-05-21
  • 打赏
  • 举报
回复
不会,帮顶!
VC6的代码反汇编下44看。
。Net代码复杂化了
cnzdgs 2009-05-18
  • 打赏
  • 举报
回复

21,500

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧