Experiments with the cursor

Reference picture of the post "Experiments with the cursor"

In this post I write about how to set the cursor using the BIOS interrupts INT 10h / AH=02h.

I investigated how the cursor works for a while and, in this post, I'm going to describe all the strange things that I have found. For my experiments, I wrote a program and I adapted it from time to time in order to proceed further with the experiments. What you find in the DOWNLOAD AREA is the latest version of the program "LearnCursor.zip", as well as the screenshots in this post, are from this latest version however, I will also refer to some initial versions of the program to describe how my learning journey was developing. One thing I found during my learning was that the screen of the computer was in a certain way remembering me about something else and then I realized that it looked somehow like the old good arcade game snake and for this reason, I selected a picture of that game as the opening picture of this post.

Fig. A - One screenshot of the program
Fig. A - One screenshot of the program

In Fig A, you can see the program as it is right now with all functionalities implemented, but at the beginning, I had just the possibility to change the video mode (the key F3) and the possibility to increase the cursor one column position at a time (the key F1). The values for column and row in "movingCursor" tells what the program sets and "BIOS data cursor" returns the value from the BIOS data area (address 0x0000:0450) of course I expected the two values to be identical, but I really wondered if it were so also when I was going to set the cursor at the right of the rightmost column. Similarly, I retrieved the value of the current video page and the size of the screen in columns by rows from the BIOS Data Area (I called them "Video page" and "BIOS data windows" in Fig A). In Fig. C of the post "Test the video modes" you can find a partial overview of the BIOS Data Area made by me. In the meantime, I found an excellent overview of the BIOS Data Area made by Vitaly Filatov that I recommend to you on this web page http://vitaly_filatov.tripod.com/ng/asm/asm_002.html. I always wanted to check the behaviour of the cursor in all the standard video mode available plus one additional extended mode (find out more reading my previous post "Test the video modes") and in order to roll around the modes that I wanted to explore, I prepared an array in the section _justData.

Fig. B - The array [.listOfModes]
Fig. B - The array [.listOfModes]

As you can see in Fig. B, the array starts at address .listOfModes: and terminates at address .listOfModesEnd:. At address .vModeIdx: (it stands for video mode index) I stored the address of the current element of interest inside the array [.listOfModes]. Of course, the two labels .listOfModesEnd: and .vModeIdx: are exactly the same address but I preferred anyway to use two different names in the code in such a way to keep logically distinguished the two different ways by which I used this address. The array [.listOfModes:] can be redefined shorter or longer (with more or fewer elements) without the need of changing the code because the code knows where it starts (.listOfModes:) and where it ends (.listOfModesEnd:).

Fig. C - The rolling index of [.listOfModes]
Fig. C - The rolling index of [.listOfModes]

In Fig. C, you see the lines of code from 125 to 136. Here I took the current value of the index from the address .vModeIdx:, I compared it with the end of the array address .listOfModesEnd: and I reset it to point to the beginning of the array if it was above the end. Then I used the index to load the video mode with a LODSB instruction which also increased SI at the same time.

The first question that I had was: "what does it happen if I try to set a column value for the cursor which is above the maximum number of columns available in the current video mode?"

Fig. D - Cursor on the right of the rightmost column in text mode
Fig. D - Cursor on the right of the rightmost column in text mode

Fig. D shows you the result of this experiment. It is possible to set a cursor on the right of the rightmost column. The BIOS data area keeps working and records the value of the cursor being on the right of the rightmost column. The effect on the screen is that the cursor appears to be on the next row even if the BIOS data area returns a row value of 0x00. I have studied (without having made any experiments of my own yet) that the interpretation of the video RAM in text mode is that each pair of bytes (each word if you like) describes the ASCII code and the attribute (background and foreground colour) of the character on screen. So I made the hypothesis that setting the cursor one column more on the right just has the effect of writing at the next word higher in the Video RAM and, as a consequence, it was logical to see the cursor appearing on the next line. It was as well logical to see the cursor returning at the original location (and keep going again from there on) as soon as the count of columns overflowed the 255 (0xFF) boundary.

As far as it concerns the organization of Video RAM in graphic mode, I haven't any good idea of how it is organized and actually works, so I was really curious to see the effects of this experiment in any of the graphic modes.

Fig. E - Cursor on the right of the rightmost column in graphic mode
Fig. E - Cursor on the right of the rightmost column in graphic mode

Fig. E shows the result of the experiment. As you can see, I observed that the cursor went one pixel downwards overwriting partially the char of the previous line when I set it at the right of the rightmost column. When the column counter overflowed the 255 boundary, the cursor restarted where it was. I have to say that I liked this behaviour because it showed a consistent parallel among the modes.

Soon after the experiments moving the cursor rightwards, I modified the program to be able to set the cursor downwards. I was really curious to see what was about to happen then.

Fig. F - Cursor below the bottom-most row in text mode
Fig. F - Cursor below the bottom-most row in text mode

Fig. F shows what happened: the cursor just disappeared outside the screen. It could have been possible that the cursor has reappeared on the top of the screen one column on right, in a way similar to what happened in the previous cases, however, this didn't surprise me much and I found it compatible with the Video RAM management hypothesis done before. In other terms, if writing one cursor on the right meant to write one word ahead in the Video RAM address space, probably writing one cursor down would mean to write at as many words ahead in the Video RAM address space as the total number of columns in which the currently selected video mode was. If this hypothesis were true, then the program was writing on other video pages when the cursor went out of the screen on page 0x00.
To check this hypothesis I extended the original program in order to be able to switch from page to page and see what was going on also there. I was able to modify my program in this sense (this is the final version of "LearnCursor.zip" that you find in the DOWNLOAD AREA) and I could confirm my hypothesis, but I also found something very strange and unexpected in the behaviour of the pages.

Fig. G - Cursor below the bottom-most row continued on page 0x01
Fig. G - Cursor below the bottom-most row continued on page 0x01

Fig. H - Cursor below the bottom-most row continued on page 0x02
Fig. H - Cursor below the bottom-most row continued on page 0x02

As you can see in Fig. G and Fig. H, the setting done on the cursor on page 0x00 (the first page) propagates on other pages (on higher address in memory) when the cursor goes below the bottom-most row of page 0x00. I observed that the vertical line which paints the movement of the cursor jumped left and right from page to page compared to the original column position set on page 0x00. With some additional research on the internet1 , I learned that the memory pages start with a given alignment so that page n+1 doesn't start immediately after page n but there exists a gap of addresses that aren't displayed.

Fig. I - Picture from Free VGA web page
Fig. I - Picture from Free VGA project web page

All the things that I wrote so far describe what I could understand about the results of the tests and that I could explain based on the experience made and the knowledge acquired until now. Additionally, I experienced some strange and unexpected behaviours on the screen that I cannot understand and explain yet.

In the past, I learnt that if I try to set a video mode that was not supported by the video card, the reaction was simply that the video card kept using the current video mode. As you can see in Fig. L of the post "Test the video modes", when I tried to set the video mode 0x08 with INT 0x10/AH=0x00, AL=0x08 then the screen remained in mode 0x03 as checked with INT 0x10/AH=0x0F. Based on this experience I guessed that if I had attempted to set a page that was not supported then I should have noticed no change at all both at the screen and in the BIOS Data Area (address 0x0000:0462 contains one byte holding the current display page). I was wrong. I found that the BIOS attempted to set the page and that strange things then happened. It was always possible to go one page beyond the limit (for instance page 0x08 on mode 0x00 whose latest supported page is 0x07) and then restore the page 0x00 with the F5-key but if I went two pages (or more) beyond the limit then the F5-key wasn't working every time and sometimes I even had to restart the computer.

Fig. J – Bonus Page in mode 0x00
Fig. J – Bonus Page in mode 0x00

With surprise, I found one additional video page (the 9th-page, page 0x08) on video modes 0x00, 0x01 and 0x02 (see Fig. J). I have no idea of how this could be and how the memory is organized for such "bonus pages" but those bonus pages seemed to me to work, and I found them on both PCs: the HP and the IBM. In the EGA graphic modes (from 0x0D to 0x10) it seemed that the pages would wrap around such as that attempting, for example, to set page 0x08 (the 9th page) in mode 0x0D would bring the page 0x00 back again on screen but trying to increase the page number furthermore blocked the computer.

Fig. K - One of the VGA graphic modes
Fig. K - One of the VGA graphic modes

In all VGA graphic modes (0x11, 0x12 and 0x13) the screen appeared to partially duplicate itself diagonally in the bottom right direction as you can see in Fig. K. I have genuine no idea about what goes on behind the curtains here and it would be great if somebody knew the explanation and would write it down it in the comment.

The latest, strangest and most unexpected thing to me was that this program was actually working properly meanwhile it had to show different behaviour on any video page other than page 0x00.

Fig. L – From the file ".\SWBIG-LIB\show_string.asm"
Fig. L – From the file ".\SWBIG-LIB\show_string.asm"

Looking at the code of the procedure _SHOW_STR in Fig. L (you find it in the file ".\SWBIG-LIB\show_string.asm" of the project "LearnCursor.zip" that you can download from the DOWNLOAD AREA), you should realize that this procedure had to display nothing on any page different from page 0x00 since I hard coded the target page in BH=0x00 on line 43 but, instead, it was working just fine on any video page that I was bringing on the screen. Based on this experience I should conclude that INT 0x10 / AH=0x0E (Teletype Out) doesn't care about the value in the register BH and works just on the currently active page. However looking at the "Ralf Brown Interrupt List" (or on the Deloire mirror site) one can read that BH should set the target page where to write.

I started searching the internet to find out if I could find some other source of information about the BIOS INT 0x10 / AH=0x0E, its behaviour and the purpose of the register BH in this context. I found a lot of different web pages all stating the same as the "Ralf Brown Interrupt List" (I suppose that everybody refers to it so that the information is just replicated). The only reference that I was able to find which apparently states something different (although in a very mysterious way) is the "Programmer's guide to the EGA, VGA and Super VGA cards" by Richard F. Ferraro on page 20, Table 2.6.

Fig. M - Table 2.6 of Ferraro's book
Fig. M - Table 2.6 of Ferraro's book

As said, the way the statement is made on Table 2.6 (Fig. M) needs to be interpreted and, based on the experience summarized in this post, my interpretation is that the BIOS INT 0x10 / AH=0x0E writes on the active page only and the register BH is just ignored.



  1. You can read more at the Free VGA project web page by Joshua Neal and additionally search for the following document "IBM VGA XGA Technical Reference Manual May 92" (look at chapter "Video Memory Organization" starting on page 2-24). [click back]

<PREV.  -  ALL  -  NEXT>

Comments