实验3 编程、编译、连接、跟踪
2018-02-13 17:17
169 查看
实验3 编程、编译、连接、跟踪
(1)将下面的程序保存为t1.asm文件,将其生产可执行文件t1.exe。
(2)用debug跟踪t1.exe的执行过程,写出每一步骤执行后,相关寄存器中的内容和栈顶的内容。
(3)PSP的头两个字节是CD 20,用debug加载t1.exe,查看PSP的内容。
实验结果:【1】编译、连接t1.asm汇编源程序。1)在windows XP中,打开cmd窗口,编译t1.asm程序。如下图:E:\assembly>masm t1.asmMicrosoft (R) MASM Compatibility DriverCopyright (C) Microsoft Corp 1993. All rights reserved. Invoking: ML.EXE /I. /Zm /c /Ta t1.asm Microsoft (R) Macro Assembler Version 6.15.8803 Patched for you by promethee [ECL] in the year 2001 - enjoyCopyright (C) Microsoft Corp 1981-2000. All rights reserved. Assembling: t1.asm如果没有任何错误,编译器会生成一个t1.obj的文件。如果有语法等严重的错误,编译器会给出错误信息,你可以根据错误信息,修改源代码相关的行。连接这个obj文件,并生成t1.exe文件:如下图:E:\assembly>link t1.objMicrosoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994Copyright (C) Microsoft Corp 1984-1993. All rights reserved. Run File [t1.exe]: t1.exeList File [nul.map]:Libraries [.lib]:[b]Definitions File [nul.def]:LINK : warning L4021: no stack segmentLINK : warning L4038: program has no starting address连接讲解:1)其中运行文件:我们输入我们将要生成的可执行程序(例如.exe)文件的名称。List File [nul.map]: 我们回车,没有列表文件;Libraries [.lib]: 我们回车,没有库文件Definitions File [nul.def]: 我们回车,没有交叉定义文件2)LINK : warning L4021: no stack segment 警告信息:没有栈段定义; LINK : warning L4038: program has no starting address 警告信息:程序没有起始地址。 你可以根据连接程序的提示信息来修正你的源程序;一般的警告信息,我们都忽略了。关于编译器的详细介绍,请参考相应的编译器手册。【2】用debug跟踪t1.exe的执行过程在命令提示符下键入:debug t1.exe使用r命令查看寄存器信息。-rAX=0000 BX=0000 CX=0016 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=0B65 CS=0B65 IP=0000 NV UP EI PL NZ NA PO NC0B65:0000 B80020 MOV AX,20001)CX寄存器介绍:cx=0016; 含义:cx寄存器是通用寄存器,也是计数寄存器,cx还有一个功能是在程序最初始记录程序代码的字节数;我们使用d命令查看它-d cs:00B65:0000 B8 00 20 8E D0 BC 00 00-83 C4 0A 58 5B 50 53 58 .. ........X[PSX0B65:0010 5B B8 00 4C CD 21 A9 02-00 75 05 2E FF 06 48 91 [..L.!...u....H.红色标记的是执行的机器码。注意此时的0016是16进制的,也就是22个字节,你数数!你也可以使用U命令查看汇编指令和机器码,一样。-u cs:00B65:0000 B80020 MOV AX,20000B65:0003 8ED0 MOV SS,AX0B65:0005 BC0000 MOV SP,00000B65:0008 83C40A ADD SP,+0A0B65:000B 58 POP AX0B65:000C 5B POP BX0B65:000D 50 PUSH AX0B65:000E 53 PUSH BX0B65:000F 58 POP AX0B65:0010 5B POP BX0B65:0011 B8004C MOV AX,4C000B65:0014 CD21 INT 21各寄存器状态值:CS=0B65 IP=0000 SS=0B652)执行代码 mov ax, 2000H mov ss, ax mov sp, 0代码含义:将2000H段开始的内存单元创建一个栈结构。栈顶指针ss:sp指向00H。这就意味着如果栈结构是空的,那么它的栈容量是64K。 &n@��怎么没有了那些t命令的中断例程保存的寄存器变量了?你在1FFF:0010H处,也就是它的低地址处看看有吗?执行后:AX=2000 BX=0000 CX=0016 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=0008 NV UP EI PL NZ NA PO NC3)执行代码: add sp, 10代码含义:明确说明sp指向10,也就是说我们创建的栈结构空间分配是10个字节; 使用d命令查看ss:0内存段,发现那些久违的寄存器变量数据就存储在这里,从2000:0a向低地址存储;我们不用管他们。执行后:AX=2000 BX=0000 CX=0016 DX=0000 SP=000A BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=000B NV UP EI PL NZ NA PE NC4)执行代码: pop ax pop bx代码含义:pop ax;将ss:sp指向的字单元赋值给ax=00;sp=sp+2=000A+2=000CH; pop bx;将ss:sp指向的字单元赋值给bx=00;sp=sp+2=000C+2=000EH; 见下图中的红色标记;此时栈顶已经超界了。蓝色部分是给栈分配的内存空间。注意此时栈中有数据吗?有!就是蓝色部分,只不过是中断例程保护的寄存器变量的值。-d ss:02000:0000 00 20 00 00 0B 00 65 0B-68 05 00 00 00 00 00 00 . ....e.h.......执行后:AX=0000 BX=0000 CX=0016 DX=0000 SP=000E BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=000D NV UP EI PL NZ NA PE NC使用d查看栈段内存:-d ss:02000:0000 00 20 00 00 00 00 00 00-0D 00 65 0B 68 05 00 00 . ........e.h...我们发现sp=000EH,也就是栈底向高地址发展了,栈结构占用的内存空间也变大了。5)执行代码: push ax push bx代码含义:push ax;首先sp=sp-2=000EH-2=000CH;然后将ax值压栈,此时ax=00, push bx;首先sp=sp-2=000CH-2=000AH;然后将bx值压栈,此时bx=00,执行后:AX=0000 BX=0000 CX=0016 DX=0000 SP=000A BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=000F NV UP EI PL NZ NA PE NC使用d查看栈段内存:-d ss:02000:0000 00 00 00 00 0F 00 65 0B-68 05 00 00 00 00 00 00 ......e.h.......内存中红色标记的部分就是压栈的2个字单元。6)执行代码: pop ax pop bx代码含义:pop ax;首先将ss:sp指向的内存字单元赋值给ax,也就是2000:000aH指向的字单元(00 00);然后sp=sp+2=000AH+2=000CH; pop bx;首先将ss:sp指向的内存字单元赋值给bx,也就是2000:000cH指向的字单元(00 00);然后sp=sp+2=000CH+2=000EH;执行后:AX=0000 BX=0000 CX=0016 DX=0000 SP=000E BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=0011 NV UP EI PL NZ NA PE NC使用d查看栈段内存:-d ss:02000:0000 00 00 00 00 00 00 00 00-11 00 65 0B 68 05 00 00 ..........e.h...此时sp指向了内存单元红色的地址。总结: 从CPU层面理解熟悉栈的结构,栈顶指针的变化;对push和pop两个指令执行后,CPU的执行步骤。 从编程角度要注意push和pop指令对栈中数据的顺序。 这个貌似sp有点变化,其他的寄存器死气沉沉的。呵呵我们使用栈时要小心,这个例子,栈结构的内存是没有使用的,它的栈顶随意的超界,没有事情,如果有数据的话,就破坏程序了。(3)PSP的头两个字节是CD 20,用debug加载t1.exe,查看PSP的内容。 首先要搞清楚,PSP段在什么地方?在代码段的前100H处。也就是上面的ds:0处。ds:100内存单元就是代码段的内容。你看看ds与cs值有什么联系? PSP头的作用,请看书吧。 使用d命令查看-d ds:00B55:0000 CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 68 05 8A 03 . ........O.h...0B55:0010 68 05 17 03 68 05 57 05-01 01 01 00 02 FF FF FF h...h.W.........0B55:0020 FF FF FF FF FF FF FF FF-FF FF FF FF 15 0B 4C 01 ..............L.0B55:0030 28 0A 14 00 18 00 55 0B-FF FF FF FF 00 00 00 00 (.....U.........0B55:0040 05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................0B55:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 .!...........0B55:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 .....0B55:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
(1)将下面的程序保存为t1.asm文件,将其生产可执行文件t1.exe。
assume cs:codesg codesg segment mov ax, 2000H mov ss, ax mov sp, 0 add sp, 10 pop ax pop bx push ax push bx pop ax pop bx mov ax, 4C00H int 21H codesg ends end
(2)用debug跟踪t1.exe的执行过程,写出每一步骤执行后,相关寄存器中的内容和栈顶的内容。
(3)PSP的头两个字节是CD 20,用debug加载t1.exe,查看PSP的内容。
实验结果:【1】编译、连接t1.asm汇编源程序。1)在windows XP中,打开cmd窗口,编译t1.asm程序。如下图:E:\assembly>masm t1.asmMicrosoft (R) MASM Compatibility DriverCopyright (C) Microsoft Corp 1993. All rights reserved. Invoking: ML.EXE /I. /Zm /c /Ta t1.asm Microsoft (R) Macro Assembler Version 6.15.8803 Patched for you by promethee [ECL] in the year 2001 - enjoyCopyright (C) Microsoft Corp 1981-2000. All rights reserved. Assembling: t1.asm如果没有任何错误,编译器会生成一个t1.obj的文件。如果有语法等严重的错误,编译器会给出错误信息,你可以根据错误信息,修改源代码相关的行。连接这个obj文件,并生成t1.exe文件:如下图:E:\assembly>link t1.objMicrosoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994Copyright (C) Microsoft Corp 1984-1993. All rights reserved. Run File [t1.exe]: t1.exeList File [nul.map]:Libraries [.lib]:[b]Definitions File [nul.def]:LINK : warning L4021: no stack segmentLINK : warning L4038: program has no starting address连接讲解:1)其中运行文件:我们输入我们将要生成的可执行程序(例如.exe)文件的名称。List File [nul.map]: 我们回车,没有列表文件;Libraries [.lib]: 我们回车,没有库文件Definitions File [nul.def]: 我们回车,没有交叉定义文件2)LINK : warning L4021: no stack segment 警告信息:没有栈段定义; LINK : warning L4038: program has no starting address 警告信息:程序没有起始地址。 你可以根据连接程序的提示信息来修正你的源程序;一般的警告信息,我们都忽略了。关于编译器的详细介绍,请参考相应的编译器手册。【2】用debug跟踪t1.exe的执行过程在命令提示符下键入:debug t1.exe使用r命令查看寄存器信息。-rAX=0000 BX=0000 CX=0016 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=0B65 CS=0B65 IP=0000 NV UP EI PL NZ NA PO NC0B65:0000 B80020 MOV AX,20001)CX寄存器介绍:cx=0016; 含义:cx寄存器是通用寄存器,也是计数寄存器,cx还有一个功能是在程序最初始记录程序代码的字节数;我们使用d命令查看它-d cs:00B65:0000 B8 00 20 8E D0 BC 00 00-83 C4 0A 58 5B 50 53 58 .. ........X[PSX0B65:0010 5B B8 00 4C CD 21 A9 02-00 75 05 2E FF 06 48 91 [..L.!...u....H.红色标记的是执行的机器码。注意此时的0016是16进制的,也就是22个字节,你数数!你也可以使用U命令查看汇编指令和机器码,一样。-u cs:00B65:0000 B80020 MOV AX,20000B65:0003 8ED0 MOV SS,AX0B65:0005 BC0000 MOV SP,00000B65:0008 83C40A ADD SP,+0A0B65:000B 58 POP AX0B65:000C 5B POP BX0B65:000D 50 PUSH AX0B65:000E 53 PUSH BX0B65:000F 58 POP AX0B65:0010 5B POP BX0B65:0011 B8004C MOV AX,4C000B65:0014 CD21 INT 21各寄存器状态值:CS=0B65 IP=0000 SS=0B652)执行代码 mov ax, 2000H mov ss, ax mov sp, 0代码含义:将2000H段开始的内存单元创建一个栈结构。栈顶指针ss:sp指向00H。这就意味着如果栈结构是空的,那么它的栈容量是64K。 &n@��怎么没有了那些t命令的中断例程保存的寄存器变量了?你在1FFF:0010H处,也就是它的低地址处看看有吗?执行后:AX=2000 BX=0000 CX=0016 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=0008 NV UP EI PL NZ NA PO NC3)执行代码: add sp, 10代码含义:明确说明sp指向10,也就是说我们创建的栈结构空间分配是10个字节; 使用d命令查看ss:0内存段,发现那些久违的寄存器变量数据就存储在这里,从2000:0a向低地址存储;我们不用管他们。执行后:AX=2000 BX=0000 CX=0016 DX=0000 SP=000A BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=000B NV UP EI PL NZ NA PE NC4)执行代码: pop ax pop bx代码含义:pop ax;将ss:sp指向的字单元赋值给ax=00;sp=sp+2=000A+2=000CH; pop bx;将ss:sp指向的字单元赋值给bx=00;sp=sp+2=000C+2=000EH; 见下图中的红色标记;此时栈顶已经超界了。蓝色部分是给栈分配的内存空间。注意此时栈中有数据吗?有!就是蓝色部分,只不过是中断例程保护的寄存器变量的值。-d ss:02000:0000 00 20 00 00 0B 00 65 0B-68 05 00 00 00 00 00 00 . ....e.h.......执行后:AX=0000 BX=0000 CX=0016 DX=0000 SP=000E BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=000D NV UP EI PL NZ NA PE NC使用d查看栈段内存:-d ss:02000:0000 00 20 00 00 00 00 00 00-0D 00 65 0B 68 05 00 00 . ........e.h...我们发现sp=000EH,也就是栈底向高地址发展了,栈结构占用的内存空间也变大了。5)执行代码: push ax push bx代码含义:push ax;首先sp=sp-2=000EH-2=000CH;然后将ax值压栈,此时ax=00, push bx;首先sp=sp-2=000CH-2=000AH;然后将bx值压栈,此时bx=00,执行后:AX=0000 BX=0000 CX=0016 DX=0000 SP=000A BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=000F NV UP EI PL NZ NA PE NC使用d查看栈段内存:-d ss:02000:0000 00 00 00 00 0F 00 65 0B-68 05 00 00 00 00 00 00 ......e.h.......内存中红色标记的部分就是压栈的2个字单元。6)执行代码: pop ax pop bx代码含义:pop ax;首先将ss:sp指向的内存字单元赋值给ax,也就是2000:000aH指向的字单元(00 00);然后sp=sp+2=000AH+2=000CH; pop bx;首先将ss:sp指向的内存字单元赋值给bx,也就是2000:000cH指向的字单元(00 00);然后sp=sp+2=000CH+2=000EH;执行后:AX=0000 BX=0000 CX=0016 DX=0000 SP=000E BP=0000 SI=0000 DI=0000DS=0B55 ES=0B55 SS=2000 CS=0B65 IP=0011 NV UP EI PL NZ NA PE NC使用d查看栈段内存:-d ss:02000:0000 00 00 00 00 00 00 00 00-11 00 65 0B 68 05 00 00 ..........e.h...此时sp指向了内存单元红色的地址。总结: 从CPU层面理解熟悉栈的结构,栈顶指针的变化;对push和pop两个指令执行后,CPU的执行步骤。 从编程角度要注意push和pop指令对栈中数据的顺序。 这个貌似sp有点变化,其他的寄存器死气沉沉的。呵呵我们使用栈时要小心,这个例子,栈结构的内存是没有使用的,它的栈顶随意的超界,没有事情,如果有数据的话,就破坏程序了。(3)PSP的头两个字节是CD 20,用debug加载t1.exe,查看PSP的内容。 首先要搞清楚,PSP段在什么地方?在代码段的前100H处。也就是上面的ds:0处。ds:100内存单元就是代码段的内容。你看看ds与cs值有什么联系? PSP头的作用,请看书吧。 使用d命令查看-d ds:00B55:0000 CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 68 05 8A 03 . ........O.h...0B55:0010 68 05 17 03 68 05 57 05-01 01 01 00 02 FF FF FF h...h.W.........0B55:0020 FF FF FF FF FF FF FF FF-FF FF FF FF 15 0B 4C 01 ..............L.0B55:0030 28 0A 14 00 18 00 55 0B-FF FF FF FF 00 00 00 00 (.....U.........0B55:0040 05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................0B55:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 .!...........0B55:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 .....0B55:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
相关文章推荐
- 汇编语言 王爽(第三版) 实验3 编程、编译、连接、跟踪
- 汇编语言(王爽)实验三 编程、编译、连接、跟踪
- 汇编语言:实验三 编程、编译、连接、跟踪
- 汇编语言(王爽)实验三 编程、编译、连接、跟踪
- 汇编试验三:编程、编译、连接、跟踪
- 实验3 编程、编译、链接、跟踪
- linux 下c编程1 排版,编译,连接
- 一步步学习汇编系列(6)-从一个简单的程序谈编译,连接,执行,跟踪的原理
- 实验06《数据库连接和访问编程》实验指导书V07-2初稿
- inux 下 C 编程和make的方法 (二、基础准备:编译与连接&GCC)
- LinuxSir.Org > 编程开发讨论区 —— LinuxSir.Org > 嵌入式Linux讨论区──实验田版 > 编译microwindows出错..
- 网络编程释疑之:TCP半开连接的处理
- (六)洞悉linux下的Netfilter&iptables:如何理解连接跟踪机制?【中】
- 我的第一次Windows编程实验
- 性能网络编程4--TCP连接的关闭
- 实验一:VC编程工具的灵活使用
- 使用 OpenSSL API 进行安全编程-创建基本的安全连接和非安全连接
- at91sam9263的linux编程----u-boot编译
- APUE Unix环境高级编程--ls1.c单独编译
- 使用 OpenSSL API 进行安全编程--创建基本的安全连接和非安全连接