汇编网首页登录博客注册
unixandlinux的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
最新评论
最新留言
好友圈
友情链接

[2023-06-20 17:20] 第9章 检测点 9.3

检测点 9.3

补全程序,利用 loop 指令实现在内存 2000H 段中查找第一个值为 0 的字节;找到后,将它的偏移地址存储在 DX 寄存器中。

与检测点 9.2 一样,本题存在三个问题:
1. 当指定的 2000h 段中不存在值为 0 的字节时,程序将陷入 s 标号至“loop s”指令之间的死循环。
2. 程序在两种情况下都应该转移至 ok 标号处,这两种情况是:
(1) 当查找到首个字节值为 0 时。
(2) 当 2000h 段中不存在值为 0 的字节,并且已经查找完段中所有字节后(即 (bx)=FFFFh)。
另外,必需在程序未尾,能够通过一定的手段判断出“程序转移至 ok 标号处”这一结果,是基于这两种情况的哪一种。
3. 原题中给出允许添加的指令数量是 1 条,而 1 条指令如何能同时解决上述第 1、2 两个问题。

通常,上述第 3 个问题是无法解决的:无法仅用 1 条指令同时实现肯定“不陷入死循环”和“在上述两种情况下都能转移至 ok 标号处”。

下面列出几种实现本检测点功能的方法:

方法 1(存在可能陷入死循环的有缺陷方法 ——  hk9_3er.asm):
说明:仅在题目要求补全代码处添加一条“inc cx”指令,这仅适合在“2000h 段中必定存在字节值 0”条件下执行;但本程序添加了“loop u”循环,以对 2000h 段字节的初始化进行人为操控 —— 将 2000h 段字节初始化为非 0 值,从而测试本程序运行后是否会陷入“loop s”死循环。

assume cs:code

code segment

start:        mov ax,2000h
        mov ds,ax
        mov bx,0

        ; 初始化 2000h 段内存单元的初值
        mov cx,0FFFFh
u:        mov byte ptr [bx],0FFh
        inc bx
        loop u
        ; loop u 循环无法将指定的数值数据传送到 ds:ffff 内存单元中;因为 16 位的 CX 寄存器只能进行 FFFEh 次的 loop u 循环(从 FFFFh 到 0001h)
        ; 这可以通过 Debug 运行本程序时,执行下面一行代码前,用 R 命令查看 BX 寄存器存储的值来证明
        mov byte ptr [bx],0FFh

        mov bx,0FFFDh  ; 为了缩短 s 标号至“loop s”指令之间的循环而设置,以证明该循环为死循环;否则,应该将 0 值赋给 bx,以便从 2000h 段的 [0] 开始查看,而不是如此行代码所示的,从 2000h 段 [0FFFDh] 开始查看。
s:        mov cl,[bx]
        mov ch,0
        inc cx
        inc bx
        loop s

ok:        dec bx  ; dec 指令的功能和 inc 相反,“dec bx”进行的操作为:(bx)=(bx)-1
        mov dx,bx

        mov ax,4c00h
        int 21h

code ends

end start
        
方法 2(chk9_3wr.asm)
说明:仅在题目要求补全代码处添加一条指令,这适合在“2000h 段中必定存在字节值为 0”条件下执行。
注意,默认情况下在 2000h 段中存在字节的值为 0。

assume cs:code

code segment

start:        mov ax,2000h
        mov ds,ax
        mov bx,0

s:        mov cl,[bx]
        mov ch,0
        inc cx
        inc bx
        loop s

ok:        dec bx  ; dec 指令的功能和 inc 相反,“dec bx”进行的操作为:(bx)=(bx)-1
        mov dx,bx

        mov ax,4c00h
        int 21h

code ends

end start

方法 3(chk9_3cr.asm):
在题目要求补全代码处添加以下指令:
mov ax,cx
mov cx,bx
inc cx
jcxz ok
mov cx,ax
inc cx
说明:
1. 修正了“方法 1(chk9_3er.asm)”程序运行在“2000h 段不存在值为 0 的字节”时,将陷入“loop s”死循环的缺陷。
2. 添加了“loop u”循环,以对 2000h 段字节内存单元进行初始化操作 —— 将 2000h 段字节初始化为非 0 值,从而测试本程序运行后是否能够成功修正“陷入‘loop s’死循环”的缺陷。
3. 最后,当程序跳至 ok 标号处执行完其下面的“mov dx,bx”指令后,即可进行以下判断:
(1) 如果 (bx)=FFFFh,则程序因为查看到 2000h 段的最后一个字节后而无条件转移到 ok 标号,并未对该字节单元存储的值执行“是否为 0”的判别操作,因为不会执行“loop s”指令以判别其“是否为 0”;这时,可通过 AX 寄存器存储的值来确认这一判别:如果 (ax)=0,则说明 2000:[FFFF] 字节单元的值为 0,相反,若 (ax)≠0,则说明 2000:[FFFF] 字节单元的值不为 0,并且 2000h 段中不存在值为 0 的字节单元 —— 如果 2000h 段中存在值为 0 的字节,就根本不会执行到查看 2000:[FFFF] 字节而早就跳至 ok 标号处了。
(2) 如果 (bx)≠FFFFh,则说明 2000:[bx] 字节的值为 0,即值为 0 的字节的偏移地址已被存入 DX 寄存器。

assume cs:code

code segment

start:        mov ax,2000h
        mov ds,ax
        mov bx,0

        ; 初始化 2000h 段内存单元的初值
        mov cx,0FFFFh
u:        mov byte ptr [bx],0FFh
        inc bx
        loop u
        ; loop u 循环无法将指定的数值数据传送到 ds:ffff 内存单元中;因为 16 位的 CX 寄存器只能进行 FFFEh 次的 loop u 循环(从 FFFFh 到 0001h)
        ; 这可以通过 Debug 运行本程序时,执行下面一行代码前,用 R 命令查看 BX 寄存器存储的值来证明
        mov byte ptr [bx],0FFh

        mov bx,0FFFDh  ; 为了缩短 s 标号至“loop s”指令之间的循环而设置,以证明该循环为死循环;否则,应该将 0 值赋给 bx,以便从 2000h 段的 [0] 开始查看,而不是如此行代码所示的,从 2000h 段 [0FFFDh] 开始查看。
s:        mov cl,[bx]
        mov ch,0

        mov ax,cx
        mov cx,bx
        inc cx
        jcxz ok
        mov cx,ax
        inc cx

        inc bx
        loop s

ok:        dec bx  ; dec 指令的功能和 inc 相反,“dec bx”进行的操作为:(bx)=(bx)-1
        mov dx,bx

        mov ax,4c00h
        int 21h

code ends

end start

方法 4(chk9_3_1):
说明:
1. 在题目要求补全代码处添加以下指令:
mov ax,cx
mov cx,bx
inc cx
jcxz ok
mov cx,ax
inc cx
2. 本程序不对 2000h 段字节内存单元进行初始化操作。
3. 最后,当程序跳至 ok 标号处执行完其下面的“mov dx,bx”指令后,即可进行以下判断:
(1) 如果 (bx)=FFFFh,则程序因为查看到 2000h 段的最后一个字节后而无条件转移到 ok 标号,并未对该字节单元存储的值执行“是否为 0”的判别操作,因为不会执行“loop s”指令以判别其“是否为 0”;这时,可通过 AX 寄存器存储的值来确认这一判别:如果 (ax)=0,则说明 2000:[FFFF] 字节单元的值为 0,相反,若 (ax)≠0,则说明 2000:[FFFF] 字节单元的值不为 0,并且 2000h 段中不存在值为 0 的字节单元 —— 如果 2000h 段中存在值为 0 的字节,就根本不会执行到查看 2000:[FFFF] 字节而早就跳至 ok 标号处了。
(2) 如果 (bx)≠FFFFh,则说明 2000:[bx] 字节的值为 0,即值为 0 的字节的偏移地址已被存入 DX 寄存器。

assume cs:code

code segment

start:        mov ax,2000h
        mov ds,ax
        mov bx,0

s:        mov cl,[bx]
        mov ch,0

        mov ax,cx
        mov cx,bx
        inc cx
        jcxz ok
        mov cx,ax
        inc cx

        inc bx
        loop s

ok:        dec bx  ; dec 指令的功能和 inc 相反,“dec bx”进行的操作为:(bx)=(bx)-1
        mov dx,bx

        mov ax,4c00h
        int 21h

code ends

end start

方法 5(chk9_3_2.asm)
说明:
1. 在题目要求补全代码处添加以下指令:
mov ax,cx
mov cx,bx
inc cx
jcxz ok
mov cx,ax
inc cx
2. 添加了“loop u”循环,以对 2000h 段字节内存单元进行初始化操作 —— 将 2000h 段最后一个字节 [FFFFh] 初始化为 0 值,而其他所有字节则初始化为非 0 值,从而测试本程序运行后是否能够成功修正“陷入‘loop s’死循环”的缺陷。
3. 最后,当程序跳至 ok 标号处执行完其下面的“mov dx,bx”指令后,即可进行以下判断:
(1) 如果 (bx)=FFFFh,则程序因为查看到 2000h 段的最后一个字节后而无条件转移到 ok 标号,并未对该字节单元存储的值执行“是否为 0”的判别操作,因为不会执行“loop s”指令以判别其“是否为 0”;这时,可通过 AX 寄存器存储的值来确认这一判别:如果 (ax)=0,则说明 2000:[FFFF] 字节单元的值为 0,相反,若 (ax)≠0,则说明 2000:[FFFF] 字节单元的值不为 0,并且 2000h 段中不存在值为 0 的字节单元 —— 如果 2000h 段中存在值为 0 的字节,就根本不会执行到查看 2000:[FFFF] 字节而早就跳至 ok 标号处了。
(2) 如果 (bx)≠FFFFh,则说明 2000:[bx] 字节的值为 0,即值为 0 的字节的偏移地址已被存入 DX 寄存器。

assume cs:code

code segment

start:        mov ax,2000h
        mov ds,ax
        mov bx,0

        ; 初始化 2000h 段内存单元的初值
        mov cx,0FFFFh
u:        mov byte ptr [bx],0FFh
        inc bx
        loop u
        ; loop u 循环无法将指定的数值数据传送到 ds:ffff 内存单元中;因为 16 位的 CX 寄存器只能进行 FFFEh 次的 loop u 循环(从 FFFFh 到 0001h)
        ; 这可以通过 Debug 运行本程序时,执行下面一行代码前,用 R 命令查看 BX 寄存器存储的值来证明
        mov byte ptr [bx],0  ; 将 2000:[FFFF] 字节初始化为 0,而 2000h 段中其他的字节则初始化为 FFh。

        mov bx,0FFFDh  ; 为了缩短 s 标号至“loop s”指令之间的循环而设置,以证明该循环为死循环;否则,应该将 0 值赋给 bx,以便从 2000h 段的 [0] 开始查看,而不是如此行代码所示的,从 2000h 段 [0FFFDh] 开始查看。
s:        mov cl,[bx]
        mov ch,0

        mov ax,cx
        mov cx,bx
        inc cx
        jcxz ok
        mov cx,ax
        inc cx

        inc bx
        loop s

ok:        dec bx  ; dec 指令的功能和 inc 相反,“dec bx”进行的操作为:(bx)=(bx)-1
        mov dx,bx

        mov ax,4c00h
        int 21h

code ends

end start
评论次数(0)  |  浏览次数(120)  |  类型(汇编作业) |  收藏此文  | 
 
 请输入验证码  (提示:点击验证码输入框,以获取验证码