今天要做什么?
1:Bochs 汇编 引导程序调试
2:处理器编译问题分析
一:AX、BX、CX、DX、SI、DI、SP、BP、IP
输入 sreg 会显示很多段寄存器的内容
输入 r 显示所有的通用寄存器
单步执行指令:输入框 输入S (step)单步
断点指令:b 所谓断点 这是一个内存地址,当处理器执行到这个地址时,指令停止
例如输入:b 0x7c00 ,到0x7c00 时,指令停止
输入C 时,不间断执行指令,如果我们设置了断点,他就会在断点处停下来
进入调试窗口,查看 段寄存器(输入sreg) 和通用寄存器 输入(r)
输入s单步执行指令 后 执行当前正在等待的指令,然后显示下一次将要执行的指令
这是在rom bos区间中调试,
设置断点 b 0x7c00
会执行到0x7c00处
目前正在等待执行的指令是 mov ax,0x0030,将30传送给ax
然后s 单步执行
在输入 R,查看通用寄存器
调试完后
输入q 结束本次提调试
二:
问题检测练习 测试
1:硬盘的磁头盘面是从数字 0 开始编号的,每个盘面的磁道是从数字0开始的,每磁道/柱面上的扇区是从数字1 开始编号的,主引导扇区的位置是0面 0道 1扇区
2:
三:
在屏幕上显示文本信息
需要两种硬件,显示器和显卡,
显卡控制显示器的最小单位是像素,如何控制这些像素,显卡都有自己的存储器,因为位于显卡上,所以叫显示存储器。
可以用显存里面的数据控制显卡的亮度和颜色。
早期每个像素由红绿蓝三种颜色组成
现在的液晶显示器是长方形的显示块
三个字节,共同表示一个像素
1111 1111
1111 1111
1111 1111
每个字节的大小,是红绿蓝三颜色的饱和度,三种不同深浅的颜色,就会合成一个具有特定颜色的像素,这是色彩混合的原理,每种都有256种饱和度,三种不同颜色的饱和度来组成不同的颜色
第一个字节,对应于红像素,第二个字节 对应于绿像素,第三个字节对应于蓝像素
不管是显示颜色图片,还是显示文字,对于显示器来说没有什么不同,所有的文字都由像素组成,必须小心细致的显示,区别是组成的内容。
文字的数量是有限的,不像图片千变万化,
有没有一种方法,可以简化文本的显示呢?
有文本模式下的缓存和
图像模式下的缓存
在文本模式下,显存的内容是字符的代码
在图像模式下,显存的内容是像素的颜色
当字符发生器 接收到字符编码的时候,当字符的编码 接收到显存里
接收到e的编码时候,就控制一部分像素,将他显示成字符H的轮廓,为了给出要显示的字符。
为了给出要显示的字符,处理器需要访问显存,把字符的编码写进去,显存是位于显卡上的,访问显存需要通过显卡。
为此,计算机系统的设计者们,决定把显存映射到处理器可以直接访问的地址空间中,
如图所示,我们知道8086 一次可以访问 一兆字节的内存
从00000 到A0000 结束的这一部分,是常规的部分,是由内存条来提供的
从F0000 到FFFFF 是 64KB的ROM-BIOS
从F0000 到A0000 传统上,是外部设备区间,其中就包括显卡部分,显示很重要啊
所有在个人计算机上使用的显卡,在加电自检之后,都会把自己加载到80*25的文本模式,屏幕上显示25行,每行80个字符,所以叫做80*25的文本模式,这样的话,总共可以显示2000个字符 ,从B8000 到BFFFF,是留给显卡的,是由显卡来提供的,是将显卡上的显存映射过来的。
四:在屏幕上显示文本信息 和 准备工作
使用逻辑地址来访问显存: 段地址范围是
B800:0000 - B800:7FFF
B8000-BFFFF
写汇编文件
英特尔的处理器不允许将一个立即数 传送给段寄存器。
支持的两种写法格式
Mov 段寄存器, 通用寄存器 mov ds,ax
Mov ds,bx
Mov ds,cx
Mov 段寄存器,[内存地址] mov es,[0x6c](从内存中取出16位长的数据传送给es)
我们知道文字信息是以数字的形式存储在计算机中,这一点应该是非常容易理解的,问题在于 用哪个数字 来代表哪个字符呢
需要一个编码标准
ASCII字符集1967年刚出来的时候 是128个字符
空格 是 20
! 是 数字字符 21,以此类推
第一个字节是字符的ASCII编码,第二个是字符的属性,包括颜色底色和背景色,以及显存,以及显示器
前两个字节 对应着字符左上角的第一个字符位置,在文本模式下的显存中,前两个字节合起来
字符编码0x48,字符属性 0x07,每一个都有 背景色K RGB和前景色I RGB组成:
背景色中有K位,K位是闪烁位,当K是0的时候,意味着背景不闪烁,当K是1的时候,意味着K是闪烁的。
前景色中有I位,如果I这一位是0,意味着是正常亮度,如果I这一位是1,意味着高亮,亮度不同,也会影响颜色的效果
低四位是前景色(第一个是i位),高四位是背景色(第一个是K位)
代码
这个是把段寄存器ds的内容作为段地址,从这里开始
将D800 加上byte 0x00 是B8000
0x41 所占用的空间是16位两个字节,但是只用了其中一部分
Mov al,[0xf000] ; 从偏移F000处取出一个字节,传送到al中
Mov bx,[0x08] ; 传送时,在段寄存器DS中偏移地址0x08中取出一个字,传送到bx
Mov al, 0x07 ; 传送立即数0x07 到al中
Mov [0x0c], dx ;将dx 传送到内存偏移地址位0x0c的位置
Mov [0x2000], ah ;将ah 传送到内存中偏移地址位0x2000的地方,占用一个字节单元
Mov byte [0x02], 0xe9 ;将立即数0xe9 传送到内存中偏移地址为0x02的地方
Mov word [0x02],0xe9;把立即数0xe9传送到内存中 0x02的一个字节单元 ,但是在这个时候,只知道位大小,不知道长度,目标位置只知道位置,不知道长度,使用byte关键字来加以修饰
Mov word [0x06], 0x3c; 将立即数0x3c传送到内存中偏移地址位0x06的地方,在这里 立即数只知道大小,不知道长度,目标位置,只知道位置,不知道长度,使用word 关键字来修饰 使用一个字立即数 传送到 0x06的字单元 ,他是16位的
mov 0x07,al ;Mov指令的目的操作数 不允许是立即数
Mov [0x01],[0x02] ; 不允许两个操作数 都是内存单元,事实上,可以用通用寄存器进行中转。
mov ax, [0x02] ;
Mov [0x01] , ax ;
Mov ip,0xf000指令指针寄存器IP 在指令中是不可直接访问的,不能出现在任何指令中,只能间接的修改,
Mov ds,ax ;如果目标操作数是段寄存器,那么源操作数必须是通用寄存器,或者是内存地址
Mov es,[0x3002] ;目的操作数是段寄存器es,源操作时是内存地址,也是可以的
在这里 仅仅显示了所有指令的机器码,没有汇编指令
不过nasm 可以一起生成一个列表文件,方便进行对照
Nasm exam.asm -l exam.lst
伪指令 db 0x55,0xaa
和 db 0x55,0xaa 是相同的
一个主引导扇区是512个字节,其中最后两个字节是主引导扇区的有效标志,十六进制的0x55和0xaa。所以我们用伪指令db 来定义这两个字节 。
前面是代码,中间是填充的0,后面的是 55 和aa
用times 510-? db 0
所以填充的起始位置是0x5f
用times 510减去0x5f
在asm中 不同的进制可以一起运算,只要他们有明确的标志,意思是16进制或者十进制。
六:使用标号来计算数据和代码的长度
start:
每一个汇编语言第二行的代码是指令
标号 只是标号,没有汇编地址
长度相减 第三种用法
填充别的内容做测试
重新生成bin文件
查看二进制分析后,发现内容总长度没有变化,所以标号
Times 510-(current-start) db 0
式子成立