|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 cc20911 于 2022-9-3 13:48 编辑
在XP虚拟机里面编译链接没问题,运行也没问题,就是显示不出来,忙活了半天了,还是找不到问题在哪里,麻烦有空的大佬帮我看看,非常感谢
assume CS:code
datasg segment
;表示21个年份的21个8位型数据
DB '1975','1976','1977','1978','1979','1980','1981','1982'
DB '1983','1984','1985','1986','1987','1988','1989','1990'
DB '1991','1992','1993','1994','1995'
;表示21年中每年公司总收入的21个32位型数据 32位的被除数
DD 16,22,383,1356,2390,8000,16000,24486,50065,97479,140417
DD 197514,345980,590827,803530,118300,1843000,2759000
DD 3753000,4649000,5937000
;21年当中每年公司的的雇员数量,16位 16位的除数
DW 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037
DW 5635,8226,11542,14430,15257,17800
datasg ends
tabll segment
DB 21 dup('year summ ne ??? ',0)
tabll ends
stack segment
Dw 32 dup(0)
stack ends
code segment
start:
MOV AX,datasg
MOV DS,AX
MOV AX,tabll
MOV ES,AX
MOV AX,stack
MOV SS,AX
MOV sp,64
MOV BX,0
MOV SI,0
MOV DI,0
MOV CX,21
s1:
;======把数据先放入表格中,等待打印===============
PUSH CX
;年份
MOV AX,[BX]
MOV ES:[DI],AX
MOV AX,[BX+2]
MOV ES:[DI+2],AX
;年收入
MOV AX,[BX+54h]
MOV DX,[BX+56h]
MOV DI,10 ;表格第一行的“收入”从偏移10开始
CALL dtocdd ;dtocdd的目标为es:di
;人数
MOV AX,[SI+0a8h]
MOV DX,0 ;人数只有16位,没有高位
MOV DI,26 ;表格第一行的“收入”从偏移26开始
CALL dtocdd ;dtocdd的目标为es:di
;平均收入
MOV AX,[BX+54h] ;被除数的低位
MOV DX,[BX+56h] ;被除数的高位
MOV CX,[SI+0a8h] ;CX=除数
CALL divdw
MOV DI,36 ;表格第一行的“平均”从偏移36开始
;MOV ES:[DI+0dh],AX ;商的低位
;MOV ES:[DI+0fh],DX ;商的高位
CALL dtocdd
;
ADD BX,4h ;控制年份和收入,都是4字节型
ADD SI,2h ;控制人数,2字节型
ADD DI,2Ah ;控制表格行数,+41等于换行
POP CX
LOOP s1
s2:
;在屏幕上打印除表格数据
MOV DH,1 ;屏幕第1行开始
MOV DL,3 ;屏幕第3列开始
MOV CL,2 ;绿色
PUSH DS
MOV AX,DS
MOV ES,AX
MOV SI,0
CALL show_str ;show_str使用的参数为ds:si,
;这里要打印的是ES:DI
POP DS
MOV AX,4C00H
INT 21H
;====================================================
divdw:
;参数:AX=被除数低16位,DX=被除数高16位
;CX = 除数
;返回值:AX=结果的低16位,DX=结果的高16位
;CX = 余数
;原理:汇编语言(王爽)实验10.2
;做高位的除法
PUSH AX ;低16位先保存
;高16位先做除法
MOV AX,DX ;AX这时是高16位
MOV DX,0 ;dx置0为了不影响余数位
DIV CX ;相当于原被除数的高位先做除法
MOV BX,AX ;AX=商,暂时用bx保存,余数在DX中
;低16位再做除法
POP AX ;取低16位,dx现在是高位除法的余数
DIV CX ;继续除法,除完之后AX保存商
MOV CX,DX ;第二次除法的余数放入cx
MOV DX,BX ;第一次除法的商为整体除法的高位
;此时整体除法的商分别放在DX(高16位),AX(低16位)中
ret
show_str:
;参数:dh=行号(0-24),dl=列号(0-79)
;cl=颜色,ds:si指向字符串首地址
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
;定位行========================
MOV Al,0a0h ;每行偏移0a0h,160个字节
DEC DH ;第N行开始,所以偏移N-1行,8位乘以8位,
MUL DH ;结果存放在16位ax中
MOV BX,AX ;定位好的 “行” 位置偏移放BX中
;=============================
;定位列=======================
MOV AL,2 ;每列偏移2个字节
MUL DL
SUB AX,2 ;第N列开始,所以偏移N-1列
ADD BX,AX ;此时BX存放行与列的偏移地址
;=============================
;目标区域->显存===============
MOV AX,0b800h ;显存开始的地址
MOV ES,AX
MOV DI,0 ;di指向显存的偏移地址
;=============================
;把数据放入显存区域 ==========
MOV AH,CL ;颜色存入高位
MOV CH,0 ;下面需要用到CL,先把CH置0
s:
MOV CL,[SI] ;判断字符是否为0
JCXZ str_ok ;为0代表已到字符串尾,退出
MOV AL,CL ;字符存入低位,与显存对应
MOV ES:[BX+DI],AX ;AL=字符,AH=颜色
INC SI
ADD DI,2 ;显存一个字符占2字节
JMP short s
;==============================
str_ok:
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET
dtocdd:
;将word型整数转换为ASCII码字符串并保存
;参数:AX=数据低16位,DX=高16位
;es:di指向字符串首地址
PUSH DX
PUSH CX
PUSH BX
PUSH AX
PUSH SI
MOV BX,0 ;BX在子程序中用来存放位数,
;用栈来临时存放修改后的字符
s_dc1:
MOV CX,10 ;cx = 除数
CALL divdw
ADD CX,30h
PUSH CX ;保存转换号的字符
;为什么要给CX之后再OR,是为了保留AX,DX的
;值,不破坏下一次除法的参数
MOV CX,AX ; 低位商给CX
OR CX,DX ;高位与低位只要任意不为0,证明商不为0,
;还要继续除法
JCXZ s_dc2
INC BX ;bx保存有几位数,发现一位就加1
JMP short s_dc1
s_dc2:
ADD CX,30h
PUSH CX
INC BX ;再进行一次栈操作
;补充当商为0而余数不为0时的情况
MOV CX,BX ;总共有几位数,就循环几次
MOV DI,0
s_dc3:
POP AX
MOV ES:[DI],AL
INC SI
LOOP s_dc3
dtoc_ok:
POP SI
POP AX
POP BX
POP CX
POP DX
ret
code ends
end start |
|