ITEEDU

当程序使用03H功能取得光标位置时,BIOS会把光标的高度通过CX寄存器返回,CH是光标起始扫描线,CL是光标终止扫描线。注意这里所说的扫描线是指在一个字符空间内的位置。请看下面用DEBUG跟踪的结果:

C:\ASM\>DEBUG DISPSTR2.EXE[Enter]
-g=0 b[Enter]?   光标类型?   光标位置
AX=0310 BX=0000 CX=0D0E DX=1800 SP=0000 BP=0000 SI=0000 DI=0000
DS=0A10 ES=0A00 SS=0A10 CS=0A12 IP=000B NV UP EI PL NZ NA PO NC
0A12:000B B314 MOV BL,14

返回的光标类型为0D0EH,说明光标起始于第13线,终止于14线。无论光标在屏幕的哪个位置,这两个数字都不会变。VGA卡全屏共有480根扫描线,每个字符占16根线,因此VGA卡的光标起始线和终止线决不会大于16。

既然光标形状是可以改变的,那么有没有方法通过程序改变光标类型呢?BIOS为我们提供了一个功能调用--01H功能,这个功能专用于改变光标类型:

功能号:01H
用 途:改变光标类型
参 数:CH=光标起始行(0-15)
CL=光标结束行(0-15)
调 用:INT 10H
返 回:无

下面的程序演示了这个功能调用的应用,程序中又出现了一个新的条件转移指令:

助记符:JNS(Jump if Not Signed)
用 途:根据运算结果的符号情况进行转移
格 式:JNS 目的地址
执 行:若标志寄存器"符号位"SF为0,则执行转移

不用问,和这条指令功能相对的指令必然是"JS"(Jump if Signed)。我们先来领略一下这个演示程序:

        code  segment
              assume    cs:code,ds:code
              org       100h
        main  proc      far
              jmp       short start
         msg  db        'Press any key...',0dh,0ah,24h
      start:  mov       ah,09h	;输出字符串MSG
              mov       dx,offset msg
              int       21h
			
              mov       ch,0fh	;设置光标起始扫描线
              mov       cl,0fh	;设置光标终止扫描线
     change:
              mov       ah,1	;利用10H中断的01功能
              int       10h	;改变光标形状
			
              mov       ah,0	;等待键盘输入
              int       16h
			
              dec       ch	;光标起始扫描线减1
              jns       change	;转至CHANGE继续改变光标形状
			
              int       20h	;结束进程
        main  endp
        code  ends
              end       main

运行这个程序并连续按键,就可以看到光标形状所发生的变化。现在我们来谈谈指令JS与JNS,这两条指令和SF标志有密切关系,所以我们先来研究SF标志究竟受什么指令影响,这又要请我们的老朋友--DEBUG来帮助:

C:\ASM\>DEBUG [Enter]
-a100[Enter]
13CD:0100 mov ax,ffff	;0FFFFH送入AX寄存器
13CD:0103 dec ax		;计算0FFFFH-1
13CD:0104 add ax,3		;计算0FFFEH+3
13CD:0107 or ax,8000	;将AX寄存器的符号位置1
13CD:010A and ax,7fff	;将AX寄存器的符号位清0
13CD:010D ror ax,1		;将AX寄存器的最低位移至符号位
13CD:010F[Enter] 

输入了以上程序,我们即可开始跟踪这个实验程序,下面给出了跟踪过程,可以看到用MOV指令将一个带符号数送入累加器后符号标志为0。

-t      AX寄存器预先置入0FFFFH
AX=FFFF BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13CD ES=13CD SS=13CD CS=13CD IP=0103 NV UP EI PL NZ NA PO NC
13CD:0103 48DEC AX?    准备计算0FFFFH-1  符号标志为0

 以下是计算0FFFFH-1的结果,可以看到符号位由0变为1,说明计算结果为负数。可见标志寄存器只受计算指令的控制,不受数据传递指令的控制。

-t      计算结果为-2
AX=FFFE BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13CD ES=13CD SS=13CD CS=13CD IP=0104 NV UP EI NG NZ NA PO NC
13CD:0104 050300 ADD AX,0003?    准备计算-2+3  符号标志置1

注意以上我们都把0FFFFH作为带符号数-1来看待,实际上0FFFFH同时也表示无符号数65535。SF标志并不反映65535-1的后果,65535-1的后果由CF标志反映。由此再次说明我们是通过判断不同的标志位"暗示"出我们对某个数是否带符号的理解。

-t      -2+3=1
AX=0001 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13CD ES=13CD SS=13CD CS=13CD IP=0107 NV UP EI PL NZ NA PO NC
13CD:0107 0D0080 OR AX,8000?准备进行逻辑操作?符号标志清0

通过跟踪-2+3的计算,再次看到符号标志的改变情况:当计算结果符号位为1时SF=1,否则SF=0。同时通过CF的变化,我们也可以看到65534+3的结果。

-t      逻辑"OR"操作的结果
AX=8001 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13CD ES=13CD SS=13CD CS=13CD IP=010A NV UP EI NG NZ NA PO NC
13CD:010A 25FF7F AND AX,7FFF     符号标志再次置1

逻辑"OR"操作同样改变符号标志,下面给出逻辑"AND"操作的跟踪结果,可以看出逻辑操作指令与数学计算指令一样要影响SF标志位:

-t      逻辑"AND"操作的结果
AX=0001 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13CD ES=13CD SS=13CD CS=13CD IP=010D NV UP EI PL NZ NA PO NC
13CD:010D D1C8R OR AX,1?准备进行移位操作?符号标志再次清0

最后是利用移位指令改变符号位时标志寄存器的变化,可以看到移位指令"ROR"没有改变SF标志。

-t      移位后的结果
AX=8000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=13CD ES=13CD SS=13CD CS=13CD IP=010F NV UP EI PL NZ NA PO NC
13CD:010F B208 MOV DL,08符号标志无变化