DAY 0x06

Makefile

汇编

关于调试

可以在汇编中混入INT 3指令来断点调试,但是在中断向量表未准备好时,不能使用该方式 但是在使用bochsdbg时,可以在汇编中参入MAGIC BREAKPOINT,具体步骤是在bochs配置文件中加入magic_break: enabled=1,然后在汇编中加入xchg bx,bx,然后就能在该处断点

load_gdtr

_load_gdtr函数先取出第1个参数limit,地址为ESP+4,

		MOV		AX,[ESP+4]		; limit

这是一个2字节指令,而因为之前分析过这个机器是小端模式,因此对于0x0000ffff,WORD [ESP+4]就是0xffff,把它放到了AX寄存器,然后

		MOV		[ESP+6],AX

0xffff放到了更高的两个byte上面,而ESP+8则是第二个参数addr的地址,这样一来,limit的低2字节和addr就连起来了,之后

		LGDT	[ESP+6]

直接取了ESP+6为低位的6个byte的数据,放到GDTR寄存器, 这就是书上说的GDTR的6个字节的来源,低2个字节是limit,高4字节是addr

GDT的访问权属性

段号记录表中的项中的段属性中有一个Gbit位, 当该位为1时,记录的limit的单位不是byte而是页的大小,一页是指4KB

段的访问权属性ar(access_right),由8位+4位扩展组成,高4位扩展为GD00,其含义为:

低八位的部分组合的含义

00000000(0x00):未使用的记录表(descriptor table)。
10010010(0x92):系统专用,可读写的段。不可执行。
10011010(0x9a):系统专用,可执行的段。可读不可写。
11110010(0xf2):应用程序用,可读写的段。不可执行。
11111010(0xfa):应用程序用,可执行的段。可读不可写。

x86的处理器通过ring0到ring4四个级别来进行访问控制 系统模式(ring0)和应用模式(ring3)取决于运行中的程序代码所在的段的访问权限属性低8位是0x9a还是0xfa

PIC(Programmable interrupt controller)可编程中断控制器

用于将8个中断信号集合成一个中断信号 每个PIC上面可以接收8个中断信号,主板上一共有两个PIC,一共有15个可用的中断信号,IRQ2被用于连接从PIC

中断号码表

IRQ0 	计时器
IRQ1 	键盘
IRQ2 	用于与从站级联
IRQ3 	串口(COM2)
IRQ4 	串口(COM1)
IRQ5 	主要用于ISA / PCI扩展设备
IRQ6 	FDC
IRQ7 	并行端口
IRQ8 	RTC
IRQ9 	主要用于ISA / PCI扩展设备
IRQ10 	主要用于ISA / PCI扩展设备
IRQ12 	鼠标
IRQ13 	FPU(?)
IRQ14 	ATA-0
IRQ15 	ATA-1

PIC内部有多个寄存器:

CPU有一根中断型号,由IF中断许可标志位标志标识是否接受外部中断(1表示接受,STL指令置1,CTL指令置0),而PIC可以对它导出的一共8个RIQ端口分别控制是否接受中断

DAY 0x07

中断处理

io_out8(PIC0_OCW2, 0x61);// 0x61=0x60+0x01,表示已经处理IRQ1上的中断

键盘触发的中断会在键盘按下和松开的时候都触发一次

根据CPU的规范,机器语言的STI指令之后,如果紧跟着HLT指令,那么就暂不受理这两条指令之间的中断,而要等到HLT指令之后才受理

关于C++

C++静态局部变量对于基本类型的常量初始化时,采取直接定义一个隐藏的全局变量的方法,例如对于函数:

int ofEndLine(){
	static int i = 1;
	i++;
	return i;
}

其汇编为 用常量初始化静态局部变量 而对于需要调用函数来进行初始化的静态局部变量,

int ofEndLine() {
	static int i = getValue();
	i++;
	return i;
}

则是 用函数初始化静态局部变量 这其中就用到了___cxa_guard_acquire___cxa_guard_release

DAY 0x08

每组中,第一个字节的高4位是对移动有反应的部分(在[0,3]的范围内),低4位是对点击有反应的部分(在[8,f]的范围内)

76543210
000上移右移1
100下移左移1右键中键(按下)左键
第二个字节和左右移动有关
第三个字节和上下移动有关
鼠标与屏幕的y方向正好相反,因此y使用前应该加负号

asmhead.nas 之后所做的事情

汇编

引用