《“NGNide集成调试环境”简介》(NGNc专用)

类别:编程语言 点击:0 评论:0 推荐:

http://www.ngnc.net/NGNide/NGNide_intro.htm

《“NGNide集成调试环境”简介》 文档更新日期:2004年6月10日

NGNc在语言规则上没有什么差别,因为在一开始设定项目目标时,简单好用的标准c语法就作为了NGNc的首选;那它唯一的“标新立异”就是花了些工夫编写了它的专有的IDE(集成调试环境),将来的发展方向是集成开发环境。这是目前只有商业脚本语言如JAVA才会做的工作。

NGNide的当前版本的开发目标是,具备最基本的调试器功能,断点、单步调试、调试信息包括(虚拟机反编译,局部变量,全局变量浏览与“Watch”查看列表,“Slot”进程状态/算术寄存器、堆栈浏览、真实内存浏览)。下面通过对“NGNcalc2x”的调试说明它的使用方法和功能。

下面是NGNide调试NGNcalc2x的桌面:

启动NGNide:

这是NGNide的图标 (大)(小),双击启动它。下面是它的主界面:

NGNide的主界面有5个部分,自上而下分别是:标题、菜单、工具条、主视图、状态条;

1、标题条:为当前调试目标的工程文件名(默认为ngn.ini)。它是文本格式,请浏览该文件,各“Section”段都有明确的注释,说明工程文件各个部分段的意义;

2、菜单:功能同工具条;

3、工具条:(详细说明见:工具条的功能详解)

第1至第5为调用NGNc.exe,对目标工程文件进行编译的按扭;

第6至第10是对编译结果进行调试所需要的操作;如:设置环境,载入插件等;

第11至第15是目标代码显示的详细程度控制,以及汇编显示方式,断点设置等;

第16至19是目标代码运行和停止,重新载入和重置;

第20至23是单步调试相关的功能;

4、主视图:编译结果显示区域和显示调试代码的区域,其中在显示调试代码时,有当前执行位置(EIP指针位置)(兰色条),断点标记(棕色圆点)等。在启动时,此区域为空白,无任何内容,待编译或载入目标调试信息和代码时候才会有信息显示;

5,状态条:以显示工具条按扭的详细功能注释;

编译目标工程文件:

因为前5个工具条都是通过调用NGNc.exe和与其通信完成IDE环境下编译脚本的,因此不做详细描述,请参考NGNc.exe的使用说明,它是一个可以通过命令行执行的编译器。

NGNide是为了NGNc.exe增加了一些选择目标路径等的外部操作,方便使用而已;

选择调试目标,并准备:

通过点击按扭6),将打开NGNc.ini编辑和调试环境设置对话框,如下:

(首先选择NGN.ini文件)

(NGNc.ini编辑和调试环境设置对话框)

该对话框有2部分:路径设置,插件管理。

“NGNc.ini Location”,为对话框显示前选择的目标位置;

“Uedit32.exe Location”,为Uedit32.exe的安装位置

(注:Uedit32.exe是IDM Computer Solutions, Inc开发的UltraEdit_-32 Professional Text/HEX Editor的主执行程序,因为NGNc.exe使用了其命令行参数接口,控制调试代码和调试信息的显示,此参数并不影响IDE的调试功能,详见NGNc.exe的使用说明)

“当前插件声明”,是“插件名称/路径”列表中选择的插件的函数声明,也就是插件和脚本语言的接口函数,在调试目标代码前,一定要保证载入目标代码必须的插件。

“添加/删除插件”是管理插件列表的功能键;

“OK”:只有按该键,系统才会接受当前显示的参数,并将插件载入内存;“Cancel”则放弃;

载入调试信息,和目标代码:

通过点击按扭7),将利用NGNc.ini里描述的调试信息文件(默认为LOG.LOG),该文件是NGNc.exe编译产生的调试信息文件,NGNide通过对其的分析,将需要的调试信息载入内存;正确载入后,主界面的主视图区域就会显示目标调试代码;首次载入,只显示调试目标的函数声明,而无函数体{}Block。可以通过按扭11),按扭12),控制调试目标的显示深度,只有函数体{}Block显示,相应的功能按扭才会Enabled;

通过点击按扭9),将利用NGNc.ini里描述的编译结果的目标代码(.obj)文件名,载入目标obj。并显示调试入口对话框(如下),选择一个函数,“OK确定”后,正式进入调试状态;其间可以通过按扭10),任意改变调试入口,展开新的调试;

“func name list”,是选择入口函数的列表。首次打开时,默认为起点函数“void Start( void )”,如果没有该函数,则定位到第一个函数。

“param list”,是“func name list”相应函数的参数列表,可以通过其他控制输入参数数值,用于调试独立函数,而不需要一切调试都从目标Obj的入口Start函数开始。可以作到函数级的测试;请参考高级应用指南,了解如何操作函数级的调试。

调试环境:

1、调试环境介绍:

:表示当前行,是脚本执行的当前指令指针eip所在位置;

:表示当前行为一个程序断点,脚本运行到此将暂时中断;(粉色条是当前选择脚本行)

:鼠标移动,相应的行以反白显示,表示当前鼠标行位置,点击或双击将设置之;

2、调试信息窗口:

进入调试状态,将会显示下面的2个调试信息窗口:

“Slot View”是NGNc虚拟机的一个线程的状态集合。“slot envir”是控制寄存器集,“registers”是全局算术寄存器,作为临时变量使用,“breaks”是断点列表,“watchs”是公用的调试信息选择窗口,“stack”是线程堆栈。

“Contents View”是调试信息具体内容的显示区域,如上图的注释,表明此区域为公用的显示区域,它可以显示局部/全局以及寄存器的当前状态/数值,物理内存的绝对地址内容等。同时还兼具备命令和修改的功能(详见:IDE高级应用指南)。

:是窗口Docking按扭,控制“Contents View”与“Slot view”窗口间的位置关系,通过移动“Contents View”到“Slot view”窗口的上、下、左、右也可以自动实现Docking操作。此功能是为了方便调试和使用者的个性习惯而设。

3、寄存器的状态显示:

(1) (2)

选择“registers”里的寄存器“_eax_”,在“Contents View”的公共显示区域内显示。

NGNc虚拟机的寄存器支持10种基本数据类型,对应c类型如下:.c (char)、.uc (uchar, unsigned char)、.s (short)、.us (ushort, unsigned short)、.l (long)、.ul (ulong, unsigned long)、.f (float)、.db (double)、.ldb (ldouble, long double);“registers” 内的寄存器类型是当前Slot运行时IDE对寄存器的类型预测的结果和数值(等号后的数值为10进制和16进制2种)。

3、局部变量的状态显示:

(1) (2) (3)

局部变量分2种,参数和局部变量。选择“slot envir”中的“par”参数,“loc”局部变量,将在“watchs”区域显示变量树(如图2),再在变量树里选择相应的项目,在“Contents View”的公共显示区域内显示。

内容信息格式:偏移,类型,名,10进制数(16进制数)

4、全局变量的状态显示:

(1) (2)

按下“show all globals”将显示全局变量树,您可以选择其中有“+”号的树节点,展开结构或数组或指针。选择任何一个节点,都会在“Contents View”的公共显示区域内(图2)显示相应的调试信息。

选择父节点,显示包含子节点;选择子节点,显示包含树结构。内容信息格式同“局部变量”一致。

5、Watch观察列表维护:

(1) (2)

“show all globals”和“show watchs”是同一个按扭,切换全局变量树与Watch列表。当显示观察列表的时候,“Contents View”的公共显示区域内(图2)就会显示观察列表内容,如果只有一个选择则显示全部列表,并滚动选择的观察项到窗口中,并用“<<<<<<<<<<”标记之;如果有2个和以上观察项选择,则只显示选择的观察项。

添加局部/全局变量:选择相应的变量节点,点击“add watch”即可。

添加寄存器:选择寄存器,然后在“Contents View”的公共显示区域内,选择寄存器数据类型,再点击“add watch”即可。

删除Watch观察项:选择“del watch”删除之。

开始调试和运行:

1、运行目标脚本:

正确载入目标,并选择了入口后,按17)键或快捷键(F5),即可运行目标,如果没有设置任何断点。目标脚本终止后提示使用者查看返回结果。如下图:

脚本结束并不表示Slot线程的释放,依然可以查看它的状态,包括返回寄存器“_ret_”。只有在按键19),释放“Slot”时,才无法查看,且“Slot view”和“Contents view”窗口将关闭。

2、调试目标脚本:

NGNide具备所有基本的调试能力,各个调试功能都可以通过快捷键和工具按扭执行,参考:工具条功能详解,理解相应按扭功能。以下说明几个主要的常使用的调试技巧。

快捷键与输入焦点:在调试信息窗口内操作浏览调试信息的时候,按调试快捷键是无效的。这时按“Esc”键,将输入焦点自动转移到IDE的主界面,就可以相应快捷调试用的快捷键了。

调试观察列表的使用:在调试状态,如单步执行和断点运行时,“Contents View”的公共显示区域内将根据调试窗口的状态自动显示调试信息。如果有观察列表,将显示观察列表。如果观察列表为空,最后一次选择的调试信息将作为调试观察用的信息,比如:最后一次观察的是“Loc”信息,在调试时将自动更新局部变量的数值显示于“Contents View”的公共显示区域内。在调试状态,寄存器信息不做观察显示,所以需要用Watch观察列表明确加入,才会自动更新寄存器的数值状态,这只用于虚拟机伪机器码的调试,普通脚本编写不需要。使用观察列表的选择功能,可简化观察列表的显示内容,以简化调试。

断点定位和脚本执行指针EIP的定位作用:双击eip和brk列表项都会自动定位到相应的脚本行,便于程序浏览。并自动将焦点切换到主窗口。

当前选择脚本行的断点应用:粉色条,是在鼠标行单击左键的结果。设置/清除断点都以此标记为准。键20)(F4, Here)功能,实际为在当前选择脚本行设置一个临时断点的作用,但不对其标记,这从Brk列表可以看到。使用此方法,简化了Here操作,持续按F4可以模拟设置1个断点后循环按F5的功能。

变量树的浏览:NGNide的变量树的显示和初始化是分阶段的,首次显示,则只显示父节点,子节点信息在点“+”后,才做显示。因此,在没有点“+”前,选择父节点,“Contents View”的公共显示区域内只显示父节点的内容,不显示子节点。点“+”后,才会显示整个父节点信息包括子节点。

调试信息窗口的安排:以Calc2x的调试为例,因为为了能同时观察调试信息和调试代码,又需要查看目标脚本的运行界面,需要将所有窗口显示在一个桌面。通过调整IDE主窗口,和调试信息的Docking操作,将Calc2x的Dos虚拟机窗口显示出来,边单步执行,边查看,可以了解CalC2x的脚本逻辑和层次。

IDE工作环境的保存:NGNide为每次工作的状态进行保存,再下次启动IDE继续工作时将比较方便。保存的内容包括,选择目标ngn.ini的路径,Uedit32.exe的路径,插件列表,主窗口和调试窗口的位置和尺寸和Docking结构。环境信息保存于SymTrace.ini文件中。

重设调试环境:在调试过程中,可以通过按键19)或(Ctrl-S快捷键),来终止Slot的执行,并释放它,将关闭调试窗口。按键16),或(F2)快捷键将重新载入之前选择的函数。不终止Slot,直接按F2也同样重新初始化Slot为脚本函数的入口。

切换调试入口:在调试过程中Slot还在运行的状态下,按键10),或Ctrl-F2快捷键,切换入口是危险的。您需要明确地终止和释放当前Slot,才是安全的。通过按19)或(Ctrl-S快捷键),会提示信息如下,选择“是(Y)”将终止并释放Slot。

转变调试目标:在新版本的obj产生,需要重新载入调试信息和编译结果obj时,或强制调试伪机器码的obj脚本模块的时候,且已经进入了调试状态。选择按键6),选择新的NGN.ini前,系统会提示下面信息,确认是否要释放当前调试信息和调试目标模块obj。只有“是(Y)”释放掉当前信息,才可以重新选择。

附件一:工具条功能详解:

1):显示编译结果(刷新);NGNc.exe运行状态和结束后的错误信息显示(切换到编译信息);

2):运行NGNc和ini路径;运行同目录下的NGNc.exe并设置NGN.ini路径;

3):运行NGNc;运行同目录下的NGNc.exe;

4):暂停NGNc;暂停NGNc;

5):继续运行;继续运行;

6):编辑NGNc.ini;选择NGNc.ini文件并进行编辑;(见NGNc.ini编辑对话框的说明)

7):读入调试信息;读入LOG.LOG文件并提取调试信息;

8):调试信息加入OBJ;将调试信息混合入OBJ目标文件中;

9):载入目标Obj;载入目标文件准备调试,同时设置入口参数;

10):设置调试入口参数(Ctrl-F2);直接设置已经载入的目标调试入口参数;

11):显示调试信息"+";显示编译的LOG.LOG的调试信息, 深度增加;

12):显示调试信息"-";显示编译的LOG.LOG的调试信息, 深度减少;

13):Asm代码显示开关;开关Hex代码指令显示方式;

14):设置/清除断点;设置/清除调试断点Break;

15):清除所有断点;清除所有断点;

16):回到初始调试状态(F2);重置Slot为初始化状态,并定位到第1条指令;

17):继续运行OBJ(F5);从当前位置继续运行调试代码;

18):暂停执行(Ctrl-P);暂停程序于当前指针处,其他执行键将终止暂停状态;

19):停止运行(Ctrl-S);停止运行并释放当前Slot;

20):运行到Here(F4);运行到当前所选行的位置;

21):单步执行(F7);单步骤执行,在遇到函数时进入函数体;

22):单指令执行(F8);单指令执行,在遇到函数时执行函数;

23):返回调用(F12);强制返回上次调用的地址;

本文地址:http://com.8s8s.com/it/it28791.htm