汇编语言(王爽第三版)检测点10 第10章 答案及分析
(2017-04-11 10:44:05)
标签:
汇编王爽it教育 |
分类: 汇编语言(王爽第三版)检测点 |
检测点10.1
补全程序,实现从内存1000:0000处开始执行指令
汇编源代码check10-1.asm
assume cs:code
stack segment
stack ends
code segment
start:
code ends
end start
程序分析:
1. retf指令作用(CPU角度):从栈中弹出2个字单元,并修改CS(第二个字)和IP(第一个字);首先它弹出的是IP,其次是CS,故在压栈时,CS的值首先入栈,IP再入栈。
讲解:在汇编代码这个层次,retf指令作用是修改CS和IP的值,进而使指令从修改后的地址处开始执行。由于它所依赖的是栈中存储的内容,故在压栈过程中要搞清楚入栈的顺序、入栈的值。
2.熟悉ret指令和RETF指令执行的操作。
我们编译链接后,debug跟踪check10-1.exe
-d ss:0
0B66:0000
在stack数据区中初始化了16个0,此时它未成为栈结构。直到初始化栈的结构。
执行代码t t(二次)
AX=0B66
DS=0B56
0B67:0008
B80010
-d ss:00
0B66:0000
初始化一个栈sp=0010H(16),栈地址:ss=0b66,这里我们发现一些不应该有的数据(不理会它,它是中断的信息)
继续执行代码:
-d ss:0
0B66:0000
发现从高位开始存储10 00 00 00四个字节的数据,(体会栈是从高地址向低地址发展的,sp指针从10H减少到了0cH)
此时的CS=0B67
执行retf代码:
我们发现:CS=1000
总结:ret和RETF依赖于栈的结构存储一个程序执行点(IP或CS和IP),当执行这个代码时,可以恢复到这个程序的执行点(将栈中的数据修改IP或CS和IP,使CPU指向新的CS:IP)
检测点10.2
内存地址:
1000:
0
1000:3
1000:
6
1000:7
程序分析:
1.熟悉call指令的操作过程。call指令在执行时,首先push ip(此时ip应为6,CPU将要执行的地址),然后jmp 标号,执行标号处的代码,pop ax (弹栈写入ax,(ax)= 6),我们发现inc ax没有执行。
2.结论:(ax)= 6
检测点10.3
内存地址
1000:0
1000:3
1000:8
1000:9
程序分析:
1.关键还要明白是什么段地址和偏移地址压栈?遇到CALL指令,老样子,首先将当前的CS和IP值压栈,(cs)=1000H(由CALL的机器码得知),此时IP指向了0008H。它们统统压栈(cs先入栈,ip在栈顶)。(ax)=0
2.转移到标号S处继续执行代码,pop ax出栈写入到ax,(IP)先出栈(0008H),(ax)=0008H
3.add ax,ax
4.pop bx 将(cs)=1000H出栈,并写入bx中,(bx)=1000H
5.add ax,bx
6.(ax)=1010H;代码:inc ax没有执行
检测点 10.4
下面的程序执行后,ax中的数值为多少?
内存地址
1000:0
1000:3
1000:5
1000:6
程序分析:
1. 遇到CALL指令,老样子,(ip)(此时是5),压栈;这里我们可以不管sp是多少(我的debug是0000H),目前我们确定的就是IP的值是5(压栈的数据)。此时栈中有一个字就是0005H。(sp)=(sp)-2 =>>0000H-2=fffeH
2.由于是CALL ax,(ax)=0006H,直接转移到1000:0006处执行,将sp的值赋值给bp。
3.由于bp默认隶属于ss段寄存器,故[bp]指向ss段的物理内存,也就是栈结构的空间,此时栈中就一个字0005H,那么(ss:[bp])=0005H(读取ss栈中的内容)。
4.add
ax,[bp]
5.结果:ax的值是000BH。inc ax指令依然没有执行。
检测点10.5
(1)下面的程序执行后,ax中的数值为多少?(ax)=3
assume cs:code
stack segment
dw 8 dup (0) stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ds,ax
mov ax,0
call word ptr ds:[0eh]
inc ax
inc ax
inc ax
mov ax,4c00h
int 21h code ends
end start
程序分析:
1. 在栈段初始化并定义了8个字,16个字节的空间。是dw指令。
2. 初始化栈,将栈段地址也赋值给了ds;(ss)=(ds),数据段和栈段是同一个内存空间段。
3. 遇到了call,老样子,将(cs)压栈(这个值肯定是call指令后面的那个指令的cs和ip我们可以不关心它,依据你的debug程序)、将(ip)压栈,此时的ip值应该是第一个inc ax的偏移地址。然后jmp到ds:[0eh]内存单元内容作为偏移地址的点执行代码。由于ds和ss都是同一个段,call的是一个字单元,故ds:[0eh]内存单元是指向的一个字(ds:[0eh]~ds:[0fh]内存单元),此单元正好是栈空间栈顶的存储单元,存储着最后压入的ip的值,这个值就是代码inc ax的偏移地址,那么开始执行inc ax
4.执行3次inc ax后, (ax)=3。
5.总结:这个考察了我们对于CALL 内存空间这个指令的熟悉程度,也考察了栈段和数据段在同一段地址下,怎样读出栈空间单元内容。