您的位置:首页 > 其它

《汇编语言》课程设计

2014-02-25 10:17 127 查看
[b]一、目的[/b]

知行合一,就是说学以致用。《汇编语言》这本书从13年春节开始看,中间由于众多事物中断,知道14年春节才看完。但是,百看不如一练,借着刚看完书,对汇编语言还很热的感觉,决定对书中最后的课程设计冲刺一下,作为这本书的结业课。

[b]二、课程设计内容[/b]

[b]1、题目[/b]

阅读下面的材料:

开机后,CPU自动进入到FFFF:0单元处执行,此处有一条跳转指令。CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。

初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。

硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。

如果设为从软盘启动操作系统,则int 19h将主要完成以下工作。

(1)控制0号软驱,读取软盘0道0面1扇区的内容到0:7c00;

(2)将CS:IP指向0:7c00。

软盘的0道0面1扇区中装有操作系统引导程序。int 19h将其装到0:7c00处后,设置CPU从0:7c00开始执行此处的引导程序,操作系统被激活,控制计算机。

如果在0号软驱中没有软盘,或发生软盘I/O错误,则int 19h将主要完成以下工作。

(1)读取硬盘C的0道0面1扇区的内容到0:7c00;

(2)将CS:IP指向0:7c00。

这次课程设计的任务是编写一个可以自行启动的计算机,不需要在现有操作系统环境中运行的程序。

该程序的功能如下:

(1)列出功能选项,让用户通过键盘进行选择,界面如下

1) reset pc ;重新启动计算机

2) start system ;引导现有的操作系统

3) clock ;进入时钟程序

4) set clock ;设置时间

(2)用户输入"1"后重新启动计算机(提示:考虑ffff:0单元)

(3)用户输入"2"后引导现有的操作系统(提示:考虑硬盘C的0道0面1扇区)。

(4)用户输入"3"后,执行动态显示当前日期、时间的程序。

显示格式如下:年/月/日 时:分:秒

进入此项功能后,一直动态显示当前的时间,在屏幕上将出现时间按秒变化的效果(提示: 循环读取CMOS)。

当按下F1键后,改变显示颜色;按下Esc键后,返回到主选单(提示:利用键盘中断)。

(5)用户输入"4"后可更改当前的日期、时间,更改后返回到主选单(提示:输入字符串)。

[b]2、程序设计思路 [/b]

将安装程序分为三个段,

1、第一个段为安装程序,负责将第二个段写入第一扇区,第三个段写入2-11扇区;

2、第二个段是主引导程序,存在于软盘第一扇区,由BIOS的19h中断读取到0:7c00开始的内存单元中,并执行0:7c00的第一行代码。这一段的任务是将软盘2-11扇区的数据读入内存,并执行。(这里读入到了2000h:0h开始的内存中)

3、第三个段是系统程序,存放所有引导所需的程序和子程序

3、程序实现功能

程序实现的功能有:

1) reset pc ;重新启动计算机

2) start system ;引导现有的操作系统

3) clock ;进入时钟程序

4[b]、实现程序 [/b]

;========================================================
;段代码功能:加载codesg段到2000h:7f00h位置处,并且将cs:ip
;设定到2000h:7f02处去执行,以测试codesg段是否是真正意义的
;位置无关代码
;========================================================
assume cs:setupsg,ss:stack
stack segment
db 128 dup(0)
stack ends

setupsg segment
start:
mov ax,stack
mov ss,ax
mov sp,128

mov ax,codesg
mov ds,ax
mov si,0 ;设置ds:si指向源地址

mov ax,2000h
mov es,ax
mov di,7f00h ;设置es:di指向目标地址
mov cx,offset codesgend-offset codesgstart+2
cld
rep movsb

mov ax,2000h
push ax
mov ax,7f02h ;codesg段的第一条地址是偏移量为2的地方
push ax
retf

setupsg ends

;========================================================
;段代码功能:sum单元加1
;========================================================
assume cs:codesg
codesg segment
sum dw 0
codesgstart:
call getip ;获得下一条指令的运行地址
pos:
mov bx,ax
mov ax,offset pos
sub bx,ax    ;获得sum的真实物理地址

mov ax,cs
mov ds,ax
inc word ptr ds:[bx]

mov ax,4c00h
int 21h

;========================================================
;函数功能:获得当前的IP,也即下一条指令的地址
;函数返回:ax
;========================================================
getip:
push bx
mov ax,ss
mov ds,ax
mov bx,sp
mov ax,ds:[bx+2]
pop bx
ret

codesgend:
nop
codesg ends
end start


View Code
(3)本课程设计程序中遇到的位置有关代码问题

程序一开始没有mainshell段,这部分代码紧随initsg段。编译好后,被写入到了虚拟镜像。等于说是,虚拟镜像上的程序就只有一个代码段。开机时,虚拟镜像的程序被加载到了0h:7c00h出去执行。但是initsg段在编译后的段首址的IP值为0。程序不能正常运行。

解决办法就是设置两个段,一个是mainshell段,是真正的代码段,这个段含有位置有关代码,必须放在IP为0的位置处运行。一个是initsg段,负责将mainshelll段搬运到2000h:0h处,并且设置cs:ip到该处去运行,这个段是位置无关代码。

(4)如何设计位置无关代码的程序

位置无关代码的程序必须不能使用绝对地址,而要使用相对地址。相对跳转就是为设计位置无关代码来服务的。

我认为,x86汇编指令用cs:ip这样的指令指针(pc)方式,引入代码段的概念,也就是为设计位置无关代码考虑的。

[b]2、中断程序不能随意返回[/b]

中断返回的地址不能随意更改,必须是从哪里断的返回到哪里。

因为,假设从调用了n次“call 标号”后的子程序中断的,而更改了返回地址跳到别处去。这个时候,即使中断程序写的很好,保证了进入和出去中断时sp的不变(堆栈的不变)。但是,由于返回的不是原断点处,就有很大的可能堆栈不能完全恢复(因为还需要n次ret指令来恢复中断),导致错误。

[b]3、堆栈设置问题[/b]

这个课程设计程序的堆栈是不需要我们来设置的,因为BIOS在启动的时候已经设置过了。倘若,我们重新指定堆栈的位置,就有可能导致错乱。

堆栈的使用必须小心,保证进出函数时堆栈的不变。因为堆栈里边存放了寄存器的值,变量的值,还有返回地址,所以必须小心。

参考资料:王爽汇编语言课程设计2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: