1.若要使程序中的jmp指令执行后,CS:IP指向程序的第一条指令,
在datasg段中应该定义哪些数据?
================CODE=================================
assume cs:codesg
datasg segment
......
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov bx,0
jmp word ptr [bx+1]
codesg ends
end start
=======================================================
分析:
若jmp word ptr [bx+1]执行后,CS:IP指向程序的第一条指令,
(1)确定IP:那么IP这个偏移量应为零。即内存内容为:
DS:0000~0002 ?? 00 00 (??处为随便占一字节的内容)
(2)确定CS:因为是属于段内转移,所以CS不用指定。
(3)datasg处定义为:
db 0,0,0
或
db 0
dw 0
当然,如果将jmp word ptr [bx+1]段内跳转指令改为
jmp dword ptr [bx+1],段间跳转指令又怎么办呢?
分析:
若jmp dword ptr [bx+1]执行后,CS:IP指向程序的第一条指令,
(1)确定IP:那么IP这个偏移量应为零。即内存内容为:
DS:0000~0002 ?? 00 00
(2)确定CS:因为是属于段间转移,所以(CS)=(bx+1+2),即内存内容为:
DS:0000~0005 ?? 00 00 CS(L) CS(H)
那么如何把CS写到datasg中相应位置呢?用codesg或seg codesg。
如下:
================CODE=================================
assume cs:codesg,ds:datasg
datasg segment
db 0
dw 0,seg codesg
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov bx,0
jmp dword ptr [bx+1]
mov ax,4c00H
int 21H
codesg ends
end start
======================================================
2.使jmp指令执行后,CS:IP指向程序的第一条指令。
======================CODE================================
assume cs:codesg,ds:datasg
datasg segment
dd 12345678H
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov bx,0
mov [bx],bx
mov [bx+2],cs
jmp dword ptr ds:[0]
mov ax,4c00H
int 21H
codesg ends
end start
======================================================
分析:
若jmp dword ptr ds:[0]执行后,CS:IP指向程序的第一条指令,
(1)确定IP:那么IP这个偏移量应为零。即DS处原内容为:
DS:0000~0001 78 56
应改为:
DS:0000~0001 00 00
这由"mov [bx],bx"来实现,
当然也可以用"mov [bx],word ptr 0"来实现。
(2)确定CS:因为是属于段间转移,所以(CS)=(DS:[bx+2]),即内存内容为:
DS:0000~0004 78 56 34 12
DS:0000~0004 00 00 CS(L) CS(H)
这里由"mov [bx+2],cs"来实现;
也可由"mov word ptr [bx+2],codesg"来实现。
"mov [bx+2],codesg"和"mov [bx+2],word ptr codesg"均会出现警告性错误提示:
1702.ASM(13): warning A4031: Operand types must match
49004 + 431492 Bytes symbol space free
1 Warning Errors
0 Severe Errors
但还能编译够链接通过得到可执行文件,进行调试,也没问题。
3.在内存2000H段中查找第一个值为0的byte,
找到后,将它的偏移地址存储在dx中。
=============================CODE=========================
assume cs:code
code segment
start:
mov ax,2000h
mov ds,ax
mov bx,0
s:
mov cl,[bx]
mov ch,0
inc bx
loop s
ok:
dec bx
mov dx,bx
mov ax,4c00h
int 21h
code ends
end start
======================================================
如果程序是这样,那么当遇到第一个0的时候,
程序运行到loop处CX已经为零。
程序执行loop,首先要CX-1 = 0000-1 = FFFF,使得CX = FFFF,
然后判断CX,不为零,程序会继续执行,而不跳出loop。
经过debug还可以发现,上面的程序是对"遇到第一个1的时候"的解决方案,
而不是"遇到第一个0的时候的解决方案"。
所以要解决这种特殊问题,那我们在遇到loop进行CX-1之前,
给CX其加上1,就可以了。
改后程序如下:
=============================CODE=========================
assume cs:code
code segment
start:
mov ax,2000h
mov ds,ax
mov bx,0
s:
mov ch,0
mov cl,[bx]
inc cx
inc bx
loop s
ok:
dec bx
mov dx,bx
mov ax,4c00h
int 21h
code ends
end start
======================================================
4.(实验8)下面程序能否正确返回:
=========================CODE=============================
assume cs:codesg
codesg segment
mov ax,4c00H
int 21H
start:
mov ax,0
s:
nop
nop
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
s0:
jmp short s
s1:
mov ax,0
int 21H
mov ax,0
s2:
jmp short s1
nop
codesg ends
end start
IF 0
***************************************************************************
源程序 CS:[XXXX] 指令所 对应机器码 Debug下u命令
地址 占字节数 (按所占内存位置) 对应指令
assume cs:codesg
codesg segment
mov ax,4c00H [0000] [3] B8 00 0C MOV AX,4C00
int 21H [0003] [2] CD 21 INT 21
start:
mov ax,0 [0005] [3] B8 00 00 MOV AX,0000
s:
nop [0008] [1] 90 NOP
nop [0009] [1] 90 NOP
mov di,offset s [000A] [3] BF 08 00 MOV DI,0008
mov si,offset s2 [000D] [3] BE 20 20 MOV SI,0020
mov ax,cs:[si] [0010] [3] 2E CS:
8B 04 MOV AX,[SI]
mov cs:[di],ax [0013] [3] 2E CS:
89 05 MOV [DI],AX
s0:
jmp short s [0016] [2] EB F0 JMP 0008
s1:
mov ax,0 [0018] [3] B8 00 00 MOV AX,0000
int 21H [001B] [2] CD 21 INT 21
mov ax,0 [001D] [3] B8 00 00 MOV AX,0000
s2:
jmp short s1 [0020] [2] EB F6 JMP 0018
nop [0022] [1] 90 NOP
codesg ends
end start
*****************************************************************************
装载的时候,IP=5。
即装载程序后,CS:IP为CS:0005,从start处的mov ax,0开始执行指令。
mov ax,0 (AX)=0
s: s标号
nop 占位1字节;
nop 占位1字节;
mov di,offset s (DI) = 0008H,因为"offset s"是s处相对于CS:0000H处的偏移值;
mov si,offset s2 (SI) = 0020H,因为"offset s2"是s2处相对于CS:0000H处的偏移值;
mov ax,cs:[si] (AX) = (CS:0020H),也就是AX的内容为CS:0020H处起始的两个字节的内容;
而CS:0020H处开始的两个字节的内容为jmp short s1,
那么我们来看看jmp short s1的实质是什么:
jmp short "标号"的的功能是修改IP,使得(IP)=(IP)+位移量(8位)
这种不带目的地址的指令转移指令,是靠位移量对IP修改进行的。
位移量 = ”标号“处的地址 - jmp指令后的第一个字节的地址,即:
位移量 = 18H - 22H = F6(用8位来表示),
这是个负数,用补码表示为:11110110,表示位移是向上移动。
根据"负数的补码取反加1得其绝对值",
这个负数的绝对值为: 00001010
也就是16进制的A,十进制的10。
也就是说jmp short s1的实质是要使得(IP)=(IP-AH)
这jmp short s1被编译器编译后,就已算出,
所以编译后,s1已经被转为偏移值了。
我们可看到"jmp short s1"对应的机器码为:EB F6
mov cs:[di],ax 把(AX)也就是(CS:0020H)的内容(EB F6)写到CS:[DI]处,
也就是s标号处的两个nop字节被改为了EB F6。
s0: s0标号
jmp short s 对应机器码为EB F0,
F0十进制绝对值为16,即为10H,也就是改变IP,使得(IP)=(IP) - 10H,
当CPU读取EBF0并将其送入指令缓冲器后,IP为0018H,
而执行完EBF0后,IP = 0018H - 10H = 0008H
即跳到S标号地址处。
EBF6(原nop nop) 此时这里已经被上面执行过的指令改写为EBF6,
而EBF6的指令使得(IP)=(IP-AH)
CPU读入EBF6并将其送入指令缓冲器后,IP为000AH
而执行完EBF0后,IP = 000AH - 000AH = 0000H
mov ax,4c00H
int 21H 这两条指令能使程序正确返回。
*****************************************************************************************
ENDIF
5.下面指令执行到mov ax,4c00H之前时,AX值为多少?
*******************************************************
assume cs:codesg
codesg segment
start:
mov ax,2
mov cx,3
s:
add ax,2
s1: loop s
mov di,offset s1
mov si,offset s3
mov ax,cs:[di]
mov cs:[si],ax
mov ax,1
mov cx,3
s2:
add ax,2
s3:
nop
nop
mov ax,4c00H
int 21H
codesg ends
end start
*******************************************************
分析:
s: add ax,2
s1:
loop s
mov di,offset s1
mov si,offset s3
mov ax,cs:[di]
mov cs:[si],ax 此4条指令是将标号为s1处的指令(loop s)复制到s3处。
loop s编译后占两字节。
loop s编译后,实际上为是一种带CX值判断的jmp short 标号指令。
也可以说是与"jcxz 标号"指令恰好相反的指令。
所以是属于带偏移值的跳转指令,我们来看跳转的是多少。
loop s 本身占2,s标号处的add ax,2占3,
如果s处地址为CS:000YH的话,
那么loop s指令后的第一个字节地址为:CS:000XH
其中:X = Y+3+2
所以jmp short的偏移值为:Y - X = Y-y-3-2 = -5。
所以,上面4条指令所复制的机器码实际上的功能是使得:
(1)判断CX-1是否等于0;
(2)如果CX-1为零,那么对(IP)不做修改。
(3)如果CX-1不为零,那么(IP)=(IP)-5 。
mov ax,1 重新赋值ax。
mov cx,3
s2:
add ax,2
s3:
nop
nop 实际上这两个nop被改为:
(1)判断CX-1是否等于0;
(2)如果CX-1为零,那么对(IP)不做修改。
(3)如果CX-1不为零,那么(IP)=(IP)-5 。
所以相当于loop s2了。
所以,ax到这里为7。
- [taotling] 小朋友问这道题怎么按我的抄完后尽是报除法溢出来着。 忽略掉之前的吧,下面的是正确姿势。 这个 04/04 17:47
- [rexic] 回复[ taotling 发表于 2015-09-05 22:41 ] 此处程序应该在 11/14 21:34
- [taotling] assume cs:code, ss:stack, ds:data data segment 09/13 13:53
- [taotling] 更正: 忽略后来在2008-04-01发的评论: [taotling发表于2008-04-01 09/05 23:17
- [taotling] 实验五(5)可简化为: ------------------------------------- 09/05 22:41
- [taotling] 纠正,将 mov cx,17h 改为 mov cx,18h ------------ 原 09/05 13:58
- [fpamc] 欢迎前辈。 10/18 08:49
- [fpamc] 谢谢作者。 很感谢分享自己的经验。 原本我会很担心时间问题,因为我是基础差,遇到不明白的很多,都 03/17 07:50
- [tomato] 博主总结的很到位。 03/16 23:10
- [killkk] 多谢、学习。。 08/28 12:41
- [zouhehui] 你好,有个问题想请教你,你的实验10.4的那种图是怎么做出来的,谢谢! 11/30 22:57
- [fangyugirl] 你好,请问你有MSN吗?我想加你,让你给我讲讲16的实验的问题,我看过其他人的,方法就那么几种,我也 05/18 11:03
- [w0922] 你好 !能不能到我的博客看哈 有个问题想请教哈你··· 就是我博客实验十分析的那个问题 04/18 15:18
- [rsice] taoling你好,现在有事想你求救,我在第10章实验10的第3个子程序始终出错,我想破脑壳也想不出 04/08 12:14
- [游客] 博主如果想继续学习的话,可以看看C语言,将数据结构中的算法用C语言编一遍,然后学习学习OS(操作系统 03/30 20:03