一、汇编和微机原理
1、section作为梳理程序只用。例如划分data、code段。
2、vstart定义一个虚拟地址。例如:假如程序加载到0x7c00,自己设置vstart=0x7c00,那么message db “Start Boot”,13,10,'$'中message地址是:0x7c10 + 偏移。而不是0x7c00+偏移。所以需要提前知道程序被加载到那个地址,然后vstart设置该地址。
3、ndisasm,反汇编工具
4、vstart=xxxx 和 org xxxx 功能相同,注意:它们不是告诉程序将地址加载到xxxx地址,而只是作为基地址,代码后面的地址以xxxx作为起始地址。
5、编译器只负责编址,它只会将数据相对于文件开头的偏移量作为该数据的地址,全是以0 起始的。
6、CPU与内存执行流程。另外,地址寄存器AR和数据寄存器DR在微处理器的内部总线和外部总线之间,还起着隔离和缓冲的作用。
(1)控制总线控制CPU对内存读或写操作。
(2)操作的内存地址通过地址总线传给存储到AR中。
(3)读时,该内存地址的指令存到DR中,然后通过数据总线传输到CPU内部。写入数据到内存时则相反。
7、指令的执行过程
指令的执行过程可分为取指令、分析指令和执行指令3个步骤。
(1)取指令:控制器将CS:IP的地址送上地址总线,然后通过数据总线取指令,存入指令寄存器IR。
(2)分析指令:指令译码器分析操作码,根据操作码从寄存器或内存(需要读入存储单元再使用)取操作数。
(3)执行指令:控制器向运算单元发出开始运算信号,运算单元执行指令。然后,IP寄存器加上指令大小,指向下一条指令。
另外,一般把计算机完成一条指令所花费的时间称为一个指令周期。指令周期越短,指令执行就越快。
8、段寄存器为16位宽
9、实模式:直接访问物理地址。保护模式:通过虚拟地址访问物理地址。
10、8086CPU的实模式下,因为只有20位宽地址总线,CS16+IP超过0xFFFFF部分,直接去掉。例如:0xFFFF16+0XFFFF=0x10FFEF,那么0x10FFEF只取0xFFEF部分作为地址,称为地址回卷。
11、基址寻址,add word[bx], 0x1234 ”这条指令将 0x1234 加上内存地址 ds: bx 处的值后再存入内存地址 ds: bx 中
12、通过SS:bp的方式把栈作为数据段访问,用途:访问函数参数。
13、执行流入栈顺序:参数(从右到左),放回地址,ebp原值,局部变量。例如:function(int b, int c){int d}
14、16bit模式下,ret从栈顶弹出两字节,存入IP寄存器;retf从栈顶弹出4字节,分别2字节存入CS和IP,先出栈IP,再出栈CS。
15、数据类型伪指令“ word”,这个是用来告诉编译器取2字节的。其他,byte、dword、qword作用相似,只是读写字节数不同。
16、short: 1字节,near: 2字节,far:4字节。常用于call和jmp定义跳转地址范围。如:short跳转地址范围为-128~127,超出会报“error: short ] ump is out of range”错误。
17、jmp:相对短转移、相对近转移、间接绝对近转移、直接绝对远转移、间接绝对远转移。
call :相对近调用、间接绝对近调用、直接绝对远调用、间接绝对远调用
18、下面函数中,jmp short start被编译器编译机器码为ef7f,反汇编为jmp .+127,0x7f=127,所以CPU是用相对地址转移的,然后在CPU内部再计算成绝对地址,对地址=操作数+IP寄存器的值+2,即127+0x900+2=0x981。call也是一样。
19、有条件转移,通过flags寄存器标志条件跳转。
二、IO接口操作
1、CPU和外设通过IO接口连接,IO接口可作为缓冲,信号转换,地址译码电路(选择IO接口中某个外设与CPU通信,使其可访问数据总线)。
2、地址译码电路:(1)地址译码电路用于将输入的地址信号解码成选择线路的控制信号,以控制需要读取或写入的存储单元。
(2)I/O请求线连到地址译码器的使能端,以控制是否要与外设通信;I/O请求线低电平时,译码器允许工作,IO口地址控制接口地址译码器使能那个外设使用数据总线。
3、南桥集成了各种低速要求的IO接口,如时钟,SATA接口,USB接口,PCI接口。可以仲裁那个接口跟CPU通信。
4、南桥芯片选中使用那个IO接口后,通知CPU通过地址译码电路使能该IO接口使用数据总线。
5、访问端口:(1)内存映射(mov操作)。(2)端口号独立编址(in/out操作)
6、in:把指定端口数据写入cpu寄存器。out:把cpu寄存器数据写入指定端口。dx存储端口号,ax存储读写数据。
in ax(or al), dx
out dx, ax(or al)
三、显卡
1、(1)CPU将数据写入内存特定区域,显卡将该区域内存映射到显存。
(2)也有为了加速显存读取数据,将CPU通过地址总线指定显存地址,然后往该地址直接写入数据。
2、在1M内存表中,0xB8000-0xBFFFF作为文本显示区域。往这个内存写入的内容会直接映射到显存。
3、显示器上每个字符占两字节大小
四、代码
1、mbr.asm
;代码以此地址作为偏移地址的基地址
[ORG 0x7c00]
;指定代码段和16bit模式
[SECTION .text]
[BITS 16]
_start:
mov ax,cs ;寄存器清0
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00 ;设置栈寄存器sp,栈地址从上往下存储,恰好0x500~0x7bff是可用区域
mov ax,0xb800 ;设置gs段寄存器地址,gs段寄存器不能直接赋值,只能通过先传给通用寄存器,再传gs寄存器。
mov gs,ax
;int 0x10 相当函数,参数从ax,bx,cx,dx这些寄存器取。清掉BIOS的输出。
mov ax, 0x0600 ;ah=0x06,表示功能号,功能为上卷清屏.al=0x0,表示上卷行数,为0则表示全部
mov bx, 0x0700 ;上卷属性,黑底
mov cx, 0 ;左上角坐标(0, 0)
mov dx, 0x184f ;右下角坐标(24, 79), 0x18=24,0x4f=79
int 0x10 ;0x10中断
;写入1MB内存中,文本显示区域0xb800-0xbffff,显卡会自动在该内存映射到显示器。显示字符需要两个字节,一个保存字符,一个保存字符属性
mov byte [gs:0x00],'M'
mov byte [gs:0x01],0xA4 ;表示绿色背景闪烁,4表示前景色为红色
mov byte [gs:0x02],'B'
mov byte [gs:0x03],0xA4
mov byte [gs:0x04],'R'
mov byte [gs:0x05],0xA4
jmp $ ;在这行的地址处循环跳转,相当于while(1)
times 510-($-$$) db 0 ;一个扇区512字节,减去0xaa55为510字节。($$-$)为上面代码所占用字节数,510-($-$$)为当前行到魔术符字节数。time 字节数 dd 0 : 填充当前字节开始,到字节数为0
dw 0xaa55 ;BIOS程序识别MBR魔术符
2、Makefile
.PHONY:build image clean
obj=mbr.bin
build:
nasm mbr.asm -o $(obj)
image:
dd if=./mbr.bin of=./hd60M.img bs=512 count=1 conv=notrunc
clean:
rm -rf *.img $(obj)
3、运行
(1)code tree
root@intel-S2600IP:~/systemcode/Pinux# tree
.
├── bochsrc
├── Makefile
├── mbr.asm
(2)在bochsrc 文件目录下运行下面命令
root@xian-S2600IP:~/systemcode/Pinux# bochs -qf bochsrc
(3)结果