做这个程序,花了很久时间。回想起来觉得主要原因还是和基础概念有关系。
比如:我一开始的程序里面的SHOW_STR里用MOV SS, AX , 这句话造成我的DEBUG到这一行程序就崩溃了。
这就造成我没办法DEBUG,只能试着替换一些可疑的地方, 然后直接编译运行来验证结果。
MOV SS, AX 改成
DS 入栈
MOV DS, AX,
...
DS 出栈
就没有DEBUG问题了。看了网上解释是说DEBUG也需要用SS,所以会有这种问题。
还有就是进出子程序时,我觉得可以将所有的REGISTER入栈和出栈来保存栈内的值,这样比较容易也轻松很多。但是程序会稍微面一些,因为会将一些子程序没用到的REGISTER
入栈和出栈。
下面就是我的代码:
assume ds:data, es:table, cs:code
data segment
db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982'
db '1983' ,'1984', '1985', '1986', '1987', '1988', '1989', '1990'
db '1991', '1992', '1993', '1994', '1995' ; 4bytes per year
dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486 ;4 bytes per number
dd 50065, 97479, 140417, 197514, 345980, 590827, 803530, 1183000
dd 1843000, 2759000, 3753000, 4649000, 5937000
dd 3, 7, 9, 13, 28, 38, 130, 220
dd 476, 778, 1001, 1442, 2258, 2793, 4037, 5635
dd 8226, 11542, 14430, 15257, 17800
data ends
table segment
;db 'year summ n1 ?? '
;db 'year summ n2 ?? '
;db 19 dup ('year summ ne ?? ')
db 'Year' ; Year 4 digits [0-3]
dw 0 ; amont L [4-5]
dw 0 ; amont H [6-7]
dw 0 ; people count [8-9]
dw 0 ; averge [10-11]
dw 0 ; filler [12-13]
dw 0 ; filler [14-15]
;[16-17],[18-19],[20-21],[22-23],[24-25],[26-27],[28-29],[30-31]
dw 00,317ah,0000h,000Ah,0008h,0008h,0008h,0008h
;[32],[33],[34],[35],[36],[37],[38],[39],[40],[41],[42],[43],[44],[45],[46],[47]
db 16 dup (0) ;decimal output buffer
;[48 - 55]
db 8 dup (' ') ;year
;[56 - 71]
db 16 dup (' ') ;total amount
;[72 - 87]
db 16 dup (' ') ;Peope count
;[88 - 103]
db 16 dup (' ') ;average count
;[104 - 107]
dw 00,00 ;function movCol parameters, 104 is source position, 106 is output position
;[108]
dw 00 ;data segment pointer value, can be 0, 1
;[110]
db 00 ;Display buffer pointer value
table ends
code segment
start: mov ax, data
mov ds, ax
mov ax, table
mov es, ax
;*********************使用LOOP 开始
mov cx, 21
mov es:[110], 0b800h
mov si, 0
mov ax, 0
shwNYr:
mov bx, es:[110]
add bx, 0Ah
mov es:[110], bx
mov es:[108], ax ; mov 0 to year data pointer
add ax, 4
Call shwYear
loop shwNYr ;
;*********************使用LOOP 结束
;*********************使用21次硬编码 开始
; mov es:[110], 0b800h ;0 ;1975
; mov ax, 0
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b80Ah ;1 ;1976
; mov ax, 4
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b814h ;2 ;1977
; mov ax, 8
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b81Eh ;3 ;1978
; mov ax, 12
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b828h ;4 ;1979
; mov ax, 16
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b832h ;@60 5 ;1980
; mov ax, 20
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b83Ch ;@71 6 ;1981
; mov ax, 24
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b846h ;7 ;1982
; mov ax, 28
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b850h ;8 ;1983
; mov ax, 32
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b85Ah ;9 ;1984
; mov ax, 36
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b864h ; 10 ;1985
; mov ax, 40
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b86Eh ; 11 ;1986
; mov ax, 44
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b878h ; 12 1987
; mov ax, 48
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b882h ; 13 1988
; mov ax, 52
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b88Ch ; 14 1989
; mov ax, 56
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b896h ; 15 1990
; mov ax, 60
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b8A0h ; 16 1991
; mov ax, 64
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b8AAh ; 17
; mov ax, 68
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b8B4h ; 18
; mov ax, 72
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b8BEh ; 19
; mov ax, 76
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b8C8h ;20
; mov ax, 80
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
; mov es:[110], 0b8D2h ; 21
; mov ax, 84
; mov es:[108], ax ; mov 0 to year data pointer
; Call shwYear
;*********************使用21次硬编码 结束
mov ax, 4c00h
int 21h
;***********************************************************
;****** Show One Year's inform
shwYear:
push ax
push bx
push cx
push dx
;push sp
push bp
push si
push di
mov si, es:[108] ;year off set
;mov ax, es:[si] ;year off set
;put year at line 18 db 'Year' ; Year 4 digits
mov ax, ds:[si] ;ds:[0]
mov es:[0], ax
mov ax, ds:[si+2] ;ds:[2]
mov es:[2], ax
;put amount
;off set 21 year, 21 * 4= 84bytes
mov ax, ds:[si+84] ;ds:[84] ;ds:[84] = 16
mov es:[4], ax
mov ax, ds:[si+86] ;ds:[86] ;ds:
mov es:[6], ax
;put people count
;off set 21 numbers, 21 * 4= 84bytes
mov ax, ds:[si+168] ; ds:[168]
mov es:[8], ax
;Now I got '31 39 37 35 10 00 00 00-03 00 00 00 00 00 00 00'
;push bp
Call divDW ;Compile Line @2D
;pop bp
;D 1966:0 f should be
;'31 39 37 35 10 00 00 00-03 00 00 00 05 00 00 00'
;*********************** Move Year ************************
mov ax, es:[0] ;Line 47 in exe
mov es:[48], ax
mov ax, es:[2]
mov es:[48+2], ax
;D 1966:30 3f should be
;'31 39 37 35 20 20 20 20-20 20 20 20 20 20 20 20'
;*********************** Move Total Amount ************************
mov ax, 4
mov es:[104], ax
mov ax, 56
mov es:[106], ax
;push bp
Call MovCol ;@5E
;pop bp
;D 1966:30 3f should be
;'31 39 37 35 20 20 20 20-31 36 20 20 20 20 20 20'
;push bp
CALL clnBuf
;pop bp
;*********************** Move People Amount ************************
mov ax, 8
mov es:[104], ax
mov ax, 72
mov es:[106], ax
;push bp
Call MovCol ;@81
;pop bp
;D 1966:30 4f
;'31 39 37 35 20 20 20 20-31 36 20 20 20 20 20 20'
;'20 20 20 20 20 20 20 20-33 20 20 20 20 20 20 20'
;push bp
CALL clnBuf
;pop bp
;********************** Move average ***********************
mov ax, 12
mov es:[104], ax
mov ax, 88
mov es:[106], ax
;push bp
Call MovCol ;@81
;pop bp
;D 1966:30 4f
;'31 39 37 35 20 20 20 20-31 36 20 20 20 20 20 20'
;'20 20 20 20 20 20 20 20-33 20 20 20 20 20 20 20'
;push bp
CALL clnBuf
;pop bp
;mov string terminator
mov cx, 0 ;@11B
mov es:[93], cx
;D 1966:30 5f
;'31 39 37 35 20 20 20 20-31 36 20 20 20 20 20 20'
;'20 20 20 20 20 20 20 20-33 20 20 20 20 20 20 20'
;'20 20 20 20 20 20 20 20-35 20 20 20 20 20 20 00'
MOV ax, es:[110] ;0b800h
;push bp
Call Show_str ;@123
;pop bp
pop di
pop si
pop bp
;pop sp
pop dx
pop cx
pop bx
pop ax
ret
;***********************************************************
;****** Move Column
movCol:
;pop bp
push ax
push bx
push cx
push dx
;push sp
push bp
push si
push di
mov si, es:[104]
mov ax, es:[si]
mov es:[18], ax ; 4240 Divident(L)
mov ax, es:[si+2]
mov es:[20], ax ; 000f Divident(H)
mov si, 46
push bp
Call ToAsc ;@11C
pop bp
mov cx, 8
mov bx, 0
mov si, 0
movAsc4:
PUSH cx
mov cx, es:[31+si]
ADD si, 2
jcxz skpEmp4
mov ax, table
mov es, ax
push si
mov si, es:[106]
mov es:[si+bx], ch
pop si
ADD bx, 1
skpEmp4:
pop cx
loop movAsc4 ;
pop di
pop si
pop bp
;pop sp
pop dx
pop cx
pop bx
pop ax
;push bp ;@147
ret
;***********************************************************
;****** Show Text
show_str:
;pop bp ;@F6
push ax
push bx
push cx
push dx
;push sp
push bp
push si
push di
push ss
push ds
;mov ax, 0b86eh
mov ax, es:[110]
mov ds, ax ;row
mov si, 08 ;Column, control left or right on screen
mov bx, 0 ;String stard postion
mov ah, 00000010B ;Font
main:
mov cl, es:[bx+48] ; ds:[bx] is the character @109
mov al, ' '
mov es:[bx+48], al ; reset the ascii to empty
mov al, cl
mov ch, 0
jcxz EXIT_SS ;@110
mov ds:[si], ax ; this ss:[si+bx] is character position
inc bx
add si, 2
jmp short main ;@119
EXIT_SS:
pop ds
pop ss
pop di
pop si
pop bp
;pop sp
pop dx
pop cx
pop bx
pop ax
ret
;*******************divDW************************
;| | | | | | | |
;0 4 6 8 10 12 14
;0 - year
;4 - revenue LOW
;6 - revennue HIGH
;8 - People
;10 - Average
;12 - Not in use
;14 - Not in use
;For example input is
;31 39 37 35 10 00 00 00-03 00 00 00 00 00 00 00'
;then output should be
;31 39 37 35 10 00 00 00-03 00 00 00 05 00 00 00'
; db 'Year' ; Year 4 digits [0-3]
; dw 0 ; amont L [4-5]
; dw 0 ; amont H [6-7]
; dw 0 ; people count [8-9]
; dw 4 ; averge [10-11]
; dw 4 ; filler [12-13]
; dw 4 ; filler [14-15]
divDW: ;chapter: 8.7 Page 157
push ax
push bx
push cx
push dx
;push sp
push bp
push si
push di
MOV BX, es:[4] ;4240 Divident(L) ;Compile Line 5E @FD
MOV AX ,es:[6] ; 000f Divident(H)
MOV CX ,es:[8] ; 000A Divisor
MOV DX, 0
DIV CX ; (DX(0) + AX(000f)) / CX
mov es:[14], ax
MOV AX, BX ; move Divident (L) in AX
DIV CX ; (DX(0005) + AX (4240)) / CX
mov es:[12], ax
;mov es:[0], dx
pop di
pop si
pop bp
;pop sp
pop dx
pop cx
pop bx
pop ax
ret ;@11D
;*******************To Ascii************************
;| | | | | | | |
;0 2 4 6 8 10 12 14
;0 - remainder
;2 - Divident LOW
;4 - Divident HIGH
;6 - TEN
;8 - NOT IN USE
;dw 00,4240h,000fh,000Ah,0008h,0008h,0008h,0008h
;PUT the output to 32-47 position
;
ToAsc: ;chapter: 8.7 Page 157 @1A8
push ax
push bx
push cx
push dx
;push sp
push bp
push si
push di
ToAsc_m:
MOV BX, es:[18] ; 4240 Divident(L)
MOV AX ,es:[20] ; 000f Divident(H)
MOV CX ,es:[22] ; 000A Divisor
MOV DX, 0 ;@12E
DIV CX ; (DX(0) + AX(000f)) / CX
mov es:[20], ax
MOV AX, BX ; move Divident (L) in AX
DIV CX ; (DX(0005) + AX (4240)) / CX
mov es:[18], ax
mov es:[16], dx
mov cx, es:[16] ; set remaider in cx
add cx, 30h ; add decimal ascii
mov es:[si], cx
SUB si, 2
mov ax, es:[18] ; using bit OR to merge Divident H to Divident Low
OR ax, es:[20] ; Divident H is ds:[4], Divident L is ds:[2]
MOV cx, ax ; Then check whether ds:[2] is 0 or not
jcxz EXIT_TA ;exit_toAsicc ;@1E7
jmp ToAsc_m
EXIT_TA:
pop di
pop si
pop bp
;pop sp
pop dx
pop cx
pop bx
pop ax
ret
;***********************************************************
;****** clean buffer
clnbuf:
push ax
push bx
push cx
push dx
;push sp
push bp
push si
push di
mov cx, 8 ;@61
mov bx, 0
reset:
MOV ax, 0
mov es:[32+bx], ax
ADD bx, 2
loop reset
pop di
pop si
pop bp
;pop sp
pop dx
pop cx
pop bx
pop ax
ret
code ends
end start