Text Mode Cursor: Difference between revisions

Finished rewriting page, added a few sections
[unchecked revision][unchecked revision]
(Rewrote most of the page)
(Finished rewriting page, added a few sections)
Line 1:
In [[text mode]], the cursor does not work the same way as in high-level languages, automatically moving to one place after the last written character. Instead, it is simply a blinking area that can be resized, shown, hidden, and moved by the OS.
==Moving the Cursor==
===With the BIOS===
 
==With the BIOS==
To move the cursor with the [[BIOS]], use int 0x10 (the interrupt for screen functions). These are the registers used:
 
To manipulate the cursor with the [[BIOS]], use int 0x10, the interrupt for screen functions.
* AH = 0x02
* BH = display page (usually, if not always 0)
* DH = row
* DL = column
 
===WithoutEnabling the BIOSCursor===
 
Enabling the cursor also allows you to set the start and end scanlines, the rows where the cursor starts and ends. The highest scanline is 0 and the lowest scanline is the maximum scanline (usually 15).
Without [[BIOS]] access, moving the cursor requires sending data directly to the hardware.
 
* AH = 0x01
'''Source in C'''
* CH = start scanline
* CL = end scanline
 
===Disabling the Cursor===
<source lang="c">
void update_cursor(int x, int y)
{
uint16_t pos = y * VGA_WIDTH + x;
 
* AH = 0x01
outb(0x3D4, 0x0F);
* CH = 0x3F (bits 0-7 unused, bit 5 disables cursor, bits 0-4 control cursor shape)
outb(0x3D5, (uint8_t) (pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
}
</source>
 
===Moving the Cursor===
Note that the x and y positions start from 0 in the top-left corner. Keep in mind you don't need to update this every time a new character is displayed. It would be faster to instead only update it after printing an entire string or until a user prompt.
 
* AH = 0x02
'''Source in Assembly'''
* BH = display page (usually, if not always 0)
* DH = row
* DL = column
 
===Get Cursor Data===
Since [[BIOS]] services cannot be accessed in [[Long Mode]], the following routine shows how to move cursor without BIOS in VGA text 80x25 (can be altered a bit to fit protected mode):
 
* AH = 0x03
<source lang="asm">
* BH = display page (usually, if not always 0)
; Set cursor position (text mode 80x25)
; @param BL The row on screen, starts from 0
; @param BH The column on screen, starts from 0
set_cursor:
pushfq
push rax
push rbx
push rcx
push rdx
 
The return values:
; unsigned short position = (row*80) + col
; AX will contain 'position'
mov ax, bx
and ax, 0ffh ; set AX to 'row'
mov cl, 80
mul cl ; row * 80
mov cx, bx
shr cx, 8 ; set CX to 'col'
add ax, cx ; + col
mov cx, ax ; store 'position' in CX
; cursor LOW port to vga INDEX register
mov al, 0fh
mov dx, 3d4h ; VGA port 3D4h
out dx, al
mov ax, cx ; restore 'postion' back to AX
mov dx, 3d5h ; VGA port 3D5h
out dx, al ; send to VGA hardware
; cursor HIGH port to vga INDEX register
mov al, 0eh
mov dx, 3d4h ; VGA port 3D4h
out dx, al
mov ax, cx ; restore 'position' back to AX
shr ax, 8 ; get high byte in 'position'
mov dx, 3d5h ; VGA port 3D5h
out dx, al ; send to VGA hardware
 
* CH = start scanline
pop rdx
* CL = end scanline
pop rcx
* DH = row
pop rbx
* DL = column
pop rax
 
popfq
==Without the BIOS==
ret
 
</source>
Without [[BIOS]] access, manipulating the cursor requires sending data directly to the hardware.
 
==Setting=Enabling the Cursor Start and End Scanlines===
 
To setEnabling the cursor also allows you to set the start and end scanlines, use the Cursorrows Start Register (0x0A) andwhere the Cursorcursor Endstarts Registerand (0x0B)ends. The highest scanline is 0 and the lowest scanline is the maximum scanline (usually 15).
 
'''Source in C'''
Line 100 ⟶ 58:
</source>
 
'''Source in Assembly'''
To make the cursor be a block instead of a line, try enable_cursor(0, 15).
 
TODO
==Disabling The Cursor==
===With the BIOS===
 
===Disabling the Cursor===
To move the cursor with the [[BIOS]], use int 0x10 (the interrupt for screen functions). These are the registers used:
 
* AH = 0x01
* CH = 0x3F (bits 0-7 unused, bit 5 disables cursor, bits 0-4 control cursor shape)
 
===Without the BIOS===
 
Without [[BIOS]] access, disabling the cursor requires sending data directly to the hardware.
 
'''Source in C'''
Line 129 ⟶ 79:
disable_cursor:
pushf
push raxeax
push rdxedx
 
mov dx, 0x3D4 ; one of VGA's Index registers controller
mov al, 0xa0xA ; index 0xa is the; LOWlow cursor shape register
out dx, al
 
inc dx
inc dx ; one of VGA's data registers, port 0x3D4, allows reads and writes to VGA's registers
mov al, 0x3F ; bits 6-7 must be 0unused, if bit 5 setdisables the cursor is disabled, bits 0-4 control the cursor shape
out dx, al
 
pop rdx
pop raxedx
pop eax
popf
ret
</source>
 
===Moving the Cursor===
 
Keep in mind that you don't need to update the cursor's location every time a new character is displayed. It would be faster to instead only update it after printing an entire string.
 
'''Source in C'''
 
<source lang="c">
void update_cursor(int x, int y)
{
uint16_t pos = y * VGA_WIDTH + x;
 
outb(0x3D4, 0x0F);
outb(0x3D5, (uint8_t) (pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
}
</source>
 
'''Source in Assembly'''
 
<source lang="asm">
; BL = x
; BH = y
update_cursor:
pushfq
push eax
push ebx
push ecx
push edx
 
; position = x * VGA_HEIGHT + y
mov ax, bx
and ax, 0FFh
mov cl, VGA_HEIGHT
mul cl
mov cx, bx
shr cx, 8
add ax, cx
mov cx, ax
; cursor low port to VGA index register
mov al, 0Fh
mov dx, 3D4h
out dx, al
 
; cursor low position to VGA data register
mov ax, cx
mov dx, 3D5h
out dx, al
 
; cursor high port to VGA index register
mov al, 0Eh
mov dx, 3D4h
out dx, al
 
; cursor high position to VGA data register
mov ax, cx
shr ax, 8
mov dx, 3D5h
out dx, al
 
pop edx
pop ecx
pop ebx
pop eax
popfq
ret
</source>
 
==A Note on GRUB==
 
If the timeout is set to 0 in your grub.cfg, the cursor will be disabled and you will need to enable it yourself. Otherwise, [[GRUB]] will enable the cursor for you. Because of this inconsistency, it is a good idea to always enable the cursor. Even if you don't set the timeout to 0, you might want to in the future, or someone might change it on their system.
 
==See Also==
* [http://wiki.osdev.org/VGA_Hardware VGA Hardware]
* [http://wiki.osdev.org/Text_UI Text UI]
 
===External Links===
* http://www.bookcaseosdever.comnet/libraryFreeVGA/dosvga/ints/int10textcur.html (dead link)htm
* https://web.archive.org/web/20080731014051/http://www.bookcase.com:80/library/dos/ints/int10.html
* https://web.archive.org/web/20120324083032/http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_13/CH13-2.html
* http://www.osdever.net/FreeVGA/vga/vga.htm
 
[[Category:Video]]
Anonymous user