github
1、介绍
操作系统想要实现键盘写入或者其他硬件的相关操作时,需要用到端口读写。
本节内容较为单一,也没有太多前置知识,主要实现向固定的端口中写入数据以及读取数据。
2、code
新建文件port.h
,port.cpp
我们需要实现8Bit、16Bit以及32Bit数据的读写
首先是port.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #ifndef __PORT_H #define __PORT_H
#include "types.h"
class Port{ protected: uint16_t portnumber; Port(uint16_t portnumber); ~Port(); };
class Port8Bit : public Port { public: Port8Bit(uint16_t portnumber); ~Port8Bit(); virtual void write(uint8_t data); virtual uint8_t read(); };
class Port16Bit : public Port { public: Port16Bit(uint16_t portnumber); ~Port16Bit(); virtual void write(uint16_t data); virtual uint16_t read(); };
class Port32Bit : public Port { public: Port32Bit(uint16_t portnumber); ~Port32Bit(); virtual void write(uint32_t data); virtual uint32_t read(); };
#endif
|
我们首先创建一个port类表示需要写入的端口,端口长度位16Bit,然后使用具体的8Bit,16Bit,32Bit的类继承并实现读写功能。
接下来是实现port.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include "port.h"
Port::Port(uint16_t portnumber) : portnumber(portnumber){}
Port::~Port() {}
Port8Bit::Port8Bit(uint16_t portnumber) : Port(portnumber){}
Port8Bit::~Port8Bit() {}
void Port8Bit::Write(uint8_t data){ __asm__ volatile("outb %0, %1" : : "a" (data), "Nd" (portnumber)); }
uint8_t Port8Bit::Read(){ uint8_t data; __asm__ volatile("inb %1, %0" : "=a" (data) : "Nd" (portnumber)); return data; }
Port16Bit::Port16Bit(uint16_t portnumber) : Port(portnumber){}
Port16Bit::~Port16Bit() {}
void Port16Bit::Write(uint16_t data){ __asm__ volatile("outw %0, %1" : : "a" (data) , "Nd" (portnumber)); }
uint16_t Port16Bit::Read(){ uint16_t data; __asm__ volatile("inw %1, %0" : "=a" (data) : "Nd" (portnumber)); return data; }
Port32Bit::Port32Bit(uint16_t portnumber) : Port(portnumber){}
Port32Bit::~Port32Bit() {}
void Port32Bit::Write(uint32_t data){ __asm__ volatile("outl %0, %1" : : "a" (data) , "Nd" (portnumber)); }
uint32_t Port32Bit::Read(){ uint32_t data; __asm__ volatile("inl %1, %0" : "=a" (data) : "Nd" (portnumber)); return data; }
|
我们这里仍然采用内嵌汇编的方法实现功能,其中outb
以及inb
分别表示向固定的端口写入以及读取端口数据
3、slow write
最后,我们需要实现一个慢写入,这里面由于未查到资料,所以并不清楚实现慢写入的原因,暂时码住。
port.h
1 2 3 4 5 6
| class Port8BitSlow : public Port8Bit { public: Port8BitSlow(uint16_t portnumber); ~Port8BitSlow(); virtual void write(uint8_t data); };
|
port.cpp
1 2 3 4 5 6 7 8
| Port8BitSlow::Port8BitSlow(uint16_t portnumber) : Port8Bit(portnumber){}
Port8BitSlow::~Port8BitSlow() {}
void Port8BitSlow::Write(uint8_t data){ __asm__ volatile("outb %0, %1\njmp 1f\n1: jmp 1f\n1:" : : "a" (data) , "Nd" (portnumber)); }
|
可以看出,慢写入的汇编语句如下:
1 2 3 4
| outb data, portnumber jmp 1f 1: jmp 1f 1:
|
上面的data以及portnumber不是真实的汇编语句,这里只是为了说明汇编语句的操作,而且主要目的是介绍下面的内容
jmp 1f
,f表示向下跳转,跳转到1这个位置,到达1这个位置之后又出现了一句jmp 1f
,再次向下跳转无汇编语句,执行结束。
我们通过两次跳转指令实现了慢写入,也就是在执行outb
汇编指令之后做一些无用功,然后再返回,应该是为了等待一些工作的完成。