【实验题目】接管裸机的控制权
【实验目的】学习如何搭建和应用实验环境,编写一个简单的汇编程序,让它接管裸机的控制权
【实验要求】设计IBM_PC的一个引导扇区程序,程序功能是:用字符‘A’从屏幕左边某行位置45度角下斜射出,保持一个可观察的适当速度直线运动,碰到屏幕的边后产生反射,改变方向运动,如此类推,不断运动;在此基础上,增加你的个性扩展,如同时控制两个运动的轨迹,或炫酷动态变色,个性画面,如此等等,自由不限。还要在屏幕某个区域特别的方式显示你的学号姓名等个人信息。将这个程序的机器码放进放进第三张虚拟软盘的首扇区,并用此软盘引导你的XXXPC,直到成功。
【实验方案】
1、虚拟机配置方法
虚拟机采用VMWare Workstation 15 Player(免费版),用它构建一个虚拟机平台. 该虚拟机平台的配置为: 单核单线程 CPU, 4MB 内存, 32MB 硬盘。
2、NASM 汇编工具
NASM 是一个汇编工具, 能将汇编代码编译成对应二进制代码。使用nasm xx.asm –o xx.bin,可将汇编代码转换为二进制代码。
3、WinImage磁盘映像文件浏览编辑工具
创建磁盘映像文件xx.img。
4、WinHex二进制文件编辑工具
可以修改二进制文件。
5、FloppyWrite
FloppyWriter 能将二进制文件一键写入到软盘映像
6、编写汇编代码。
6.1 显存段地址 0B800h, 文本显示的范围为25行(0—19) 80(0—79) 列。为了实现在某个位置显示自己的学号和姓名,使用BIOS的10H调用显示字符串。在此基础上,增加了我的个性扩展,炫酷动态变色,个性画面,代码如下:
xor ax,ax
mov ax, Message
mov bp, ax; ES:BP = 串地址
mov cx, 18; CX = 串长度
mov ax, 01301h; AH = 13(功能号), AL = 01h(1表示光标放在串尾)
mov bx, 0082h; 页号为0(BH = 0) 闪烁绿字
mov dl, 10 ; 列位置
mov dh,10 ;行位置
int 10h; 10h 号中断
6.2 参考老师给的stoneM.asm文件,可以实现用字符‘#’从屏幕左边某行位置45度角下斜射出,保持一个可观察的适当速度直线运动,碰到屏幕的边后产生反射,改变方向运动,如此类推,不断运动。在老师的代码基础上,增加了字符‘#’可以改变颜色的功能
这里只列出show段的代码:
xor ax,ax ; 计算显存地址
mov ax,word[x]
mov bx,80
mul bx
add ax,word[y]
mov bx,2
mul bx
mov bp,ax
mov ah,02h ; 0000:黑底、1111:亮白字(默认值为07h)
mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符)
mov bx,0003h
mov word[gs:bp],ax ; 显示字符的ASCII码值
jmp loop1
6.3为了能够直接使用[内存变量]访问内存, 在汇编代码的开头写 org 7c00h,因为主引导扇区数据为 512 字节,处理器会将主引导扇区的数据 加载到逻辑地址 0x0000:0x7c00 中,然后检测最后两字节是否为 0x55 和 0xAA, 若存在则主引导扇区有效, 以一个段间转移指令 jmp 0x0000:0x7c00 跳到那里继续执行,数据段的位置也要作相应修改。
6.4 主引导区有效标记 55aa,所以要在在汇编代码末尾加入: times 510-(
−
-
−$) db 0 dw 0xaa55
源码:
; 程序源代码(stone.asm)
; 本程序在文本方式显示器上从左边射出一个#号,以45度向右下运动,撞到边框后反射,如此类推.
; NASM汇编格式
Dn_Rt equ 1 ;D-Down,U-Up,R-right,L-Left
Up_Rt equ 2 ;
Up_Lt equ 3 ;
Dn_Lt equ 4 ;
delay equ 50000 ; 计时器延迟计数,用于控制画框的速度
ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度
org 07c00h ; 程序加载到07c00h,可用于生成COM
start:
;xor ax,ax ; AX = 0 程序加载到0000:100h才能正确执行
mov ax,cs
mov es,ax ; ES = 0
mov ds,ax ; DS = CS
mov es,ax ; ES = CS
mov ax,0B800h ; 文本窗口显存起始地址
mov gs,ax ; GS = B800h
mov byte[char],'#'
loop1:
dec word[count] ; 递减计数变量
jnz loop1 ; >0:跳转;
mov word[count],delay
dec word[dcount] ; 递减计数变量
jnz loop1
mov word[count],delay
mov word[dcount],ddelay
mov al,1
cmp al,byte[rdul]
jz DnRt
mov al,2
cmp al,byte[rdul]
jz UpRt
mov al,3
cmp al,byte[rdul]
jz UpLt
mov al,4
cmp al,byte[rdul]
jz DnLt
jmp $
DnRt:
inc word[x]
inc word[y]
mov bx,word[x]
mov ax,25
sub ax,bx
jz dr2ur
mov bx,word[y]
mov ax,79
sub ax,bx
jz dr2dl
jmp show
dr2ur:
mov word[x],23
mov byte[rdul],Up_Rt
jmp show
dr2dl:
mov word[y],77
mov byte[rdul],Dn_Lt
jmp show
UpRt:
dec word[x]
inc word[y]
mov bx,word[y]
mov ax,79
sub ax,bx
jz ur2ul
mov bx,word[x]
mov ax,-1
sub ax,bx
jz ur2dr
jmp show
ur2ul:
mov word[y],77
mov byte[rdul],Up_Lt
jmp show
ur2dr:
mov word[x],1
mov byte[rdul],Dn_Rt
jmp show
UpLt:
dec word[x]
dec word[y]
mov bx,word[x]
mov ax,-1
sub ax,bx
jz ul2dl
mov bx,word[y]
mov ax,-1
sub ax,bx
jz ul2ur
jmp show
ul2dl:
mov word[x],1
mov byte[rdul],Dn_Lt
jmp show
ul2ur:
mov word[y],1
mov byte[rdul],Up_Rt
jmp show
DnLt:
inc word[x]
dec word[y]
mov bx,word[y]
mov ax,-1
sub ax,bx
jz dl2dr
mov bx,word[x]
mov ax,25
sub ax,bx
jz dl2ul
jmp show
dl2dr:
mov word[y],1
mov byte[rdul],Dn_Rt
jmp show
dl2ul:
mov word[x],23
mov byte[rdul],Up_Lt
jmp show
show:
xor ax,ax
mov ax, BootMessage
mov bp, ax; ES:BP = 串地址
mov cx, 18; CX = 串长度
mov ax, 01301h; AH = 13, AL = 01h
mov bx, 0082h; 页号为0(BH = 0) 闪烁绿字(BL = 0Ch,高亮)
mov dl, 10
mov dh,10
int 10h; 10h 号中断
xor ax,ax ; 计算显存地址
mov ax,word[x]
mov bx,80
mul bx
add ax,word[y]
mov bx,2
mul bx
mov bp,ax
mov ah,02h ; 0000:黑底、1111:亮白字(默认值为07h)
mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符)
mov bx,0003h
mov word[gs:bp],ax ; 显示字符的ASCII码值
jmp loop1
end:
jmp $ ; 停止画框,无限循环
datadef:
count dw delay
dcount dw ddelay
rdul db Dn_Rt ; 向右下运动
x dw 0
y dw 0
char db '#'
BootMessage: db "wangyaning17341152"