将之前的Power idea公司的数据按照下图所示的格式在屏幕上显示出来。-LMLPHP

之前的文章

示例代码如下

assume cs:codesg
;将整个data段看作是一个数组,长度一共为
;21*4+21*4+2*21=168+42=210字节 data segment
db '', '', '', '', '', '', '', '', ''
db '', '', '', '', '', '', '', '', ''
db '', '', '' ;长度为84的数组,一个字符一个字节:4X21
dd , , , , , , , , , , , dd , , , , , , , ,
dw , , , , , , , , , , , , , , , ,
dw , , ,
data ends ;ax+210/16向上取整,即ax+14h ;对于ds,偏移量为16*14=224 table segment
db dup('year summ ne ?? ')
table ends show segment
db dup()
show ends temp segment
dw dup()
temp ends codesg segment
start: mov ax, data
mov ds, ax
mov bx, table
mov es, bx
mov bx, ;定位结构体数组元素
mov di, ;定位data中的4字节数据
mov si, ;定位data中的2字节数据
mov cx, 15h s0: ;转移年份
mov ax, ds:[di];
mov es:[bx], ax
mov ax, ds:[di+]
mov es:[bx+], ax ;添加空格
mov byte ptr es:[bx+], ;转移收入 ;作为被除数
mov ax, ds:[di+];
mov es:[bx+], ax
mov ax, ds:[di+]
mov es:[bx+], ax ;添加空格
mov byte ptr es:[bx+], ;转移雇员数量
mov ax, ds:[si+]
mov es:[bx+], ax ;添加空格
mov byte ptr es:[bx+], ;计算人均收入,并转移到table中
mov ax, es:[bx+] ;低16位
mov dx, es:[bx+] ;高16位
div word ptr es:[bx+]
mov es:[bx+], ax ;商默认存放在ax中 ;添加空格
mov byte ptr es:[bx+], ;操作完成,bx加16,di加2
add bx,
add di,
add si,
loop s0 ;s0循环的作用主要是将数据存储到table段中 ;而在s1循环中,先把table段中的数据转化为字符串,转储到 ;show段中,然后再在s2循环中调用show_str子程序来将这些字符串一行一行地 ;显示到屏幕上
mov ax, table
mov ds, ax
mov ax, show
mov es, ax
mov dx,
mov dh,
mov bx,
mov cx, 15h

s1:
mov di, ;这里的di作为table数据段的指针
push ds
push es
push cx
push dx ;保存行列信息,在调用show_str时会用到 ;转储年份
mov ax, ds:[bx+di]
mov es:[di], ax
add di,
mov ax, ds:[bx+di]
mov es:[di], ax
mov byte ptr es:[di+], ;转储收入
mov di,
mov ax, ds:[bx+di]
mov dx, ds:[bx+di+]
call dtoc ;转储人数
mov ax, ds:[bx+]
mov dx,
call dtoc ;转储人均收入
mov ax, ds:[bx+]
mov dx,
call dtoc ;以上就是table段中的一行转换为ASCII码值的处理过程 ;下面开始显示过程,此过程需要循环四次
pop dx
mov di, ;这里的di作为待输出数据段的指针
mov cx,
s2:
mov si,
call show_str
add dl, ;把列错开
loop s2
mov dl,
add dh,
add bx,
pop cx
pop es
pop ds
loop s1
mov ax, 4c00h
int 21h
dtoc:
;该子程序用于将数值型的数字转换为字符串 ;十进制数值转换为ASCII码值,转换关系为:ascii=10进制+30H ;要想将一个十进制的整数拆分成一个一个的数值,那我们需要让这个数 ;除以10,然后将得到的结果依次入栈,除完之后再依次出栈,即可得到由高位到低位 ;的所有数值,之后将这些值加上30H,即得到其对应的ASCII码值,然后将这些 ;ASCII码值存放到一个数据段中,调用show_str函数,来在屏幕上显示这些数值 ;为了存储转换后的ASCII码值,我们需要新开辟一个数据段
push bx
push cx
push dx
push ds
push ax
push si
push es
mov bx, ;记录十进制数据的位数
split: mov cx, 0ah ;cx存放除数
call divdw ;如果被除数大于2550,al是无法存放商的,会造成溢出,因此,我们需要调用本实验中第二个程序 ;专门用于解决除法溢出问题的程序 ;此程序返回运算后的商和余数,分别保存在ax和cx中
push cx ;余数入栈
inc bx ;当循环终止的时候可以进行弹栈存储操作了,但是我们需要一个标记,来标识我们需要 ;弹出多少次,我们使用bx来进行存储
mov cx, ax
add cx, dx ;ax中的值在下一次运算中一定会用到,dx中的值也有可能会用到(当被除数很大时) ;此时可以临时保存数据的只有cx了,因此我们直接将运算结果放到cx中 ;一举两得 ;判断条件是商==0,因此我么需要高16位和低16位全都为0
jcxz ok1 ;处理过程是需要循环的,循环结束的条件是商==0 ;我们只需要将执行jcxz指令即可,当cx的值位0的时候,它会自动跳转到ok1循环的
jmp short split
ok1:
pop ax
add al, 30h
mov byte ptr es:[di], al
inc di dec bx
mov cx, bx
jcxz last jmp short ok1 last:
;最后一步,在数据的ASCII数据形式的最后加上一个0
mov ah,
mov byte ptr es:[di], ah
inc di
pop es
pop si
pop ax
pop ds
pop dx
pop cx
pop bx
ret
divdw:
push ds
push dx
push cx
push bx
push ax
mov ax, temp
mov ds, ax
mov ax, dx
mov dx,
div cx ;ax存放商,dx存放余数 ;根据公式,使用被除数高位除以除数得到的商×65536 ;*65536等价于在低位加16个0,因此操作就会变得非常简单 ;使用被除数高位除以除数得到的余数×65536+被除数的低位,再将得到的结果除以除数 ;两者的结果相加,即可得到32位/16位的无溢出结果 push dx ;使用栈临时保存余数
mov dx, ax
mov ax,
mov ds:[], ax
mov ds:[], dx
pop dx ;弹出余数,作为右操作数中被除数的高16位 pop ax ;得到被除数的低16位 push ax ;恢复栈顶数据,避免对主程序造成干扰 ;将右操作数[]中的左操作数的低16位和被除数的低16位相加 ;但是右操作数[]中的左操作数的低16位一定是全0的,因此我们可以省略这一步 ;直接执行pop ax,将被除数的低16位作为右操作数的低16位 div cx ;ax存放商,dx存放余数 ;由于左操作数的低16位一定是全0,所以不必与其相加,直接将 ;右操作数的低16位存储到ds:[0]内存单元即可
mov ds:[], ax ;商的低16位放到ds:[0]单元中 mov ds:[4], dx ;余数放到ds:[4]单元中 ;ds:[2]中一直保存的都是商的高16位,且没有被更改过,因此无须任何操作
pop ax
pop bx
pop cx
pop dx
mov ax, ds:[] ;ax保存商的低16位
mov dx, ds:[] ;dx保存商的高16位
mov cx, ds:[] ;cx保存余数 pop ds ;之所以要在pop ds之前将数据转移,是因为子程序divdw调用前,ds已经被使用 ;指向的是其他的段,如果不在pop之前转移数据,那么div段的数据就无法获取了
ret
show_str:
push ax
push bx
push cx
push dx
push es
push ds ;根据上节中的框架,为了不让子程序干扰主程序中寄存器的值,将所有子程序会用到的寄存器进行压栈
mov ax, 0b800h
mov es, ax ;颜色区的段地址
mov ax, show
mov ds, ax ;要读入的数据区的段地址
mov al,
mul dh ;每行占160个字节,乘以行数
push ax ;将行计算的结果存储到栈中
mov al,
mul dl ;每列占2个字节,乘以列数
pop bx ;将上次运算的结果(160×行数)的值转移到bx中 add bx, ax ;此时的ax值为(2×列数) ;将两者相加,最终结果保存到bx中
mov dl, ;显示颜色为绿色
change:
mov cl, ds:[di]
inc di
mov ch,
jcxz ok
mov ch, dl
mov es:[bx+si], cx
add si,
jmp short change
ok:
pop ds
pop es
pop dx
pop cx
pop bx
pop ax
ret
codesg ends
end start

参考链接: https://blog.csdn.net/include_heqile/article/details/80629599

05-08 08:28