对程序进行反汇编,运行至loop s1
处。
loop s1
的机器码为E2F2。F2的八位二进制形式为11110010,补码为10001110,为-14。即位移量为14。
从执行角度分析:
mov ah,2
mov dl,[si]
。运行至loop s2
处。
loop s2
的机器码为E2F0。F2的八位二进制形式为11110000,补码为10010000,为-16。即位移量为16。
与上题分析过程类似,略
call指令的跳转原理:
CPU 执行 call 指令时,进行两步操作:
- 将当前的 IP 或 CS 和 IP 压入栈中;
- 转移。
根据该原理进行分析:
call word ptr ds:[0]
所压入栈中的IP,为21call dword ptr ds:[2]
所压入栈中的CS:IP中的IP,为26call dword ptr ds:[2]
所压入栈中的CS:IP中的CS,具体数值未知使用DEBUG进行测试:
发现猜想正确。
assume cs:code, ds:data data segment x db 99,72,85,63,89,97,55 len equ $-x data ends code segment START: mov ax,data mov ds,ax mov bl,byte ptr 10;这个除数10应该为8位的数据,故采用byte形式。 mov si,offset x mov cx,len dec cx s: call printNumber call printSpace inc si loop s mov ax,4c00h int 21 printNumber: mov al,[si] mov ah,0h div bl;将al中的数除10,al中获得了商(实际上的十位数),ah中获得了余数(实际上的个位数)。 mov dh,ah;ah在中断显示中必须为2,所以先把数据放在dh中。 mov ah,2 mov dl,al or dl,30h;将ascii转为ascii中对应的数字 int 21h;显示十位数 mov dl,dh or dl,30h int 21h;显示个位数 ret printSpace: mov ah,2 mov dl,' ' int 21h;输出一个空格 ret code ends end start
assume cs:code, ds:data data segment x db 'try' len equ $ - x data ends code segment start: mov ax,0b800h mov es,ax mov ax, data mov ds, ax mov si,offset x mov cx,len mov bl,00001010b mov bh,0;设定了首字符地址指向x,长度为len,颜色黑底绿字,指定第一行 call printStr mov ax, data;直接初始化 mov ds, ax mov si,offset x mov cx,len mov bl,00001100b mov bh,24;设定了首字符地址指向x,长度为len,颜色黑底红字,指定第25行 call printStr;再次调用 mov ax, 4c00h int 21h printStr: mov al,160 mul bh;在80*25显示模式中,屏幕上每行有160个字节,则将bh乘160即可让bh代表屏幕上第几行。 mov di,ax s: mov al,[si] mov es:[di],al;ascii码 mov es:[di+1],bl;这个字符的显示颜色 inc si add di,2;转到两个字节后下一个显示字符的位置 loop s ret code ends end start
如果将代码中 line 33 的 160 改为 1 ,则红色的 try 会显示在第一行的第 12(24/2)个字符位。
assume cs:code, ds:data data segment stu_no db '201983290518' len = $ - stu_no data ends code segment start: mov ax,data mov ds,ax mov ax,0b800h mov es,ax call printBlueScreen;先画蓝屏底子 mov di,0f00h;在最后一行的第一位开始画横线 call printLines call printNum call printLines mov ax,4c00h int 21h printBlueScreen: mov di,0h mov cx,007d0h;整个屏幕可以显示2000个字符,换算成八进制就是07d。 mov al,00010000b s: mov es:[di+1],al add di,2 loop s ret printLines: mov al,0002dh;横线的ascii码 mov ah,00011111b mov cx,00022h;34次 s1: mov es:[di],al mov es:[di+1],ah add di,2 loop s1 ret printNum: mov cx,len mov si,offset stu_no mov ah,00011111b s2: mov al,[si] mov es:[di],al mov es:[di+1],ah inc si add di,2 loop s2 ret code ends end start
本章实验主要复习了80*25显示模式以及常用的跳转命令。这些命令主要都是jmp
命令的变体。
在80*25彩色显示模式中,每个字符占两个字节,第一个字节为ascii码,第二个字节为该字符显示在屏幕上的颜色。