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

我的博客

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

[2013-05-16 02:27] 第九章          附:实验题

实验题地址:http://www.asmedu.net/bbs/pasteinfo.jsp?part=1&level=book&kind=1010&qkSg=2&qID=70755&readSg=1



■        [mov ax,offset s]取得标号的偏移地址,ax = 标号 s 所在的那一条指令偏移地址
■        [jmp short s][jmp short 标号](转到标号处执行指令)段内短转移        功能:(ip)=(ip)+8位位移
|        (对IP修改范围为-128~127)也就是说它向前转移时可以最多越过128个字节,向后转移可以最多越过127个
|        字节. "short" 符号说明指令进行的是短转移,指令中的"标号"指明了指令要转移的目的地,转移指令结束
|        后,CS:IP应该指向标号处的指令        8位位移=标号处的地址 - jmp 指令后的第一个字节的地址
|■        [jmp near ptr 标号]:段内近转移        -32768~32767        功能:(ip)=(ip)+16位位移
|■        [jmp far ptr 标号]:段间转移,又称远转移        far ptr 指明了指令用标号的段地址和偏移地址修改cs和ip
|        功能:(cs)=标号所在段的段地址        (ip)=标号在段中的偏移地址
|■        [jmp ax]                IP = AX  ,将 ax 的值赋值给 IP 
|■        [jmp word ptr 内存单元地址(段内转移)]功能:从内存单元地址处开始存着一个字,是转移目的偏移地址
|■        [jmp dwrod ptr 内存单元地址(段间转移)]
|        功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的地址,低地址是偏移地址
■        [jcxz 标号]        ■(如果(cx)=0,转移到标号处执行),当(cx)≠0时,什么也不做(程序向下执行)
■        [loop 标号]        ((cx)=(cx)-1,如果(cx)≠0,转移到标号处执行)
■■        [jmp 2000:0100]        转移指令是在debug中使用的汇编指令,汇编编译器不认识,源程序中使用会报错
■■■        80×20彩色字符模式显示缓冲区 □-B8000H~BFFFFH-□ 每行80个字符(包括颜色)占160个字节
转移指令的原理:__________        可以修改IP,或同时修改CS和IP的指令统称为转移指令.
                转移指令就是可以控制CPU执行内存中某处代码的指令.
                8086CPU的转移行为有以下几类:
                (1)只能修改IP时,称为段内转移,比如:        jmp ax
                (2)同时修改CS和IP时,称为段间转移,比如:        jmp 1000:0
                由于转移指令对IP的修改范围不同,段内转移又分为:□短转移和近转移
                (1)短转移IP的修改范围为-128-127
                (2)近转移IP的修改范围为-32768-32767
                8086CPU的转移指令分为以下几类:
                (1)无条件转移指令(如:jmp)
                (2)条件转移指令
                (3)循环指令(如:loop)
                (4)过程
                (5)中断
                这些转移指令的转移前提条件可能不同,但基本原理相同
                sp

                
操作符offset:__________         由编译器处理的符号                功能:取得标号的偏移地址
                assume cs:codesg
                codesg segment
                start:        mov ax,offset start                ;相当于mov ax,0
                s:      mov ax,offset s                        ;相当于mov ax,3
                codesg ends
                end start
                以上程序中,offset操作符取得了标号start和s的偏移地址0和3,所以指令:mov ax,offset start
                相当于指令mov ax,0,因为start是代码段中的标号,标记的指令是代码段中第一条指令,偏移为0
                mov ax,offset s相当于指令mov ax,3因为s是代码段中的标号,标记的指令是代码段中第二条指
                令,第一条指令长度为3个字节,则s的偏移地址为3
                __________添写两条指令,使该程序在运行中将s处的一条指令复制到s0处
                assume cs:codesg                                
                codesg segment
                s:        mov ax,bx        ;要复制的数据mov ax,bx长度为两个字节,即1个字
                        mov si,offset s                ;s所处内存单元        cs:offset s
                        mov di,offset s0        ;s0所处内存单元        cs:offset s0
                ;段地址已知在CS中                偏移地址offset s 和 offset s0 已经送入 si 和 di 中
                        (mov ax,cs:[si])        ;将cs:offset s 处数据送入ax
                        (mov cs;[di],ax)        ;将ax中的数据送入 cs:offset s0
                        s0:        nop                ;nop 的机器码占一个字节
                                nop
                codesg ends                                
                end s

jmp指令:__________        jmp为无条件转移指令,可以只修改IP,也可以同时修改CS和IP
                jmp指令要给出两种信息:
                (1)转移的目的地址                (2)转移的距离(段间转移\段内短转移\段内近转移)
                不同的给出目的地址的方法和不同的转移位置 对应有不同格式的jmp指令
                
依据位移进行转移的jmp指令:__________        [jmp short s][jmp 段内短转移 标号](转到标号处指令指令)
                段内短转移(对IP修改范围为-128~127)也就是说
                它向前转移时可最多越过128个字节,向后转移可最多越过127个字节."short"符号说明指令进行
                的是短转移,指令中的"标号"指明指令要转移的目的地,指令结束后,CS:IP应该指向标号处的指令
                如:        assume cs:codesg
                        codesg segment
                        start:        mov ax,0
                                jmp short s        ;越过add ax,1         IP指向标号s:处的inc ax
                                add ax,1
                        s:        inc ax
                        codesg ends
                                end start        ;输出结果 ax=1
                [jmp short s]机器码[EB03]不包含转移的目的地址
        ■■        CPU在执行jmp指令的时候并不需要转移目的地址,而包含的是转移的位移,位移根据汇编指令中的
                "标号"计算出来的:        (ip)=(ip)+8位位移
                        偏移地址        机器码                                 汇编指令
                        0000                40        编译程序根据此两点的|①        s: inc ax
                        0001                EB03        距离算出位移量:6-3=3|        jmp s0
                        0003                BB0300                             ②        mov bx,3
                        0006                43        编译程序根据此两点的|②        s0: inc bx
                        0007                EBF7        距离算出位移量0-9=-9|        jmp s
                        0009                90        (补码表示为F7)             ①nop
        □□□        -9 的绝对值 9 的补码 0000 1001 取反加1 11110110+1=11110111B(为-9的补码)=247=F7H
                (1)8位位移=标号处的地址 - jmp 指令后的第一个字节的地址
                (2)short 指明此处的位移为8位位移
                (3)8位位移的范围为-128~127,用补码表示0-01111111(127) 10000000-11111111(-128,-1)
                (4)8位位移由编译程序在编译时算出
        ■■■        段内近转移:[jmp near ptr 标号] 功能为:(ip)=(ip)+16位位移
                (1)16位位移=标号处的地址 - jmp 指令后的第一个字节的地址
                (2)near ptr 指明此处的位移为8位位移
                (3)16位位移的范围为-32768~32767,用补码表示0-[16个1](1000000000000000为-32768)
                (4)16位位移由编译程序在编译时算出
转移的目的地址在指令中的jmp指令:________        对于当前的IP转移位移的机器指令中并没有转移的目的地址
                [jmp far ptr]        功能:(cs)=标号所在段的段地址        (ip)=标号在段中的偏移地址
                assume cs:codesg
                codesg segment
                start:        mov ax,0                ;长度3
                        mov bx,0                ;3
                        jmp far ptr s                ;EA0B01BD0B 高地址BD0B是转移的段地址,低位0B01是偏移
                        db 256 dup (0)                ;7开头
                s:        add ax,1
                        inc ax
                codesg ends
                end start

转移地址在寄存器中的jmp指令:__________        [jmp 16位reg]        功能:(ip)=(16位reg)"Register寄存器"
                [jmp ax]                IP = AX  ,将 ax 的值赋值给 IP 

转移地址在内存中的jmp指令:__________        [jmp word ptr 内存单元地址(段内转移)]
                功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址
        □        内存单元地址可用寻址方式的任意格式给出:
        |        mov ax,0123H        mov ds:[0],ax        jmp word ptr ds:[0]        执行后(ip)=0123H
        |        mov ax,0123H        mov [bx],ax        jmp wort ptr [bx]        执行后(ip)=0123H
        □        [jmp dwrod ptr 内存单元地址(段间转移)]
        |        功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的地址,低地址是偏移地址
        |        (cs)=(内存单元地址+2)        (ip)=(内存单元地址)
        |        mov ax,0123H    mov ds:[0],ax    mov wort ptr ds:[2],0    jmp dword ptr ds:[0]
        |        执行后,(cs)=0 (ip)=0123H        cs:ip指向 0000:0123
        |        mov ax,0123H    mov [bx],ax    mov wort ptr [bx+2],0    jmp dword ptr [bx]
        |        执行后,(cs)=0 (ip)=0123H        cs:ip指向 0000:0123
____________________________________________________________________________________________________
(1)要使jmp指令执行后,cs:ip指向程序第一条指令,则[bx+1]处的数据必须是0
;jmp word ptr [bx+1] 修改 ip = ([bx+1]处的数据)        程序入口的地址是cs:0
;assume cs:code
;data segment
;                db '0'
;data ends
;code segment
;start:        mov ax,data
;                mov ds,ax
;                mov bx,0
;                jmp word ptr [bx+1]
;code ends
;end start
_______________________________________________
(2)补全,使jmp指令后 cs:ip 指向第一条指令
;assume cs:code
;data segment
;                dd 12345678H
;data ends
;code segment
;start:        mov ax,data
;                mov ds,ax
;                mov bx,0
;                mov [bx],bx                ;mov [bx],?                dd定义的数据占4个单元 低位地址存放偏

移地址  结果使[bx]为0
;                mov [bx+2],cs                ;mov [bx+2],?                高位单元存放段地址                结果

使段地址指向程序所在的段
;                jmp dword ptr ds:[0]
;code ends
;end start
_______________________________________________
(3)用debug 查看内存 2000:1000 BE 00 06 00 00 00 .. ..     cs=?     ip=?
;mov ax,2000H
;mov es,ax
;jmp dwrod ptr es:[1000H]
;cs=6H        ip=BEH
assume cs:code
code segment
mov ax,2000H
mov es,ax
jmp dword ptr es:[1000H]
code ends
end
____________________________________________________________________________________________________

jcxz指令:__________        有条件转移指令,所有的有条件转移指令都是短转移,对应的机器码中包含转移的位移
        ■        指令格式:        [jcxz 标号]        ■(如果(cx)=0,转移到标号处执行)
                操作:        当(cx)=0时,(ip)=(ip)+8位位移
                8位位移=标号处的地址-jcxz指令后的第一个字节的地址
                8位位移的范围为-128~127,用补码表示
                8位位移由编译程序在编译时算出
        ■        当(cx)≠0时,什么也不做(程序向下执行)        "jcxz 标号"的功能相当于:
                C语言描述[if ((cx)==0)jmp short 标号]
____________________________________________________________________________________________________
补全编程,利用jcxz指令实现在内存2000H段中查找第一个值为0的字节,找到后将它的偏移地址存储在dx中?
assume cs:code
code segment
start:        mov ax,2000h
        mov ds,ax
        mov bx,0
s:        (mov cl,0)        ;要用8位寄存器,因为如果是字型的单元数据 00 01 的话 cx≠0 跳转不了
        (mov ch,[bx])        ;或写成 mov ch,0        mov cl,[bx]
        (inc bx)        ;本句与 jcxz ok 调转顺序没问题
        (jcxz ok)
        jmp short s
ok:        mov dx,bx
        mov ax,4c00h
        int 21h
code ends
end start
____________________________________________________________________________________________________

loop指令:__________        循环指令,所有循环指令都是短转移,机器码中包含转移的位移,IP范围:-128~127
        ■        指令格式:        loop 标号        ((cx)=(cx)-1,如果(cx)≠0,转移到标号处执行)
                操作:(1)(cx)=(cx)-1        (2)如果(cx)≠0,(ip)=(ip)+8位位移
                8位位移=标号处的地址-jcxz指令后的第一个字节的地址
                8位位移的范围为-128~127,用补码表示
                8位位移由编译程序在编译时算出
        ■        当(cx)=0时,什么也不做(程序向下执行),"loop 标号"功能相当于:
                C语言描述[(cx)--][if ((cx)≠0)jmp short 标号]
____________________________________________________________________________________________________
补全,用loop指令查找内存2000H段中第一个值为0的字节,找到后存储在dx中
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
____________________________________________________________________________________________________

根据位移进行转移的意义:__________
                对应机器码中不包含转移的目的地址,包含的是目的地址的位移                        修改IP
                jmp short 标号        jmp near ptr 标号        jcxz 标号        loop 标号
                这种设计方便程序段在内存中的浮动装配:
                mov cx,6        b9 06 00
                mov ax,10h        b8 10 00
                s: add ax,ax        01 c0
                loop s                 e2 fc
                这段程序在内存中的不同位置都可以正确执行,因为loop s在执行时只涉及s的位移(-4,前移)
                如果loop s的机器码中包含的是s的地址,如果s处的指令不在目的地址处,程序的执行就会出错

编译器对转移位移超界的检测:__________        转移范围超界,编译时编译器将报错
                编译错误:
                assume cs:code
                code segment
                start:        jmp shor s
                        db 128 dup (0)
                s:        mov ax,0ffffh
                code ends
                end start
                jmp short s的转移范围是-128~127,ip最多向后移动127个字节
                [jmp 2000:0100]转移指令是在debug中使用的汇编指令,汇编编译器不认识,源程序中使用会报错
____________________________________________________________________________________________________
实验8        这个程序可以正确返回吗?        运行后为什么是这种结果?
assume cs:codesg
codesg segment
        mov ax,4c00h        ;ip=0
        int 21h                ;ip=3
start:        mov ax,0        ;ip=5        ;程序入口
s:        nop                ;ip=8                ;经过运行以下代码,此处机器码 90 变成 EBF6
        nop                ;ip=9
        mov di,offset s        ;ip=10        di=8H
        mov si,offset s2;ip=13        si=20H
        mov ax,cs:[si]        ;ip=16        ax = cs:20 传送了指令[jmp short s1]的机器码EBF6 到AX
        mov cs:[di],ax        ;ip=19        cs:8 = ax   copy了数据 EBF6 而不是指令
s0:        jmp short s        ;ip=22        跳转到cs:8执行 jmp short s1
s1:        mov ax,0        ;ip=24
        int 21h                ;ip=27
        mov ax,0        ;ip=29
s2:        jmp short s1        ;ip=32d=20H  机器码 EBF6 ;12-22 = -10 补码 11110110B  246D  F6H
        nop                ;ip=34
codesg ends
end start
可以正确返回,运行结果:
执行ip=16 → ax = [jmp short s1] ip=19→cs:8 = [jmp short s1] ip=22→跳转到cs:8执行
(机器码跟原来的 EBF6 ,F6H=-10B) 向后移动10个字节 ip=0 → mov ax,4c00h int 21h
____________________________________
实验9 根据材料编程        ■12行32列处输入字符串
        编程:在屏幕中间分别显示绿色\绿底红色\白底蓝色的字符串'welcome to masm!'
        编程所需的知识通过阅读、分析下面的材料获得.
        80×25彩色字符模式显示缓冲区(简称显示缓冲区)的结构
        内存空间地址中,b8000h-bFFFFh共32kb的空间,为80×25彩色字符模式的显示缓冲区,向这个地址空间写入        

数据,写入的内容立即出现在屏幕上
■        在80×25彩色字符模式下,显示器可以显示25行,每行80个字符
■        每个字符可以有256种属性(背景色\前景色\闪烁\高亮等组合信息)
        这样,一个字符在显示缓冲区中就要占两个字节,分别存放字符的ASCII码和属性
■        80×25模式下,一屏的内容在显示缓冲区中共占4000个字节
        显示缓冲区分为8页,每页4KB(≈4000B),显示器可以显示任意一页的内容,一般情况下,显示第0页的内容
        通常情况下,B8000H~B8F9FH中的4000个字节的内容将出现在显示器上
        在一页显示缓冲区中:
■        偏移 000~09F 对应显示器上的第1行(80个字符占160个字节)
        偏移 0A0~13F 对应显示器上的第2行
        偏移 140~1DF 对应显示器上的第3行        依此类推        第25行偏移 F00~F9F
        在一行中,一个字符占两个字节的存储空间(1个字),低位字节存储字符的ASCII码,高位字节存储字符属性
■        一行共有80个字符占160个字节
        即在一行中:
        00~01单元对应显示器上的第1列
        00~02单元对应显示器上的第2列 依此类推,9E~9F单元对应显示器上的第80列
        例:在显示器的0行0列显示黑低绿色的字符串'ABCDEF'
        ('A'的ASCII码值为41H,02H表示黑底绿色)
        显示缓冲区里的内容为:
                        00 01 02 03 04 05 06 07 08 09 0A 0B        ... 9E 9F
        B800:0000        41 02 42 02 43 02 44 02 45 02 46 02        ... ... .. .. ..
        …………
        B800:00A0
■        可以看出,在显示缓冲区中,偶地址存放字符,奇地址存放字符的颜色属性
        一个在屏幕上显示的字符,具有前景(字符色)和背景(字符色)两种颜色,字符还可以以高亮度和闪烁的方式
        显示,前景色背景色闪烁高亮等信息被记录在属性字节中
■        属性字节的格式(二进制):        7          6  5  4          3          2  1  0                R:红色
                含义:                BL         R  G  B         I        E  G  B                G:绿色
                                闪烁           背景                高亮        前景                B:蓝色
■        可以按位设置属性字节,从而配出各种不同的前景色和背景色
        比如:
                红底绿字,属性字节为        01000010B
                红底闪烁绿字                11000010B
                红底高亮绿字                01001010B
                黑底白字                00000111B
                白底蓝字                01110001B
        例:在显示器的0行0列显示红底高亮闪烁绿色的字符串'ABCDEF'
        (红底高亮闪绿属性字节为:11001010B,CAH)
        显示缓冲区里的内容为:
                        00 01 02 03 04 05 06 07 08 09 0A 0B        ... 9E 9F
        B800:0000        41 CA 42 CA 43 CA 44 CA 45 CA 46 CA        ... .. ..
        ……
        b800:0000        .. .. .. .. .. .. .. .. .. .. .. ..        ... .. ..
■■        闪烁的效果必须在全屏dos方式下才能看到
______________________________________________RGB=红绿蓝  000=黑色  111=白色
绿色 :                 00000010        闪烁\R\G\B\高亮\R\G\B
红底绿色:        01000010
白底蓝色:        01110001


assume cs:code
data segment
        db 'w e l c o m e   t o   m a s m ! '
data ends
code segment
start:        mov ax,data
                mov ds,ax
                mov ax,0b800H
                mov es,ax
                mov cx,16
                mov bx,0
s:        mov al,[bx]
                mov es:[bx+64].8c0H,al
                mov es:[bx+64].960H,al
                mov es:[bx+64].0A00H,al
                mov ah,00000010B                ;或2h
                mov es:[bx+65].8c0H,ah
                mov ah,01000010b
                mov es:[bx+65].960H,ah
                mov ah,01110001b
                mov es:[bx+65].0A00H,ah
                inc bx
                inc bx
                loop s
mov ax,4c00h
int 21h
code ends
end start
评论次数(0)  |  浏览次数(596)  |  类型(笔记) |  收藏此文  | 
 
 请输入验证码  (提示:点击验证码输入框,以获取验证码