[solved] Invalid jmp inside of an interrupt - real mode x86

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
User avatar
Lithorien
Member
Member
Posts: 59
Joined: Tue Oct 27, 2009 1:40 pm
Location: Hanover, PA

[solved] Invalid jmp inside of an interrupt - real mode x86

Post by Lithorien »

I'm working on a real mode OS, and currently working on getting interrupts hooked into the IVT. I've hooked the interrupts correctly and they work (mostly), but I've hit on a strange bug that I can't seem to track down.

When I call my OS' interrupt for getting a string from the keyboard, it works fine - until I type in a control character that I handle (enter or backspace - things like tab that I ignore work fine). Half the time I get junk characters printed to the screen, and half the time Bochs bombs out with a "LOCK prefix unallowed" issue. When I traced the execution, it appears that my jmp isn't pointing to the right address, but I can't figure out why that's happening.

Here's the code for my interrupt:

Code: Select all

Int32h:
	cli
	pusha
	
	cmp ah,0x0
	je .0
	
	jmp .done
	
	.0:
		xor cx,cx						; cx = Buffer count
	
		.cmd_loop:
			mov ah,0x1
			int 16h
			jz .cmd_loop
			
			mov ah,0
			int 16h
			
			cmp al,0x8					; 0x8 = Backspace
			je .backspace
			
			cmp al,0xD					; 0xD = CR
			je .end
			
			.store_buf:
				cmp cx,256
				je .cmd_loop
				
				mov ah,0x1
				int 31h
			
				stosb
				inc cx
				jmp .cmd_loop
				
			.backspace:
				cmp cx,0				; Beginning of string
				je .cmd_loop
				
				dec di
				mov BYTE [di],0
				dec cx
				
				mov ah,0x1
				int 31h
				
				mov al,' '
				mov ah,0x1
				int 31h
				
				mov al,0x08
				mov ah,0x1
				int 31h
				
				jmp .cmd_loop
			
			.end:
				mov al,0				; Null terminator
				stosb
				jmp .done
	
	.done:
		popa
		sti
		iret
Any help is appreciated. Thank you very much!

Edit: Ints 30 and 31 are also handled by my OS. If the code for those would help, please let me know and I'll add it to this post. Thanks!
Last edited by Lithorien on Mon Feb 15, 2010 8:34 am, edited 1 time in total.
User avatar
Artlav
Member
Member
Posts: 178
Joined: Fri Aug 21, 2009 5:54 am
Location: Moscow, Russia
Contact:

Re: Invalid jmp inside of an interrupt - real mode x86 ASM

Post by Artlav »

Which jmp's doesn't seem to work?
What looks wrong in the code is that i don't see where di is being initialized to a meaningful value. If it is not, the character is written into a random memory location, potentially - jmp command or so.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Invalid jmp inside of an interrupt - real mode x86 ASM

Post by qw »

Are you sure the direction flag is clear?
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Invalid jmp inside of an interrupt - real mode x86 ASM

Post by xenos »

You could also enable memory tracing in Bochs, or set a memory watchpoint, just to see whether the jmp instruction gets overwritten at some point. Something similar once happened to me when I was using real mode the last time...
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Invalid jmp inside of an interrupt - real mode x86 ASM

Post by jal »

Artlav wrote:What looks wrong in the code is that i don't see where di is being initialized to a meaningful value.
Neither is es, so the stosb will fail as well. Come to think of it, neither is ds, so the interrupt routine will trash the calling program's data segment. I don't want to start insulting, but this is all basic stuff. Please...


JAL
User avatar
Lithorien
Member
Member
Posts: 59
Joined: Tue Oct 27, 2009 1:40 pm
Location: Hanover, PA

Re: Invalid jmp inside of an interrupt - real mode x86 ASM

Post by Lithorien »

jal wrote:
Artlav wrote:What looks wrong in the code is that i don't see where di is being initialized to a meaningful value.
Neither is es, so the stosb will fail as well. Come to think of it, neither is ds, so the interrupt routine will trash the calling program's data segment. I don't want to start insulting, but this is all basic stuff. Please...


JAL
My segments are set in my kernel (which is loaded at 0:0x500, my stack points to 0:0x700)

Code: Select all

xor ax,ax
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax

mov ss,ax
mov sp,0x700
And di is being set in the calling code - Buffer is defined as 'Buffer times 256 db 0', so I have a 256-byte buffer established already:

Code: Select all

mov di,Buffer
mov ah,0x0
int 32h
The jumps that are failing are the "je .backspace" and "je .end" jumps.
Hobbes wrote:Are you sure the direction flag is clear?
According to Bochs, df is clear.
User avatar
DednDave
Posts: 18
Joined: Fri Feb 05, 2010 10:40 am
Location: Mesa, Arizona

Re: Invalid jmp inside of an interrupt - real mode x86 ASM

Post by DednDave »

you may need to save and restore DI and CX across the earlier INT's as well
that includes INT 16h and your INT 31h's
BIOS INT 16h probably doesn't mess with CX or DI
but, better safe than sorry
some machines out there may have crappy BIOS - lol

Code: Select all

         .backspace:
            cmp cx,0            ; Beginning of string
            je .cmd_loop
            
            dec di
;;;;            mov BYTE [di],0 ;no need to 0 this byte - it will be overwritten
            dec cx
            
            mov ah,0x1
            push di             ;save di - not sure, but you may need to save/restore ES as well
            push cx             ;save cx
            int 31h
            
            mov al,' '
            mov ah,0x1
            int 31h
            
            mov al,0x08
            mov ah,0x1
            int 31h
            pop cx              ;restore cx
            pop di              ;restore di
            
            jmp .cmd_loop
         
         .end:
            mov al,0            ; Null terminator
            stosb
;;;;            jmp .done       ;unnecessary branch
   
   .done:
      popa
      sti
      iret
User avatar
Lithorien
Member
Member
Posts: 59
Joined: Tue Oct 27, 2009 1:40 pm
Location: Hanover, PA

Re: Invalid jmp inside of an interrupt - real mode x86 ASM

Post by Lithorien »

It's fixed, as far as I can tell.

When I moved my stack from 0x700 to 0x1000, the problems ceased. I think that I was trampling over existing code when the stack grew too large and so my jmp was getting modified-in-place. (I need to suck it up and move my stack to a memory location far above the kernel, I guess.)

Thank you all for your help - it's very appreciated.
Post Reply