(Resolved) Help with small real mode assembly kernel

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
sema4
Posts: 5
Joined: Tue Aug 11, 2009 9:30 pm

(Resolved) Help with small real mode assembly kernel

Post 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
Last edited by sema4 on Thu Aug 13, 2009 1:06 am, edited 1 time in total.
User avatar
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

Re: Help with small real mode assembly kernel

Post 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.
If I had an OS, there would be a link here.
User avatar
f2
Member
Member
Posts: 311
Joined: Mon Jun 15, 2009 10:01 am
Location: France

Re: Help with small real mode assembly kernel

Post 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
"Open source seems to embrace the dark side of human nature." - Ville Turjanmaa
Narida
Posts: 2
Joined: Tue Aug 11, 2009 8:43 am

Re: Help with small real mode assembly kernel

Post 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...)
sema4
Posts: 5
Joined: Tue Aug 11, 2009 9:30 pm

Re: Help with small real mode assembly kernel

Post 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.
Hoozim
Member
Member
Posts: 53
Joined: Fri Jul 23, 2010 8:26 am

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

Post 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
User avatar
VolTeK
Member
Member
Posts: 815
Joined: Sat Nov 15, 2008 2:37 pm
Location: The Fire Nation

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

Post 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 ;)
Post Reply