Page 1 of 1

(Resolved) Help with small real mode assembly kernel

Posted: Tue Aug 11, 2009 9:51 pm
by sema4
I tried the tutorial at http://wiki.osdev.org/Real_mode_assembly_bare_bones and modified it a little. I added a function for the left and right arrow keys to move the cursor around. The problem is that I am using CL as a counter and every time I press the left and right arrows cl gets changed to some other value. I am new to assembly language so I don't know much about the registers.

Here is the code for left:

Code: Select all

	cmp cl, 0	; beginning of string?
	je .again	; yes, ignore the key

	dec di		; decrease the position in the buffer
	mov ah, 0x03	; get cursor pos
	int 0x10

	dec dl		; decrease the cursor pos
	mov ah, 0x02	; set cursor pos
	int 0x10

	jmp .again
Here is for right:

Code: Select all

	inc di		; increase the position in the buffer
	mov ah, 0x03	; get cursor pos
	int 0x10

	inc dl		; increase the cursor pos
	mov ah, 0x02	; set cursor pos
	int 0x10

	jmp .again
Here is the whole thing:

Code: Select all

;---------------------------------------------;
; a procedure to get user input from keyboard ;
;---------------------------------------------;
input:
	xor cl, cl

.again:
	mov ah, 0
	int 0x16	; wait for keypress

	cmp al, 0x08	; backspace pressed?
	je .backspace	; yes, handle it

	cmp al, 0x0D	; enter pressed?
	je .done	; yes, we're done

	cmp ah, 0x4B	; left arrow key
	je .left	; move cursor left

	cmp cl, 0x3F	; 63 chars inputted?
	je .again	; yes, only let in backspace, enter and left

	cmp ah, 0x4D	; same as above
	je .right

	cmp al, 0x00	; special key?
	je .again	; don't print special keys

	mov ah, 0x0E
	int 0x10	; print out character

	stosb		; put character in buffer
	inc cl
	jmp .again

.backspace:
	cmp cl, 0	; beginning of string?
	je .again	; yes, ignore the key

	dec di
	mov byte [di], 0	; delete character
	dec cl		; decrement counter as well

	mov ah, 0x0E
	mov al, 0x08
	int 0x10	; backspace on the screen

	mov al, ' '
	int 0x10	; blank character out

	mov al, 0x08
	int 0x10	; backspace again

	jmp .again	; go to the main loop

.left:
	cmp cl, 0	; beginning of string?
	je .again	; yes, ignore the key

	dec di		; decrease the position in the buffer
	mov ah, 0x03	; get cursor pos
	int 0x10

	dec dl		; decrease the cursor pos
	mov ah, 0x02	; set cursor pos
	int 0x10

	jmp .again

.right:
	inc di		; increase the position in the buffer
	mov ah, 0x03	; get cursor pos
	int 0x10

	inc dl		; increase the cursor pos
	mov ah, 0x02	; set cursor pos
	int 0x10

	jmp .again

.done:
	mov al, 0	; null terminator
	stosb

	mov si, buffer
	call print
	call crlf

	ret

Re: Help with small real mode assembly kernel

Posted: Tue Aug 11, 2009 10:53 pm
by alethiophile
Not having read the relevant interrupts' manuals, I would venture a guess that the wait-for-keypress interrupt overwrites cl; try saving it in a memory location before calling the interrupt, and reloading it afterwards. Or just use push/pop.

Re: Help with small real mode assembly kernel

Posted: Wed Aug 12, 2009 12:09 am
by f2
INT 0x10 AH = 0x3 destroys CX:

Code: Select all

INT 10 - VIDEO - GET CURSOR POSITION AND SIZE
	AH = 03h
	BH = page number
	    0-3 in modes 2&3
	    0-7 in modes 0&1
	    0 in graphics modes
Return: AX = 0000h (Phoenix BIOS)
	CH = start scan line
	CL = end scan line
	DH = row (00h is top)
	DL = column (00h is left)
You must push CX before calling the interrupt:

Code: Select all

   cmp cl, 0   ; beginning of string?
   je .again   ; yes, ignore the key

   dec di      ; decrease the position in the buffer
   push cx
   mov ah, 0x03   ; get cursor pos
   int 0x10
   pop cx

   dec dl      ; decrease the cursor pos
   mov ah, 0x02   ; set cursor pos
   int 0x10

Re: Help with small real mode assembly kernel

Posted: Wed Aug 12, 2009 4:48 am
by Narida
Furthermore, shouldn't you be incrementing/decrementing cl when someone press the left/right arrow key? That seems to be missing... (I could be mistaken though...)

Re: Help with small real mode assembly kernel

Posted: Thu Aug 13, 2009 1:05 am
by sema4
I used the push/pop and it's working.
@Narida: Yes, you're right about the inc/dec of CL. I forgot to add that in.

Thanks for the help.

Re: (Resolved) Help with small real mode assembly kernel

Posted: Fri Aug 13, 2010 6:14 pm
by Hoozim
BIOS interrupt often affect many of the registers. Just push them onto the stack before using a software interrupt. Eventually though, you might want to switch to 32-bit mode and do everything directly. (Manually polling the keyboard controller or installing hardware interrupt descriptors and remapping the PIC) This may be harder but it is faster and a lot more rewarding. :D

Re: (Resolved) Help with small real mode assembly kernel

Posted: Sat Aug 14, 2010 12:25 am
by VolTeK
Do note that, before osdev'ing reread your asm manual, it will help alot. You would then remember some very useful instructions that would help make things easier, and save bytes ;)