Writing a Simple Operating System — from Scratch

(Jeff_L) #1

CHAPTER 6. DEVELOPING ESSENTIAL DEVICE DRIVERS AND A


FILESYSTEM 64


A problem with port I/O is that we cannot express these low-level instructions in C
language, so we have to learn a little bit aboutinlineassembly: most compilers allow you
to inject snippets of assembly code into the body of a function, with gcc implementing
this as follows:


unsigned char port_byte_in(unsigned short port) {
// A handy C wrapper function that reads a byte from the specified port
// "=a" (result) means: put AL register in variable RESULT when finished
// "d" (port) means: load EDX with port
unsigned char result;
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port ));
return result;
}

Note that the actual assembly instruction,in %%dx, %%al, looks a little strange to
us, since gcc adopts a different assembly syntax (known as GAS), where the target and
destination operands are reversed with respect to the syntax of our more familiar nasm
syntax; also,%is used to denote registers, and this requires an ugly%%, since%is an
escape character of the C compiler, and so%%means: escape the escape character, so
that it will appear literally in the string.
Since these low-level port I/O functions will be used by most hardware drivers in
our kernel, let’s collect them together into the filekernel/lowlevel.c, which we can
define as in Figure XXX.


unsigned char port_byte_in(unsigned short port) {
// A handy C wrapper function that reads a byte from the specified port
// "=a" (result) means: put AL register in variable RESULT when finished
// "d" (port) means: load EDX with port
unsigned char result;
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port ));
return result;
}

void port_byte_out(unsigned short port , unsigned char data) {
// "a" (data) means: load EAX with data
// "d" (port) means: load EDX with port
__asm__("out %%al, %%dx" : :"a" (data), "d" (port ));
}

unsigned short port_word_in(unsigned short port) {
unsigned short result;
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port ));
return result;
}

void port_word_out(unsigned short port , unsigned short data) {
__asm__("out %%ax, %%dx" : :"a" (data), "d" (port ));
}
Free download pdf