汇编语言笔记课程设计2

汇编语言笔记课程设计2

0x00 任务一

QQ截图20200612220449

QQ截图20200612220456

​ 思路 我们程序分为两部分 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

QQ截图20200612220254

​ 上述代码成功运行,花了近一天半时间,终于把启动过程和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

QQ截图20200613114112

QQ截图20200613114133

​ 上述代码实现了功能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

开机启动图

​ 开机启动界面

QQ截图20200613192218

​ 按2后引导c盘mbr启动c盘os

QQ截图20200613192230

​ 按3进入时钟界面

QQ截图20200613193044

​ 时钟不断刷新(但是好像变得很快,实际上不到1s就 秒数就加1,不可能是代码问题,我只负责读,又没有修改过,毕竟分钟数的变化和秒对的上)

QQ截图20200613192610

​ 按f1改变颜色