汇编语言笔记课程设计2
汇编语言笔记课程设计2
0x00 任务一
思路 我们程序分为两部分 1 安装程序 2执行程序,执行程序负责实现上面功能,安装程序负责把执行程序放到盘符为a的软盘的mbr里(也就是0号扇区,chs就是0磁头0磁道1扇区),让后把bios启动顺序设置a盘位启动盘,这样我们的程序才会开机运行。
值得注意的是,开机后bios先执行,然后把我们的执行程序读入0:7c00处,执行程序要想再引导c盘的mbr进而引导操作系统,必须仍然把c盘的mbr放到0:7c00处才能正确执行(可能是mbr里的代码有硬编码,反正我试过放在内存其他地方执行后引导不了操作系统)。所以我们的执行程序要把自己挪到其他地方,比如0:7d00处,然后要引导操作系统的时候就把c盘mbr读到0:7c00,其余功能比较简单,下面给出我们的执行程序引导c盘操作系统的代码:
assume cs:code
code segment
install:mov ax,cs
mov ds,ax
mov si,offset task-offset install+7c00h
mov ax,cs
mov es,ax
mov di,7e00h
mov cx,512
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[200h],7e00h
mov word ptr es:[202h],0
jmp dword ptr es:[200h];以上部分负责把执行程序挪到7e00
task: jmp short tts
str1: db 'other os in c: will be loaded',0
tts: mov ax,cs
mov ds,ax
mov si,offset str1-offset task+7c00h
mov ax,0b800h
mov es,ax
mov di,2000
s: mov al,ds:[si]
cmp al,0
je fin
mov byte ptr es:[di],al
mov byte ptr es:[di+1],2
inc si
add di,2
jmp short s
fin: mov ax,0
mov es,ax
mov bx,7c00h
mov ah,2
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,80h
int 13h
mov ax,0
mov ds,ax
mov si,200h
mov word ptr ds:[si],7c00h
mov word ptr ds:[si+2],0
jmp dword ptr ds:[si];以上部分正真的引导程序
start: mov ax,cs
mov es,ax
mov word ptr es:[1feh],0aa55h
mov bx,0
mov ah,3
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,0
int 13h
mov ax,0
mov es,ax
mov bx,200h
mov ah,2
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,0
int 13h
mov ax,4c00h
int 21h;安装程序
code ends
end start
上述代码成功运行,花了近一天半时间,终于把启动过程和bochs的使用搞清楚了,主要就是c盘mbr里的引导代码必须要在0:7c00处运行这一点坑
//2020-6-13日 更新
assume cs:code
code segment
install:mov ax,cs
mov ds,ax
mov si,offset task-offset install+7c00h
mov ax,cs
mov es,ax
mov di,7e00h
mov cx,512
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[200h],7e00h
mov word ptr es:[202h],0
jmp dword ptr es:[200h];以上部分负责把执行程序task挪到7e00
task: jmp short main;程序开始的地方
str0: db '1)reset pc',0
str1: db '2)start system',0
str2: db '3)clock',0
str3: db '4)set clock',0
addr: dw offset str0,offset str1,offset str2,offset str3
fun: dw offset reset,offset load
main: call clear
mov dh,10
mov dl,37
mov ax,cs
mov ds,ax
mov cx,4
mov di,0
mai_s0: mov si,offset addr-offset task+7e00h
add si,di
mov si,ds:[si]
sub si,offset task
add si,7e00h
push cx
mov cl,2
call print
pop cx
add di,2
add dh,2
loop mai_s0
mai_s1: mov ah,0
int 16h
mov bx,0b800h
mov es,bx
mov byte ptr es:[3840],al
mov byte ptr es:[3841],4
cmp al,31h
jb mai_s1
cmp al,32h
ja mai_s1
sub al,31h
add al,al
mov ah,0
mov si,offset fun-offset task+7e00h
add si,ax
mov si,cs:[si]
sub si,offset task
add si,7e00h
jmp si
clear: push ax;函数clear 无参数 无返回值 清屏
push cx
push es
push si
mov ax,0b800h
mov es,ax
mov si,0
mov cx,2000
cle_s: mov byte ptr es:[si],0
add si,2
loop cle_s
pop si
pop es
pop cx
pop ax
ret
print: push ax;函数print dh 行 dl列 cl颜色 ds:si 字符串首地址,无返回值
push dx
push es
push si
push di
mov ax,0b800h
mov es,ax
mov al,160
mul dh;
add dl,dl
mov dh,0
add ax,dx
mov di,ax;di为显示文字偏移地址
pri_s: mov al,ds:[si]
cmp al,0
je pri_e
mov es:[di],al
mov byte ptr es:[di+1],cl
inc si
add di,2
jmp short pri_s
pri_e: pop di
pop si
pop es
pop dx
pop ax
ret
reset: call clear
mov ax,0b800h
mov es,ax
mov cx,5
res_s:mov ax,0
mov ds,ax
mov word ptr ds:[200h],0
mov word ptr ds:[202h],0ffffh
jmp dword ptr ds:[200h]
load: call clear
mov ax,0b800h
mov es,ax
mov cx,5
loa_s:mov ax,0
mov es,ax
mov bx,7c00h
mov ah,2
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,80h
int 13h
mov ax,0
mov ds,ax
mov si,200h
mov word ptr ds:[si],7c00h
mov word ptr ds:[si+2],0
jmp dword ptr ds:[si];以上部分正真的引导程序
start: mov ax,cs
mov es,ax
mov word ptr es:[1feh],0aa55h
mov bx,0
mov ah,3
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,0
int 13h
mov ax,0
mov es,ax
mov bx,200h
mov ah,2
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,0
int 13h
mov ax,4c00h
int 21h
code ends
end start
上述代码实现了功能1 2,受限于一个扇区512k的限制,3 4功能放不下,要放到2扇区,用时读入内存,下午完成
//2020-6-13晚更新,实现 1,2,3功能,4功能难度不大,不准备实现了,下面是代码和效果图:
assume cs:code
code segment
;------------------------------------------
;------------------------------------------
;------------------------------------------
task: jmp short main;程序开始的地方
str0: db '1)reset pc',0
str1: db '2)start system',0
str2: db '3)clock',0
str3: db '4)set clock',0
addr: dw offset str0,offset str1,offset str2,offset str3
t_add: db 9,8,7,4,2,0
t_str: db 0,0,'/',0,0,'/',0,0,' ',0,0,':',0,0,':',0,0,0
fun: dw offset reset,offset load,offset clock
main: call clear
mov dh,10
mov dl,32
mov ax,cs
mov ds,ax
mov cx,4
mov di,0
mai_s0: mov si,offset addr-offset task+7e00h
add si,di
mov si,ds:[si]
sub si,offset task
add si,7e00h
push cx
mov cl,2
call print
pop cx
add di,2
add dh,2
loop mai_s0
mai_s1: mov ah,0
int 16h
mov bx,0b800h
mov es,bx
mov byte ptr es:[3840],al
mov byte ptr es:[3841],4
cmp al,31h
jb mai_s1
cmp al,33h
ja mai_s1
sub al,31h
add al,al
mov ah,0
mov si,offset fun-offset task+7e00h
add si,ax
mov si,cs:[si]
sub si,offset task
add si,7e00h
jmp si;段间跳转,跳到对应的功能
;------------------------------------------
clear: push ax;函数clear 无参数 无返回值 清屏
push cx
push es
push si
mov ax,0b800h
mov es,ax
mov si,0
mov cx,2000
cle_s: mov byte ptr es:[si],0
mov byte ptr es:[si+1],00000111b;黑底白字
add si,2
loop cle_s
pop si
pop es
pop cx
pop ax
ret
;------------------------------------------
print: push ax;函数print dh 行 dl列 cl颜色 ds:si 字符串首地址,无返回值
push dx
push es
push si
push di
mov ax,0b800h
mov es,ax
mov al,160
mul dh;
add dl,dl
mov dh,0
add ax,dx
mov di,ax;di为显示文字偏移地址
pri_s: mov al,ds:[si]
cmp al,0
je pri_e
mov es:[di],al
and byte ptr es:[di+1],11111000b;前景颜色清空,背景颜色不变
or byte ptr es:[di+1],cl
inc si
add di,2
jmp short pri_s
pri_e: pop di
pop si
pop es
pop dx
pop ax
ret
;------------------------------------------
reset: call clear
mov ax,0b800h
mov es,ax
mov cx,5
res_s:mov ax,0
mov ds,ax
mov word ptr ds:[200h],0
mov word ptr ds:[202h],0ffffh
jmp dword ptr ds:[200h]
;------------------------------------------
load: call clear
mov ax,0b800h
mov es,ax
mov cx,5
loa_s:mov ax,0
mov es,ax
mov bx,7c00h
mov ah,2
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,80h
int 13h
mov ax,0
mov ds,ax
mov si,200h
mov word ptr ds:[si],7c00h
mov word ptr ds:[si+2],0
jmp dword ptr ds:[si];以上部分正真的引导程序
;------------------------------------------
clock: mov ax,0
mov es,ax
cli
mov word ptr es:[9*4],208h
mov word ptr es:[9*4+2],0
sti
call clear
mov cx,6
mov bx,0
clo_s: mov si,offset t_add-offset task+7e00h
add si,bx
mov al,cs:[si]
out 70h,al
in al,71h
mov ah,al
and al,00001111b
push cx
mov cl,4
shr ah,cl
pop cx
add al,30h
add ah,30h
mov dx,bx
add dx,dx
add dx,bx;dx等于三倍bx
mov si,offset t_str-offset task+7e00h
add si,dx
mov byte ptr cs:[si],ah
mov byte ptr cs:[si+1],al;写入一位时间
inc bx
loop clo_s;生成时间字符串
mov dh,14
mov dl,32
mov cl,4
mov ax,cs
mov ds,ax
mov si,offset t_str-offset task+7e00h
call print
cloe: nop
jmp short cloe
;------------------------------------------
;------------------------------------------
;------------------------------------------
;0:204-0:207 储存原来的int 9的中断向量,切勿修改
install:mov ax,0
mov es,ax
mov bx,7e00h
mov ah,2
mov al,1
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 13h
mov ax,cs
mov ds,ax
mov si,offset do9-offset install+7c00h
mov ax,0
mov es,ax
mov di,208h
mov cx,offset do9e-offset do9
cld
rep movsb;将中断处理程序放到0:208h,但不安装
mov ax,es:[9*4]
mov es:[204h],ax
mov ax,es:[9*4+2]
mov es:[206h],ax;将原中断向量放到0:204h
mov ax,0
mov es,ax
mov word ptr es:[200h],7e00h
mov word ptr es:[202h],0
jmp dword ptr es:[200h];以上部分负责把执行程序task挪到7e00
do9: push ax
push bx
push cx
push ds
mov ax,0
mov ds,ax
in al,60h
pushf;标志寄存器入栈
call dword ptr ds:[204h]
cmp al,3bh;f1的扫描码
je change
cmp al,1;esc的扫描码
je dret;中断处理程序放在0:208h 而clock放在0:7e00所以段地址相同
d_fin: pop ds
pop cx
pop bx
pop ax
iret
change: mov ax,0b800h
mov ds,ax
mov cx,2000
mov bx,1
do9_s0: inc byte ptr ds:[bx]
add bx,2
loop do9_s0
jmp short d_fin
dret: cli
mov ax,cs:[204h]
mov cs:[9*4],ax
mov ax,cs:[206h]
mov cs:[9*4+2],ax
sti
mov bx,07e00h
jmp bx
do9e: nop
;------------------------------------------
;------------------------------------------
;------------------------------------------
start: mov ax,cs
mov es,ax
mov si,1feh
add si,offset install
mov word ptr es:[si],0aa55h
mov bx,offset install
mov ah,3
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,0
int 13h;安装mbr程序
mov ax,cs
mov es,ax
mov bx,offset task
mov ah,3
mov al,1
mov ch,0
mov cl,2;放到2扇区
mov dh,0
mov dl,0
int 13h;安装执行程序
mov ax,4c00h
int 21h
code ends
end start
开机启动界面
按2后引导c盘mbr启动c盘os
按3进入时钟界面
时钟不断刷新(但是好像变得很快,实际上不到1s就 秒数就加1,不可能是代码问题,我只负责读,又没有修改过,毕竟分钟数的变化和秒对的上)
按f1改变颜色