王爽汇编第十一章至第十七章学习


11章节 标志寄存器

flag的1,3,5,12,13,14,15位在8086CPU中没有使用,不具有任何含义。而
0,2,4,6,7,8,9,10,11
一,ZF
flag的第6位是ZF,零标志位。它记录相关指令执行后,其结果是否为0。
如果结果为0,如么zF=1;如果结果不为0,如么ZF=0

影响FLAG标志寄存器的指令有: ADD,SUB,MUL,DIV INC,OR,AND等(运算指令逻辑或算术指令)
二,PF
flag的第2位是PF,奇偶标志位。它记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数,如果1的个数

为偶数PF=1,如果为奇数,哪么PF=0

三,SF标志
flag的第7位是SF,符号标志位。它记录相关指令执行后,其结果是否为负。如果结果为负,
SF=1;如果非负,SF=0

检测点11.1
写出下面每条指令执行后,ZF,PF,SF等标志位的值。
sub al,al   zf= 1    pf=1   sf=0
mov al,1    zf= 0    pf=0   sf=0
push ax     zf= 0    pf=0   sf=0
pop bx      zf= 0    pf=0   sf=0
add al,bl   zf= 0    pf=0   sf=0
add al,10   zf= 0    pf=1   sf=0
mul al      zf= 0    pf=1   sf=1

11.4 CF标志

flag的第0位是CF,进位标志位。一般情况下,在进行无符号数运算的时候,它记录了运算
结果的最高有效们向更高位的进位值,或是从更高位的借位值。

11.5 OF标志

flag的第11位是OF,溢出标志位。一般情况下,OF记录了有符号数运算的结果是否发生了
溢出。如果发生溢出,OF=1;如果没有,OF=0。
CF和OF的区别:CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位。
检测点 11.2
写出下面每条指令执行后,ZF PF SF CF OF 等标志位的值

           CF OF SF ZF PF

sub al,al   0 0 0 1 1
mov al,10H   0 0 0 0 0
add al,90H   0 0 1 0 1
mov al,80H   0 0 0 0 0
add al,80H   1 1 1 0 0
mov al,0FCH   0 0 1 0 1
add al,05H   1 1 1 0 1
mov al,7DH   0 0 0 0 1
add al,0Bh   0 0 1 0 1


11.6 ADC指令
adc是带进位加法指令,它利用了CF位上记录的进位值。

11.9检测比结果的条件转移指令
jmp             强跳
jcxz  关系到CX的值为0就跳否则什么都不做
je  zf=1
jne    zf=0
jb  cf=1
jnb  cf=0
ja  cf=0且zf=0
jna           cf=1或zf=1


检测点11.3
1,补全下面的程序,统计F000:0处32个字节中,大小在[32,128]的数据的个数
mov ax,0f000h
mov ds,ax
mov bx,0
mov dx,0
mov cx,32
s:  mov al,[bx]
 cmp al,32
 jb so
 cmp al,128
 ja so
 inc dx
so: inc bx
 loop s

2,补全下面的程序,统计F000:0处32个字节中,大小在(32,128)的数据的个数
mov ax,0f000h
mov ds,ax

mov bx,0
mov dx,0
mov cx,32
s: mov al,[bx]
 cmp al,32
 jna so
 cmp al,128
 jnb so
 inc dx
so: inc bx
 loop s
 
检测点11.4
下面的程序执行后:(ax)=?
mov ax,0
push ax
popf
mov ax,0fff0h
add ax,0010h
pushf
pop ax
and al,11000101b
and ah,00001000b
AX=45H


实验11 编写子程序

完整程序如下:

编写一个子程序,将包含任意字符,以0结尾的字符串中的小写字母转变成大写字母。
assume cs:codesg
datasg segment
        db "Beginner's All-purpose Symbolic Instruction Code.",0
datasg ends

codesg segment
start:
        mov ax,datasg
        mov ds,ax
        mov si,0
        call letterc

        mov ax,4c00h
        int 21h
letterc:
        push si
s:      mov al,[si]
        cmp al,0
        je exitsub
        cmp al,61h ;61h为'a'的ASCII码
        jb next
        cmp al,7ah ;7ah为'z'的ASCII码
        ja next
        and al,11011111B   ;或使用sub al,20h
        mov [si],al
next:   inc si
        jmp short s
exitsub:
        pop si
        ret ;子程序部分[结束]
codesg ends
end start

-d 0B9B:0
0B9B:0000  42 65 67 69 6E 6E 65 72-27 73 20 41 6C 6C 2D 70   Beginner's All-p
0B9B:0010  75 72 70 6F 73 65 20 53-79 6D 62 6F 6C 69 63 20   urpose Symbolic
0B9B:0020  49 6E 73 74 72 75 63 74-69 6F 6E 20 43 6F 64 65   Instruction Code
0B9B:0030  2E 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0B9B:0040  B8 9B 0B 8E D8 BE 00 00-E8 05 00 B8 00 4C CD 21   .............L.!
0B9B:0050  56 8A 04 3C 00 74 0F 3C-61 72 08 3C 7A 77 04 24   V..<.t.<ar.<zw.$
0B9B:0060  DF 88 04 46 EB EB 5E C3-E8 09 5F 83 C4 04 FF 76   ...F..^..._....v
0B9B:0070  04 FF 36 24 21 E8 BC 44-83 C4 04 80 3E 60 08 00   ..6$!..D....>`..
-g

Program terminated normally
-d 0b9b:0
0B9B:0000  42 45 47 49 4E 4E 45 52-27 53 20 41 4C 4C 2D 50   BEGINNER'S ALL-P
0B9B:0010  55 52 50 4F 53 45 20 53-59 4D 42 4F 4C 49 43 20   URPOSE SYMBOLIC
0B9B:0020  49 4E 53 54 52 55 43 54-49 4F 4E 20 43 4F 44 45   INSTRUCTION CODE
0B9B:0030  2E 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0B9B:0040  B8 9B 0B 8E D8 BE 00 00-E8 05 00 B8 00 4C CD 21   .............L.!
0B9B:0050  56 8A 04 3C 00 74 0F 3C-61 72 08 3C 7A 77 04 24   V..<.t.<ar.<zw.$
0B9B:0060  DF 88 04 46 EB EB 5E C3-E8 09 5F 83 C4 04 FF 76   ...F..^..._....v
0B9B:0070  04 FF 36 24 21 E8 BC 44-83 C4 04 80 3E 60 08 00   ..6$!..D....>`..

第12章节 内中断
1,用debug查看内存,情况如下:
0000:0000 68 10 A7 00 8B 01 70 00-16 00 9D 03 8B 01 70 00
则3号中断源对应的中断处理程序的入口地址为:0070:018B
2,存储N号中断源对应的中断处理程序入口的偏移地址的内存单元的地址为:0000:[n*4]
存储N号中断源对应的中断处理程序入口的段地址的内存单元的地址为:0000:[n*4+2]字单元

实验12 编写0号中断的处理程序
编写0号中断的处理程序,使得在除法溢出发生时,在屏幕中间显示字符串"divide
error!",然后返回到DOS。
要求:仔细跟踪调试,在理解整个过程之前,不要进行后面课程的学习。
;此题参照网上代码学习
ASSUME CS:CODESG  
CODESG SEGMENT  
START:  
    ;这时设置ds:[si]指向需要复制的代码处  
    MOV AX,CS  
    MOV DS,AX  
    MOV SI,OFFSET DO0;offset DO0是把程序开始到do0的偏移地址给si  
      
    MOV AX,0000  
    MOV ES,AX  
    MOV DI,0200H;设置es:[di]指向要复制程序的目标处  
      
    MOV CX,OFFSET DO0END - OFFSET DO0;设置复制的循环次数,这里的循环次数就是要复制程序的开始地址到程

序的结束地址  
      
    CLD;设置si、di按1增长  
      
    REP MOVSB;进行复制的循环过程  
      
    ;设置中断向量表,由于是N号中断,其段地址放在0000:[N*4]字单元中,其偏移地址放在0000:[N*4+2]字单

元中。所以0号中断的  
    ;中断程序的段地址放在0000:[N*4]字单元,其偏移地址放在0000:[N*4+2]字单元中。  
    MOV WORD PTR ES:[0*4],200H  
    MOV WORD PTR ES:[0*4+2],0000  
      
    ;这里是写的测试程序,当然也可以在debug时在写入执行  
    ;MOV AX,1000H  
    ;MOV BH,1  
    ;DIV BH  
       
    MOV AX,4C00H  
    INT 21H  
;此处是中断处理程序  
DO0:  
    ;开始时是是定义要输出的字符串,其不能执行,所以跳转到DO0START处开始执行  
    JMP SHORT DO0START  
    DB 'DIVIDE ERROR!' 
      
DO0START:  
    MOV AX,CS  
    MOV DS,AX  
    MOV SI,0202H;设置ds:[si]指向所定义的字符串'DIVIDE ERROR!' 
      
    MOV AX,0B800H  
    MOV ES,AX  
    MOV DI,12*160+36*2;设置es:[di]指向屏幕的中央处  
      
    MOV CX,13;这里是设置显示字符串的循环次数  
      
  S:  
    MOV AL,DS:[SI]  
    MOV AH,02H;设置显示的字体颜色  
    MOV ES:[DI],AX  
    ADD DI,2  
    INC SI  
    LOOP S   
      
    MOV AX,4C00H  
    INT 21H  
DO0END:  
    NOP   
CODESG ENDS  
END START 


-g

Program terminated normally
-d 0000:0200
0000:0200  EB 0D 44 49 56 49 44 45-20 45 52 52 4F 52 21 8C   ..DIVIDE ERROR!.
0000:0210  C8 8E D8 BE 02 02 B8 00-B8 8E C0 BF C8 07 B9 0D   ................
0000:0220  00 8A 04 B4 02 26 89 05-83 C7 02 46 E2 F3 B8 00   .....&.....F....
0000:0230  4C CD 21 00 00 00 00 00-00 00 00 00 00 00 00 00   L.!.............
0000:0240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0250  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0260  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0270  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................


第13章节 int 指令
1,在上面的内容中,我们用7CH中断例程实现LOOP的功能,则上面的7ch中断例
程所能进行的最大转移位移是多少?

分析:参考了abcrazy的说法:虽然说这里它实现了loop的功能,通过修改ip的值使得程序在跳转到循环开始处,

它把位移交给了bx来传递,因为bx所能存储的最大数是ffffh。虽然不能从某个段的偏移位置0转移到该段的偏移位

置ffffh但可以从ffffh转到0处执行。因为掉用7ch中断还要设置cx,bx要用掉至少6个字节,但从某段的ffff跳转到

0,实际跳转位移确实也是ffffh,此时bx设置为1,int 7ch这条语句在本段的fffeh位置,那么在执行该语句时,

(ip)=ffffh了,加1值溢出为0,就转到了本段开头执行。得最大转移位移FFFFH。

 

2,用7CH中断例程完成JMP NEAR PTR S指令的功能,用BX向中断例程传送转移位移。
应用举例:在屏幕的第12行,显示DATA段中以0结尾的字符串。
assume cs:code
data segment
 db 'conversation',0
data ends
code segment
start: mov ax,data
 mov ds,ax
 mov si,0
 mov ax,0b800h
 mov es,ax
 mov di,12*160
s: cmp byte ptr [si],0
 je ok
 mov al,[si]
 mov es:[di],al
 inc si
 add di,2
 mov bx,offset s-offset ok
 int 7ch
ok: mov ax,4c00h
 int 21h
code ends
end start

//参考njutyangxiao
assume cs:codesg    
datasg segment  
    db 'conversation',0  
datasg ends  
 
codesg segment  
    start:  
    mov ax,cs  
    mov ds,ax  
    mov si,offset lp_s  
      
    mov ax,0  
    mov es,ax  
    mov di,0200h  
      
    mov cx,offset lp_e - offset lp_s  
    cld  
    rep movsb  
      
    mov word ptr es:[7ch*4],0200h  
    mov word ptr es:[7ch*4+2],0000h  
 ;;;;;;;把中断例程的对应得代码拷贝到0000:0200  
 ;处并设置中断向量表项;;;;;;;;;;;;;;;;;;;;    
      
    mov ax,datasg   
    mov ds,ax  
    mov si,0  
      
    mov ax,0b800h  
    mov es,ax  
    mov di,12*160  
      
show_s:  
    mov al,ds:[si]  
    cmp al,0  
    je show_ok;判断是否达到了字符串的末尾  
    mov byte ptr es:[di],al   
    mov byte ptr es:[di+1],0a0h  
    add di,2    
    inc si       
    mov bx,offset show_s - show_ok;设置转移位移  
    int 7ch  
show_ok:  
    mov ax,4c00h  
    int 21h  
 
 lp_s:push bp  
    mov bp,sp  
    dec cx  
    jcxz lp_ret  
    add [bp+2],bx ;change the ip's value  
      
lp_ret:  
    pop bp  
    iret  
lp_e:nop  
      
codesg ends  


13.2
判断下面说法的正误:
(1)我们可以编程改变FFFF:0处的指令,使得CPU不去执行BIOS中的硬件系统检测和初始化程序。
解答:因为FFFF:0处为只读的ROM内存空间,无法编程改变。
(2)int 19h中断例程,可以由DOS提供。
解答:因为BIOS调用int 19h进行操作系统的引导,该中断例程运行在DOS之前,所以不可以由DOS提供。

实验13 编写、应用中断例程

1,编写并安装int 7ch中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处
参数:(dh)=行号,(dl)=列号,(cl)=颜色,ds:si指向字符串首地址。
代码如下:
assume cs:code

data segment
     db "welcome to masm!",0
data ends

code segment
start:
      ;安装程序
      mov ax, cs
      mov ds, ax
      mov si, offset ShowStr
      mov ax, 0
      mov es, ax
      mov di, 200h
      mov cx, offset EndShowStr - offset ShowStr
      CLD
      rep movsb
      
      ;设置中断向量
      n EQU 7ch
      mov bx, 4 * n
      CLI        ; 确保随后二条MOV指令被连续执行而不被打断
      mov word ptr es:[bx], 200h
      mov word ptr es:[bx+2], 0
      STI        ;开中断指令,它允许CPU响应其后的中断请求
      
      ;测试int 7ch中断例程 
      mov dh, 10
      mov dl, 10
      mov cl, 00001010b
      mov ax, data
      mov ds, ax
      mov si, 0
      int 7ch
      
      mov ax, 4c00h
      int 21h
      
ShowStr:         ;定义中断例程[开始]  
      push ax    ;子程序用到的寄存器入栈 
      push dx
      push si
      push di
      
      mov ax, 0b800h
      mov es, ax  
      mov ax, 160
      mul dh     ;确定行 
      xor dh, dh
      shl dl, 1  ;确定列
      add ax, dx
      mov di, ax ;设置输出位置 
      mov ah, cl ;确定颜色 
Show:      
      cmp byte ptr [si], 0
      je EndShow
      mov al, [si]
      mov es:[di], ax
      inc si
      add di, 2
      jmp Short Show
EndShow:
      pop di    ;子程序用到的寄存器出栈 
      pop si
      pop dx
      pop ax
      iret 
      
EndShowStr:     ;定义中断例程[结束]
      nop    
      
code ends
end start

D:/masm/src>debug test13.exe
-r
AX=0000  BX=0000  CX=0088  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B8B  ES=0B8B  SS=0B9B  CS=0B9D  IP=0000   NV UP EI PL NZ NA PO NC
0B9D:0000 8CC8          MOV     AX,CS
-t

AX=0B9D  BX=0000  CX=0088  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B8B  ES=0B8B  SS=0B9B  CS=0B9D  IP=0002   NV UP EI PL NZ NA PO NC
0B9D:0002 8ED8          MOV     DS,AX
-t

AX=0B9D  BX=0000  CX=0088  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B9D  ES=0B8B  SS=0B9B  CS=0B9D  IP=0004   NV UP EI PL NZ NA PO NC
0B9D:0004 BE3A00        MOV     SI,003A
-t

AX=0B9D  BX=0000  CX=0088  DX=0000  SP=0000  BP=0000  SI=003A  DI=0000
DS=0B9D  ES=0B8B  SS=0B9B  CS=0B9D  IP=0007   NV UP EI PL NZ NA PO NC
0B9D:0007 B80000        MOV     AX,0000

-g
Program terminated normally

-d 0000:0200
0000:0200  50 52 56 57 B8 00 B8 8E-C0 B8 A0 00 F6 E6 32 F6   PRVW..........2.
0000:0210  D0 E2 03 C2 8B F8 8A E1-80 3C 00 74 0B 8A 04 26   .........<.t...&
0000:0220  89 05 46 83 C7 02 EB F0-5F 5E 5A 58 CF 00 00 00   ..F....._^ZX....
0000:0230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0250  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0260  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0270  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................


2,编写并安装int 7ch中断例程,功能完成loop指令的功能。
参数:(cx)=循环次数,(bx)=位移。
以上中断例程安装成功后,对下面的程序进行单步跟踪,尤其注意观察int
iret 指令执行前后CS、IP 和栈中的状态

在屏幕中间显示80个'!'

assume cs:code
code segment
start: mov ax,0b800h
 mov es,ax
 mov di,160*12
 mov bx,offset s-offset se
 mov cx,80
s: mov byte prt es:[di],'!'
 add di,2
 int 7ch
se: nop
 mov ax,4c00h
 int 21h
code ends
end start


//参照网上作业的中断安装代码
assume cs:code
code segment
start:
        mov ax,cs
        mov ds,ax
        mov si,offset  lp

        mov ax,0
        mov es,ax
        mov di,200h

        mov cx,offset lpend-offset lp
        cld
        rep movsb

        mov ax,0
        mov es,ax
        mov word ptr es:[7ch*4],200h
        mov word ptr es:[7ch*4+2],0h

        mov ax,4c00h
        int 21h

lp:                           ;安装部分
        push bp
        mov  bp,sp
        dec cx
        jcxz lpset
        add [bp+2],bx
lpset:
        pop bp
        iret
lpend:                        ;安装结束
        nop
 
code ends
end start


3,下面的程序,分别在屏幕的第2、4、6、8行显示4句英文诗,补全程序。
assume cs:code
code segment
s1: db 'Good,better,best,','$'
s2: db 'Never let is rest,','$'
s3: db 'Till good is better,','$'
s4: db 'And better,best.','$'
s: dw offset s1,offset s2,offset s3,offset s4
row: db 2,4,6,8

start: mov ax,cs
 mov ds,ax
 mov bx,offset s
 mov si,offset row
 mov cx,4
ok: mov bh,0
 mov dh,[si]
 mov dl,0
 mov ah,2
 int 10h

 mov dx,[bx]
 mov ah,9
 int 21h
 
 inc si
 add bx,2

 loop ok
 mov ax,4c00h
 int 21h
code ends
end start


第14章节 端口

(1)编程:读取CMOS RAM的2号单元的内容。
assume cs:code
code segment
start:        mov al,2
        out 70h,al
        in al,71h                ;7:03时测试显示al=03
        
        mov ax,4c00h
        int 21h
code ends
end start

(2)编程:向CMOS RAM的2号单元写入0
assume cs:code
code segment
start:        mov al,2
        out 70h,al
        mov al,0
        out 71h,al
        in al,71h                ;7:05时测试显示al=0,证明写入正确
        
        mov ax,4c00h
        int 21h
code ends
end start


检测点14.2
    
编程,用加法和移位指令计算(ax)=(ax)*10。

assume cs:code
code segment
start:        mov ax,idata        ;此处idata为可以存储在ax中的数值。
        mov bx,ax
        shl ax,1        ;(ax)=(ax)*2
        mov cl,3
        shl bx,cl        ;(bx)=(ax)*8
        add ax,bx        ;(ax)=(ax)*10
        
        mov ax,4c00h
        int 21h
code ends
end start

实验14        访问CMOS RAM

编程:以“年/月/日 时:分:秒”的格式,显示当前的日期、时间。
注意:CMOS RAM中存储着系统的配置信息,除了保存时间信息的单元外,不要向其他的单元中写入内存,否则将引

起一些系统错误。

assume cs:code
  
code segment

  s:        db "yy/mm/dd hh:mm:ss",'$'
  s1:        db 9,8,7,4,2,0
start:        
        mov ax,cs
        mov ds,ax
        mov bx,offset s
        mov si,offset s1
        mov cx,6
ok:
        mov al,[si]        
        out 70h,al
        in al,71h                ;读取数据至al
        mov ah,al
        push cx
        mov cl,4
        shr al,cl                ;十位放在al中
        and ah,00001111b        ;个位放在ah中
        
        add ah,30h
        add al,30h
        
        mov [bx],ax                ;写入指定字符串
        pop cx
        add bx,3
        inc si
        loop ok
        
;利用int 20h的中断例程的子程序显示字符串
        mov ah,2        ;置光标
        mov bh,0        ;第0页
        mov dh,5        ;行号
        mov dl,12        ;列号
        int 10h
        
        mov dx,0        ;ds:dx指向字符串
        mov ah,9
        int 21h
        
        mov ax,4c00h
        int 21h

code ends
end start

第15章 外中断

(1),仔细分析一下上面的int9中断例程,看看是否可以精简一下?
其实在我们的int 9中断例程中,模拟int 指令调用原int 9 中断例程的程序段是可以
精简的,因为在进入中断例程后,IF和TF都已经置0,没有必要再进行设置了。对于程序
段:

pushf
pushf
pop ax
and ah,11111100b
push ax
popf
call dword ptr ds:[0]

可以精简为:
pushf
call dword ptr ds:[0]

两条指令。

(2)仔细分析上面的程序中的主程序,看看有什么潜在的问题?
 在主程序中,如果在执行设置int9中断例程的段地址和偏移地址的指令之间发生了键盘中断,则CPU将转去
一个错误的地址执行,将发生错误.
   找出这样的程序段,改写它们,排除潜在的问题.
 mov word ptr es:[9*4],offset int9
 mov es:[9*4+2],cs

 应改为:
 cli
 mov word ptr es:[9*4],offset int9
 mov es:[9*4+2],cs
 sti

实验15 安装新的int 9 中断例程


assume cs:code
data segment
 db 16 dup (0)
data ends            
code segment
start: mov ax,data
       mov ds,ax
       mov bx,0
       mov al,9
       mov dh,'/'
       mov cx,2
    s: call change
       mov al,8
       add bx,3
       loop s 
       mov al,7
       mov dh,' '
       call change
       add bx,3
       mov al,4
       mov dh,':'
       mov cx,2
   s1: call change
       mov al,2
       add bx,3
       loop s1
       mov al,0
       mov dh,'$'
       call change
       mov ah,2
       mov bh,0
       mov dh,12
       mov dl,0
       int 10h       ;//调用int10h2号中断例程置光标.
       mov dx,0
       mov ah,9
       int 21h       ;//调用int21h9号中断例程显示数据.
       mov ax,4c00h
       int 21h
change: push ax          ;//此子程序读取cmos ram中的数据并转化趁ascii码放入data段
        push cx          ;//参数al(读取cmos ram中几号单元)
        push dx          ;//dh(数据后缀).
        out 70h,al
        in al,71h
        mov ah,al
        mov cl,4
        shr ah,cl
        and al,00001111b
        add ah,30h   
        add al,30h
        mov [bx],ah
        mov [bx+1],al
        mov [bx+2],dh
        pop dx
        pop cx
        pop ax 
        ret
code ends
end start

 

第十六章节
16.1
1,下面的程序将CODE段中a处的8个数据累加,结果存储到B处的dword中,补全程序。
assume cs:code
code segment
   a dw 1,2,3,4,5,6,7,8
   b dd 0
start:  mov si,0
        mov cx,8
     s: mov ax,_____ a[si]
        add _____,ax cs:[16]
        adc _____,0  cs:[18]
        add si,_____ 2
        loop s
        mov ax,4c00h
        int 21h
code ends
end start

 

16.2
1,下面的程序将data段中a处的8个数据累加,结果存储到b处的字中。补全程序。
assume cs:code,es:data
data segment
   a db 1,2,3,4,5,6,7,8
   b dw 0
data ends
code segment
start: __________ mov ax,data
       __________ mov ds,ax
       mov si,0
       mov cx,8
    s: mov al,a[si]
       mov ah,0
       add b,ax
       inc si
       loop s
       mov ax,4c00h
       int 21h
code ends
end start


实验十六
编写包含多个功能子程序的中断例程
assume cs:code
code segment
int7ch: jmp short main
 table: dw cls,forecolor,backcolor,roll  
  main: push bx
        cmp ah,3
        ja return
        mov bl,ah
        mov bh,0
        add bx,bx
        call word ptr table[bx]
return: pop bx
        iret

cls: push ax         ;//清空
     push bx 
     push cx
     push ds
     mov ax,0b800h
     mov ds,ax
     mov bx,0
     mov cx,2000
empty: mov byte ptr [bx],' '
       add bx,2
       loop empty
       pop ds
       pop cx
       pop bx
       pop ax
       ret

forecolor: push ax        ;//换前景
           push bx
           push cx
           push ds
           mov bx,0b800h
           mov ds,bx
           mov bx,1
           mov cx,2000
    color: and byte ptr [bx],11111000b
           or [bx],al
           add bx,2
           loop color
           pop ds
           pop cx
           pop bx
           pop ax
           ret

backcolor: push ax         ;//换背景
           push bx
           push cx
           push ds
           mov bx,0b800h
           mov ds,bx
           mov bx,1
           mov cx,2000
  icolor:  push cx
           and byte ptr [bx],10001111b
           mov cl,4
           shl al,cl
           or [bx],al
           shr al,cl 
           add bx,2
           pop cx
           loop icolor
           pop ds
           pop cx
           pop bx
           pop ax
           ret
           
roll: push ax             ;//滚动。
      push cx
      push ds
      push di
      push si
      push es
      mov ax,0b800h
      mov ds,ax           
      mov es,ax
      mov di,0
      mov si,160
      mov cx,160*24
      cld 
      rep movsb
      mov cx,80
      inc si
clear: mov byte ptr es:[si],' '
       add si,2
       loop clear
       pop es
       pop si
       pop di
       pop ds
       pop cx
       pop ax
       ret 
int7chend: nop 
start: mov ax,0
       mov es,ax
       mov di,200h        ;es:di目的地址
       mov ax,cs
       mov ds,ax
       mov si,offset int7ch     ;ds:si源地址
       mov cx,offset int7chend-offset int7ch   ;长度
       cld           ;方向为正
       rep movsb
       mov word ptr es:[4*7ch],0
       mov word ptr es:[4*7ch+2],20h   ;//设置中断向量
       mov ax,4c00h
       int 21h           
code ends
end start


第十七章节
"在int16h中断例程中,一定有设置IF=1的指令。"这种说法对吗?
 我觉得对的,当键盘缓冲区为空时,int16h会将IF设为1等待用户输入.


实验十七

assume cs:code
code segment
start: mov ax,0
       mov es,ax
       mov ax,cs
       mov ds,ax
       mov di,200h
       mov si,offset int7ch       
       mov cx,offset int7chend-offset int7ch
       cld                               
       rep movsb                           ;//把中断例程写入内存
       cli 
       mov word ptr es:[7ch*4],200h 
       mov word ptr es:[7ch*4+2],0 
       sti        ;//设置向量表
       mov ax,4c00h
       int 21h
int7ch: push cx
        push dx
        cmp bx,2879
        ja return     ;//判断逻辑扇区是否大于2879
        cmp ah,1      ;//判断功能号是否大于1
        ja return
        je first
        call diskM_1
        mov ah,2
        int 13h
return: pop dx
        pop cx
        iret
 first: call diskM_1
        mov ah,3
        int 13h
        jmp short return
diskM_1: push bx         ;//此程序通过传逻辑扇区号求得磁道号、磁面号、扇区号并指定驱动器号.
         push ax
         mov ax,bx
         mov cl,18
         div cl
         mov dh,al         ;//计算逻辑扇区除以18,商为偶数磁面为0,奇数则为1
         and dh,1          ;//二进制最后位即可判断奇偶。
         mov cl,ah         
         inc cl           ;//余数自加1为扇区号
         mov ax,bx
         mov bl,36
         div bl
         mov ch,al        ;//逻辑扇区除以36的商即为磁道号.
         mov dl,0         ;//设驱动器号为0.
         pop ax
         pop bx
         ret
int7chend: nop
code ends
end start

你可能感兴趣的:(王爽汇编第十一章至第十七章学习)