ASSUME CS:CODE
DATA SEGMENT
DB '1975', '1976', '1977', '1978', '1979', '1980', '1981'
DB '1982', '1983', '1984', '1985', '1986', '1987', '1988'
DB '1989', '1990', '1991', '1992', '1993', '1994', '1995'
;以上表示21年的21个字符串
DD 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514
DD 345980, 590827, 803530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000
;以上表示21年公司总收入的21个DWORD型数据
DW 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
DW 11542, 11430, 15257, 17800
;以上表示21年公司雇员人数的21个WORD型数据
DATA ENDS
TABLE SEGMENT
DB 672 DUP (0)
TABLE ENDS
STACK SEGMENT
DW 128 DUP (0)
STACK ENDS
CODE SEGMENT
START:
MOV AX, DATA
MOV DS, AX
;DS存放DATA段地址
MOV AX, TABLE
MOV ES, AX
;ES存放TABLE段地址
MOV AX, STACK
MOV SS, AX
MOV SP, 80H
SUB BX, BX
SUB DI, DI
SUB SI, SI
;清空BX, DI, SI
MOV CX, 21
S:
PUSH [DI]
POP ES:[BX]
PUSH [DI].2H
POP ES:[BX].2H
MOV AX, [DI].54H
MOV WORD PTR ES:[BX].8H, AX
MOV DX, [DI].56H
MOV WORD PTR ES:[BX].0AH, DX
PUSH [SI].0A8H
POP ES:[BX].10H
PUSH CX
MOV CX, [SI].0A8H
CALL DIVDW
POP CX
MOV WORD PTR ES:[BX].18H, AX
ADD BX, 20H
ADD DI, 4H
ADD SI, 2H
LOOP S
MOV AX, TABLE
MOV DS, AX
SUB SI, SI
;DS:SI指向TABLE
MOV CL, 21
SUB CH, CH
MOV BX, 1
S1:
PUSH CX
MOV DH, BL
MOV DL, 1
MOV CL, 2
;第一行第一列绿色显示
CALL SHOW_STR
ADD SI, 8H
MOV AX, [SI]
MOV DX, [SI].2H
;将总收入读入DX+AX中
CALL DTOC
MOV DH, BL
MOV DL, 11
MOV CL, 2
;显示
CALL SHOW_STR
ADD SI, 8H
MOV AX, [SI]
SUB DX, DX
;将总收入读入DX+AX中
CALL DTOC
MOV DH, BL
MOV DL, 21
MOV CL, 2
;显示
CALL SHOW_STR
ADD SI, 8H
MOV AX, [SI]
SUB DX, DX
;将总收入读入DX+AX中
CALL DTOC
MOV DH, BL
MOV DL, 31
MOV CL, 2
;显示
CALL SHOW_STR
POP CX
ADD SI, 8H
INC BL
LOOP S1
MOV AX, 4C00H
INT 21H
;显示DWORD型数
;参数:AX低16位 DX高16位 DS:SI指向字符串首地址
DTOC:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
SUB BX, BX
PUSH BX
DTOC_START:
MOV CX, 10
CALL DIVDW
PUSH CX
MOV CX, AX
JCXZ DTOC_JCXZ
POP CX
ADD CX, 30H
PUSH CX
INC BX
JMP DTOC_START
DTOC_JCXZ:
MOV CX, DX
JCXZ DTOC_POP
POP CX
ADD CX, 30H
PUSH CX
INC BX
JMP DTOC_START
DTOC_POP:
POP CX
ADD CX, 30H
PUSH CX
INC BX
MOV CX, BX
DTOC_LOOP:
POP BX
MOV DS:[SI], BL
INC SI
LOOP DTOC_LOOP
POP BX
POP SI
POP DX
POP CX
POP BX
POP AX
RET
;计算不会溢出的除法
;参数:AX低16位 DX高16位 CX除数
;结果:AX低16位 DX高16位 CX余数
DIVDW:
PUSH BX
MOV BX, AX
MOV AX, DX
SUB DX, DX
DIV CX
;计算H/N
PUSH AX ;计算的商入栈
MOV AX, BX
DIV CX
;[REM(H/N)*65536+L]/N
MOV CX, DX
POP DX
POP BX
RET
;显示一个用0结束的字符串
;参数:DH行号 DL列号 CL颜色 DS:SI指向字符串首地址
SHOW_STR:
PUSH DX
PUSH CX
PUSH BX
PUSH AX
PUSH SI
PUSH ES
;用到的寄存器入栈
MOV AX, 0B800H
MOV ES, AX
MOV AL, 0A0H
MUL DH
;算出行偏移量
MOV BX, AX
MOV AL, 2
DEC DL
MUL DL
;算出列偏移量
ADD BX, AX
MOV AH, CL
SUB AL, AL
;AL存放颜色
SHOW_STR_START:
MOV CL, [SI]
SUB CH, CH
JCXZ SHOW_STR_END
;如果为0则结束
MOV AL, [SI]
MOV ES:[BX], AX
INC SI
INC BX
INC BX
JMP SHORT SHOW_STR_START
;不为0则给[bx]赋值并循环
SHOW_STR_END:
POP ES
POP SI
POP AX
POP BX
POP CX
POP DX
RET
;寄存器出栈
CODE ENDS
END START
折磨了很久,由于WIN7无法显示缓冲区的问题,只能在DEBUG中查看,这样真的很蛋疼,所以干脆就弄个了DOS虚拟机。
编这种程序,感觉很郁闷。似乎都是GOTO语句。难的有子程序一说……
附上代码: