能力值:
( LV3,RANK:20 )
11 楼
楼主神速,我陆陆续续学了一年这本书。
==============================================================================
第10章 课程设计1
==============================================================================
assume cs:codesg,ds:data
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
data ends
table segment
db 16 dup (0)
table ends
codesg segment
start:
mov ax,data
mov ss,ax ;ss指向数据
mov bp,0
mov bx,0
;21行循环年份
mov cx,21
Row1:push cx
push bp
mov si,bp ;把年份首地址存入si中传给show_year
call show_year
inc bx ;当前行数存入bx中,传给show_year
pop bp
add bp,4 ;下一个年份首地址,每个年份占4个字节
pop cx
loop Row1 ;21行循环收入
mov si,0 ;当前行计数
mov bp,0
mov di,0
mov cx,21
Row2:push cx ;按顺序压入本段变量
push bp
push di
mov ax,[bp+54h+di] ;循环写入收入。数据启始地址+收入偏移量+每次移动2个字节
mov dx,[bp+54h+di+2]
call dtoc ;转换数字为ascll码
mov dh,4 ;设置显示初始值
mov dl,13
mov cl,2
call show_str ;显示字符串
inc si ;循环到第几行了
pop di
add di,4
pop bp
pop cx
loop Row2 ;21行循环雇员数
mov si,0 ;当前行计数
mov bp,0
mov di,0
mov cx,21
Row3:push cx ;按顺序压入本段变量
push bp
push di
mov ax,[bp+00a8h+di] ;循环写入收入。数据启始地址+收入偏移量+每次移动2个字节
mov dx,0000h
call dtoc ;转换数字为ascll码
mov dh,4 ;设置显示初始值
mov dl,23
mov cl,2
call show_str ;显示字符串
inc si ;循环到第几行了
pop di
add di,2
pop bp
pop cx
loop Row3
;21行循环人均收入
mov si,0 ;当前行计数
mov bp,0
mov di,0
mov cx,21
Row4:push cx ;按顺序压入本段变量
push bp
mov ax,[bp+54h] ;被除数低16位
mov dx,[bp+54h+2] ;被除数高16位
push di
div word ptr ss:[00a8h+di] ;收入/雇员数=人均收入,结果存在ax中
mov dx,0000h
call dtoc ;转换数字为ascll码
mov dh,4 ;设置显示初始值
mov dl,33
mov cl,2
call show_str ;显示字符串
inc si ;循环到第几行了
pop di
add di,2 ;di加2是为了循环雇员数
pop bp
add bp,4
pop cx
loop Row4
mov ax,4c00h
int 21h
;显示年份(当前行数用bx)
show_year: mov dh,4
mov dl,3
mov cl,2
mov ax,0b800h
mov es,ax
mov al,160
mul dh ;每行160*8行
mov bp,ax
mov al,2 ;3列*每列2个字节
mul dl
add bp,ax
;mov bp,160*8+3*2 ;每行160*8行+3列*每列2个字节,160*8+3*2=0506h
mov ax,160
mul bx ;bx是当前行数
mov dl,cl ;保护cl,因为cx要循环
mov di,ax ;乘法的结果ax,得到当前行偏移量存入di中
mov cx,4 ;年份是4个字符
while:mov ax,ss:[si] ;si是年份在data中的首地址
mov es:[bp+di],ax
mov es:[bp+di+1],dl ;是颜色
inc si
add di,2
loop while
ret
;转换数字为ascll码
dtoc:mov cx,0
push cx ;先压入一个0作为是否到结尾的判断。
dtoc2:mov cx,0ah ;16位高位在dx,低位在ax中已经放好了。除数放在cx中
call divdw ;调用防止溢出除法程序。
add cx,30h ;余数加30h变成ascll码
push cx ;把余数压入
mov cx,ax ;配合jmp使用的,判断商是否为0
jcxz return
jmp short dtoc2
return:mov ax,table ;出栈字符串存放的位置
mov ds,ax ;ds指向table段
mov di,0 ;di指向table首地址
chang2:pop ax
mov [di],ax
inc di
mov cx,ax
jcxz ok2
jmp short chang2
ok2:mov di,0 ;ds:si指向字符传首位,下一步为显示做准备
ret
;显示字符串(当前行数用si)
show_str: mov ax,0b800h
mov es,ax
mov al,160
mul dh ;每行160*8行
mov bp,ax
mov al,2 ;3列*每列2个字节
mul dl
add bp,ax
;mov bp,160*8+3*2 ;每行160*8行+3列*每列2个字节,160*8+3*2=0506h
mov ax,160
mul si ;si是当前行数
mov di,0 ;设置指向字符串首地址
add bp,ax ;得到当前行的偏移量
while2:
mov ax,[di] ;段地址还是ds
mov es:[bp+di],ax
mov al,cl ;保存cl颜色,因为下面要用cx判断
mov es:[bp+di+1],cl
mov cl,[di]
mov ch,0
jcxz ok
inc di
add bp,1 ;每一个字符向后挪2个字节,其中一个保存颜色。
mov cl,al ;还原颜色
jmp short while2
ok:ret
;防止除法溢出
divdw:
;对高16位000fh进行除法
mov di,ax ;保存低16位ax中的被除数
mov ax,dx ;设被除数低16位为000fh
mov dx,0000h ;设被除数高16位为0
div cx
mov bp,dx ;保存高16位运算余数到bp中
mov bx,1000h ;把65536拆分成1000和10,对ax进行高16位商的乘法
mul bx
mov bx,0010h
mul bx ;低16位默认保存在ax中;高16位默认保存在dx中。
push ax ;压入高16位商的乘法结果的低16位
push dx ;压入高16位商的乘法结果的高16位 ;对低16位进行除法运算
mov ax,bp ;高16位除法的余数,dx中是余数
mov bx,1000h ;把65536拆分成1000和10,进行高16位余数乘法
mul bx
mov bx,0010h
mul bx ;低16位默认保存在ax中;高16位默认保存在dx中。
add ax,di ;把高16位余数的乘法加上低16位
div cx ;相加的结果除以cx,算出低16位结果
mov cx,dx
;合并结果。高16位结果在dx中;低16位结果在ax中;余数在cx中
pop dx;弹出高16位结果dx
pop bx ;弹出低16位结果ax
add ax,bx
ret
codesg ends
end start
==============================================================================
第17章 检测点17.1
==============================================================================
答:一定有设置IF=1的指令,这种说法是正确的!请参见262页 ===============================================================================
第17章 应用int 13h对软盘进行写cmos 时间
===============================================================================
assume cs:code,ds:data
data segment
dw 0,2,4,7,8,9
data ends
code segment
start:mov si,data
mov ds,si
mov si,0
mov dx,70h
mov cx,6
s:mov al,[si]
out dx,al
in al,71h
push ax
add si,2
loop s
mov ax,0b800h
mov ds,ax
mov dh,0 ;行号
mov dl,0 ;列号
mov cl,2 ;颜色
mov ax,160
mul dh
mov bx,ax
mov ax,2
mul dl
add bx,ax
mov si,0
mov cx,2
s1:pop ax ;写年、月
mov di,cx ;保存循环次数
call getNum
mov byte ptr [bx],ah
mov cl,2
mov [bx+1],cl
mov byte ptr [bx+2],al
mov [bx+3],cl
mov byte ptr [bx+4],"/"
mov [bx+5],cl
add bx,6
mov cx,di
loop s1 pop ax ;写日
call getNum
mov byte ptr [bx],ah
mov cl,2
mov [bx+1],cl
mov byte ptr [bx+2],al
mov [bx+3],cl
add bx,6 ;空格
s2:pop ax ;写时、分
mov di,cx ;保存循环次数
call getNum
mov byte ptr [bx],ah
mov cl,2
mov [bx+1],cl
mov byte ptr [bx+2],al
mov [bx+3],cl
mov byte ptr [bx+4],":"
mov [bx+5],cl
add bx,6
mov cx,di
loop s2
pop ax ;写秒
call getNum
mov byte ptr [bx],ah
mov cl,2
mov [bx+1],cl
mov byte ptr [bx+2],al
mov [bx+3],cl
call ReadFloppy
mov ax,4c00h
int 21h
getNum:mov cl,4
mov ah,al
shr ah,cl
and al,00001111b
add ah,30h
add al,30h
ret ReadFloppy: mov ax,0b800h
mov es,ax
mov bx,0
mov al,1
mov ch,0
mov cl,1
mov dl,0
mov dh,0
mov ah,3
int 13h
ret
code ends
end start
===============================================================================
第17章 应用int 13h对软盘进行读
===============================================================================
assume cs:code
code segment
start: mov ax,0b800h
mov es,ax
mov bx,0
mov al,8
mov ch,0
mov cl,1
mov dl,0
mov dh,0
mov ah,2
int 13h
mov ax,4c00h
int 21h
code ends
end start ===============================================================================
第17章 实验17----用磁道向软盘写操作
===============================================================================
assume cs:code
data segment
db 'welcome to masm!',0
data ends
code segment
start: mov ax,cs
mov ds,ax
mov si,offset show_str
mov ax,0
mov es,ax
mov di,200h
mov cx,offset breakEnd-offset show_str
cld
rep movsb
mov word ptr es:[7ch*4],200h ;es段地址为0
mov word ptr es:[7ch*4+2],0
mov dh,10
mov dl,10
mov cl,2
mov ax,data
mov ds,ax
mov si,0
int 7ch
;call show_str
call ReadFloppy
mov ax,4c00h
int 21h
show_str: mov ax,0b800h
mov es,ax
mov al,160
mul dh ;每行160*8行
mov bp,ax
mov al,2 ;3列*每列2个字节
mul dl
add bp,ax
;mov bp,160*8+3*2 ;每行160*8行+3列*每列2个字节,160*8+3*2=0506h
while:mov ah,0
mov al,2 ;每一个字符向后挪2个字节
mul si ;因为字符串id在bx中的低位记录
mov di,ax
mov ax,[si]
mov es:[bp+di],ax
mov al,cl
mov es:[bp+di+1],cl
mov cl,[si]
mov ch,0
jcxz ok
inc si
mov cl,al
jmp short while
ok:iret
breakEnd:nop
ReadFloppy: mov ax,0b800h
mov es,ax
mov bx,0
mov al,8
mov ch,0
mov cl,1
mov dl,0
mov dh,0
mov ah,3
int 13h
ret code ends
end start ===============================================================================
第17章 实验17----用磁道向软盘读操作
===============================================================================
assume cs:code
code segment
;安装中断向量7ch处理程
start:mov ax,cs
mov ds,ax
mov si,offset breakoff
mov ax,0
mov es,ax
mov di,200h
mov cx,offset endOff-offset breakOff
cld
rep movsb
mov word ptr es:[7ch*4],200h ;es段地址为0
mov word ptr es:[7ch*4+2],0
;正式处理程序
mov ax,0b800h
mov es,ax
mov bx,0
mov ah,0 ;ah=0读软驱,ah=1写软驱
mov al,8 ;操作8个扇区
mov bx,2 ;逻辑扇区号
int 7ch ;用中断向量程序7ch代替loop
mov ax,4c00h
int 21h
breakOff:push ax
push bx ;保存写入读取数据地址
;取商
mov ax,bx ;逻辑扇区号给ax,准备除法
mov si,1440
call int0 ;求面号
mov dh,dl ;低位挪高位(得到面号赋给dh),ax是余数、dx是商。
mov si,18
call int0 ;ax/18求磁道号
mov cl,al ;余数(得到扇区号)
mov ch,al ;商(得到磁道号)
add cl,1 ;扇区号+1
pop bx
pop ax
cmp ah,1 ;检查写操作
je add1
cmp ah,0 ;检查读操作
je add2
ok:mov si,0b800h
mov es,si
mov bx,0
mov dl,0
int 13h ;操作磁盘
iret
;除法(dx,ax用来做被除数)
int0:mov dx,0 ;被除数高位。
div si ;si用来做除数(ax中放结果中的商,dx中放结果中的余数 )
ret
add1:mov ah,3 ;写软盘
jmp ok
add2:mov ah,2 ;读软盘
jmp ok
endOff:nop ;breakOff结束的标记。
code ends
end start ===============================================================================
第17章 课程设计2---未写入软盘
===============================================================================
课程设计2未能完全达到书上要求,在此抛砖引玉希望广大网友共同完善。 assume cs:code,ds:data
data segment
dw 0,2,4,7,8,9
db 128 dup (0)
data ends
data2 segment
dw 9,8,7,4,2,0
data2 ends
code segment
s0 db '1) reset pc ','$'
s1 db '2) start system ','$'
s2 db '3) clock ','$'
s3 db '4) set clock ','$'
s dw offset s0,offset s1,offset s2,offset s3
start:mov ax,code
mov ds,ax
show0:mov si,offset s ;ds dx显示字符串开始坐标。
mov bh,0 ;第0页
mov dh,2 ;行号
mov dl,6 ;列号
;----------显示4条选项------------------------------------
mov cx,4
show1:mov ah,2
int 10h ;设置光标
mov di,dx ;保存行号和列号。
mov dx,[si] ;显示字符串位置。
mov ah,9
int 21h ;显示行中第一条字符串
mov dx,di
inc dh
add si,2 ;为下一个循环显示data中字符串作准备。
loop show1
;------------显示4条选项结束--------------------------------
mov ah,0
int 16h
mov bx,data ;保存显示主菜单地址
mov es,bx
mov bx,16
mov word ptr es:[bx],0ffffh
mov word ptr es:[bx+2],0
cmp al,'1'
je reset
mov bx,data ;保存显示主菜单地址
mov es,bx
mov bx,16
mov word ptr es:[bx],7c00h
mov word ptr es:[bx+2],0
cmp al,'2'
je startSystem
cmp al,'4'
je setSystemClock
cmp al,'3'
je clock
mov ax,4c00h
int 21h
;重起
reset:mov ax,data
mov es,ax
jmp dword ptr es:[16]
;进入硬盘操作系统
startSystem:mov ax,0
mov es,ax
mov bx,7c00h ;读到内存中的地址。
mov dl,0080h
mov ah,2 ;读磁盘操作
mov dh,0 ;0盘面
mov ch,0 ;0磁道
mov cl,1 ;1扇区
mov al,1 ;只读一个扇区
int 13h
call reset
;----------显示更改CMOS时间用户输入提示-----------------------------
setSystemClock:jmp short dostart
db "5) Chang CMOS Clock,format si yy/mm/dd hh:nn:ss ",'$'
dostart:call clearscreen ;清屏
mov al,0
mov ah,2 ;设置光标
mov bh,0
mov dh,2
mov dl,2
int 10h
mov si,offset setSystemClock
mov ax,cs
mov ds,ax
add si,2
mov dx,si
mov ah,9
int 21h
call getstr ;调用让用户输入日期
;---显示CMOS时间--------------------------------
clock: mov cx,1000
showstart:push cx
call delay
call showTime
pop cx
loop showstart
ret showTime:mov si,data
mov ds,si
mov si,0
mov dx,70h
mov cx,6
ss0:mov al,[si]
out dx,al
in al,71h
push ax
add si,2
loop ss0
mov ax,0b800h
mov ds,ax
mov dh,0 ;行号
mov dl,0 ;列号
mov cl,2 ;颜色
mov ax,160
mul dh
mov bx,ax
mov ax,2
mul dl
add bx,ax
mov si,0
mov cx,2
ss1:pop ax ;写年、月
mov di,cx ;保存循环次数
call getNum
mov byte ptr [bx],ah
mov cl,2
mov [bx+1],cl
mov byte ptr [bx+2],al
mov [bx+3],cl
mov byte ptr [bx+4],"/"
mov [bx+5],cl
add bx,6
mov cx,di
loop ss1 pop ax ;写日
call getNum
mov byte ptr [bx],ah
mov cl,2
mov [bx+1],cl
mov byte ptr [bx+2],al
mov [bx+3],cl
add bx,6 ;空格
ss2:pop ax ;写时、分
mov di,cx ;保存循环次数
call getNum
mov byte ptr [bx],ah
mov cl,2
mov [bx+1],cl
mov byte ptr [bx+2],al
mov [bx+3],cl
mov byte ptr [bx+4],":"
mov [bx+5],cl
add bx,6
mov cx,di
loop ss2
pop ax ;写秒
call getNum
mov byte ptr [bx],ah
mov cl,2
mov [bx+1],cl
mov byte ptr [bx+2],al
mov [bx+3],cl
ret
getNum:mov cl,4
mov ah,al
shr ah,cl
and al,00001111b
add ah,30h
add al,30h
ret
;延时
delay:push ax
push dx
mov dx,1000h
mov ax,0
sss1:sub ax,1
sbb dx,0
cmp ax,0
jne sss1
cmp dx,0
jne sss1
pop dx
pop ax
ret
;------开始让用户输入日期----------------------------
getstr: push ax
getstrs: mov ah,0
int 16h
cmp al,20h
jb nochar
mov ah,0
call charstack
mov ah,2
call charstack
jmp getstrs
nochar: cmp ah,0eh ;如果是退格键
je backspace
cmp ah,1ch ;如果是回车键
je enter
backspace: mov ah,1
call charstack
mov ah,2
call charstack
jmp getstrs
enter: mov al,0 ;回车时把al中的0压入栈
mov ah,0
call charstack
mov ah,2
call charstack
call ChangTime ;调用改变CMOS时间函数
call clearscreen ;清屏
pop ax
jmp far ptr show0
charstack: jmp charstart
table dw charpush,charpop,charshow
top dw 0 ;栈的当前位置的公共变量。
array: db 60 dup (0)
charstart: push bx
push dx
push di
push es
cmp ah,2
ja sret
mov bl,ah ;ah为暗号
mov bh,0
add bx,bx
jmp word ptr table[bx]
charpush: mov bx,top
mov si,offset array
mov cs:[si+bx],al
inc top
jmp sret
charpop: cmp top,0
je sret
dec top
mov bx,top
mov si,offset array
mov al,cs:[si+bx]
jmp sret
charshow: mov dh,6
mov dl,6
mov bx,0b800h
mov es,bx
mov al,160
mov ah,0
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov bx,0 ;从头把栈中的数显示一遍。
charshows: cmp bx,top ;查看栈中是否有数据。
jne noempty
mov byte ptr es:[di],' '
jmp sret
noempty: mov si,offset array
mov al,cs:[si+bx]
mov es:[di],al
mov byte ptr es:[di+2],' '
inc bx
add di,2
jmp charshows
sret: pop es
pop di
pop dx
pop bx
ret
;-----用户输入日期结束-------------------------
;-----更改CMOS中的时间-------------------------
ChangTime: push bx
push dx
push di
push es
cmp bp,18 ;如果长度不等于18就退出,不改CMOS
jne EndReturn
changclock: mov si,offset array ;得到栈坐标
mov bp,0
mov bx,data2
mov di,0
mov cx,6
changloop: mov dx,70h
mov al,[bx+di]
out dx,al
mov dx,71h
mov ax,cs:[si+bp] ;得到年在al
push cx ;保护cx
mov cl,4
shl ah,cl ;把年的十位移到高4位
pop cx
and al,00001111b ;把年的个位高4位清0
or al,ah ;把一个完整的年分合并到al一个字节中
out dx,al ;把年写入CMOS
inc bp
add di,2
loop changloop
EndReturn: pop es
pop di
pop dx
pop bx
ret
;-----更改时间结束-----------------------------
;清空屏幕。
clearscreen: push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
subls: mov byte ptr es:[bx],' '
add bx,2
loop subls
pop es
pop cx
pop bx
ret
endsetup:nop
code ends
end start