Actually, it is quite easy. To access system services (like BIOS, VESA, SCSI, etc), you use an interrupt call. If you are familiar with programming (not making any assumptions either way), an interrupt would be akin to a function call. The parameters for those functions are put into the CPU registers, main ones (called the General Purpose Registers) being AX, BX, CX, and DX. Now, these are the original 16-bit registers originating from way back in the 8086. A reference to these original registers is at: http://ourworld.compuserve.com/homepage
Each of the 16-bit general purpose registers can be split into two usable 8-bit registers. For instance, AX can be broken up into AH and AL, for A(high byte) and A(low byte).
Also, here is a reference to interrupt 10 (which is being used in the code snippet posted): http://en.wikipedia.org/wiki/INT_10
Basically, you set up the parameters (move a value into the registers), and call the interrupt. It is that easy.
One of the things that makes this bit of code tricky to a newcomer is the fact that two important values are being moved into, say, the AX register with one move statement... let me elaborate:
Lets take the first block of code:
Code: Select all
mov ax, 1202h;
mov bx, 0301h;
The first line is really moving 02h into AH and 12h into AL. This might seem backwards to you, because logic would tell you that 12 comes first, it should be going into the AH register. Actually, most processors now operate in what is called "little endian" mode. What this really means is that the bytes are stored backwards to how you normally read a number on paper. More details can be found here: http://en.wikipedia.org/wiki/Endianness#Little-endian
Ok, so anyway, 02h is being moved into AH and 12h is being moved into AL. Now take a look at the wikipedia page I linked to above and take a look at the third row in the table on that page, with the first column reading "Set cursor position".
You will notice, setting the cursor position involves moving 02h into AH, where whatever value is in BH is the page number. The second line takes care of this, by moving 01h into BH and 03h into BL. since BH is 01h, this means set cursor position to the first page.
Now with those three lines of code, there is already some problems with it. The first line moves 12h into AL, and the second line moves 03h into BL. Neither of these values do anything. They have no purpose, they will be ignored.
Also, you will notice in the documentation, that setting the cursor position also requires values in in DH to be the row the cursor gets moved to and DL is to be the column the cursor gets moved to. Neither of these are set, so essentially, even if the cursor makes it back to page 1 (if the values in DL and DL are invalid, the call to int 10 will fail), it will be in a completely random place. Now, there could be code before VideoInit to initialize the registers to sane values, but there is no way to know from this function, so it is bad practice to assume so.
The first block SHOULD be rewritten to:
Code: Select all
mov ah, 02h;
mov bh, 01h;
mov dx, 0101h;
The rest of the code is just as sloppy. Even the function VideoInit is declared void, so there is no way to return a value to let the caller know that it failed. So more or less, if for whatever reason this function blows up (maybe you are trying to run on a machine without VESA 2.0 support), the whole system crashes, where a better solution would be to try and fall back to some other video mode, or even output to the serial port.