Page 1 of 1

[SOLVED] Ret Triple Faults After Call

Posted: Sun Nov 14, 2010 2:24 pm
by Muneer
Hello,

I'm Having a rather weird problem. Every Time I try to make a call To "NewLine" (Extern) which is declared in another file , the Call Works but when i try to Ret from the procedure . It Just Triple Faults. Also I tried to jump Back to a label Placed after the call instruction and it works. My GDT COnsists of A code segment and data segment both flat and uses data segment as stack.

Calling Procedure

Code: Select all


[BITS 32]
[SECTION .text]
[GLOBAL   START]
[EXTERN   NewLine]
[EXTERN   Cursor]


START:
Mov	Ebp , String
Call	PrintText
Jmp 	$

PrintText :
 
				Call 	NewLine         ;  HERE IS THE CALL
	         		Jmp	$
				Mov	Ebx , [Cursor]
	
		NextChar:	Mov	Ah , [ Ds:Ebp ] 
				Cmp	Ah , 0
				Je	StopPrinting
				Inc	Ebp
				Add	Ebx , 2
				Mov	[ Gs:Ebx ] , Ah
				Jmp	NextChar
		StopPrinting:	Ret

String:	db 	"Some Stuff Here" , 0

Called Procedure

Code: Select all

[BITS 32]
[GLOBAL NewLine]
[GLOBAL Cursor]


NewLine: 

	Mov	Ax , [Cursor]
	Shl	Al , 1
	Shr	Al , 1
	Mov	Dh , 0
	Mov	Dl , Al
	Mov	Ax , 80
	Sub	Ax , Dx
	Mov	Dx , [Cursor]
	Add	Dx , Ax
	Mov	[Cursor] , Dx
	add   Ebx , 2
	mov	ah , "H"
	Mov	[ Gs:Ebx ] , Ah
	Ret                             ;  HERE IS THE PROBLEM


[SECTION .data]
Cursor:	dw	0
I compile using Nasm -f Aout -o Caller.o caller.asm
Nasm -f Aout -o Called.o Called.asm
and Link using LD Djgpp
ld -T link.ld -Ttext 0x100000 called.o caller.o ;Wont link properly if caller.o called.o


link.ld

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(START)
phys = 0x00100000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    
  }
  end = .;
}

Re: Ret Triple Faults After Call

Posted: Mon Nov 15, 2010 7:36 am
by Brendan
Hi,
HardCoder wrote:I'm Having a rather weird problem. Every Time I try to make a call To "NewLine" (Extern) which is declared in another file , the Call Works but when i try to Ret from the procedure . It Just Triple Faults.
The reason for the exception could be many things (including bad values for SS:ESP, bad paging setup, bad segments/GDT, etc); and the reason for the exception may just be a symptom of bugs elsewhere (e.g. boot loader that messes up the code, memory manager that thinks ROM is RAM or allows the same RAM to be allocated twice, scheduler that trashes something, etc).

The first step would be to get some information about the problem. For example, run it in something like Bochs and see what type of exception leads to the triple fault (e.g. page fault or general protection fault), and which values are in which registers at that time. Bochs will put all this in its log, so you don't even need to use the inbuilt debugger for that. If that's not enough information, something like the inbuilt debugger in Bochs can be a powerful tool (it lets you examine contents of registers, memory, etc while seeing the effects of every instruction leading up to the exception).

Code: Select all

NewLine:

	Mov	Ax , [Cursor]
	Shl	Al , 1
	Shr	Al , 1
	Mov	Dh , 0
	Mov	Dl , Al            ;DX = low 7 bits from [Cursor], with all other bits cleared

	Mov	Ax , 80
	Sub	Ax , Dx            ;AX = 80 - (low 7 bits from [Cursor])
	Mov	Dx , [Cursor]
	Add	Dx , Ax            ;DX = "[Cursor]" + 80 - (low 7 bits from [Cursor])
	Mov	[Cursor] , Dx      ;"[Cursor]" = "[Cursor]" + 80 - (low 7 bits from [Cursor])
	add   Ebx , 2            ;EBX = unknown + 2
	mov	ah , "H"
	Mov	[ Gs:Ebx ] , Ah    ;[unknown + 2] = 'H'
	Ret                             ;  HERE IS THE PROBLEM
Are you sure this code does anything you intended?

My guess is that "[Cursor]" is meant to contain the character number for the cursor's position (e.g. where the value 123 is column 43 on row 1), and that the calculation for the new cursor position is wrong. I'd also assume that you forgot to do something like "movzx ebx,[Cursor]" before the "Mov [ Gs:Ebx ], Ah" instruction, and that the "Mov [ Gs:Ebx ], Ah" instruction should have been "Mov byte [Gs:Ebx * 2], 'H'" (where the GS segment register contains the base address of display memory).

If "[Cursor]" is meant to contain the character number for the cursor's position, then you'd need to do the equivelent of "value = value - value % 80 + 80". The only sane way to do that is with the DIV instruction (e.g. divide by 80 to find the remainder, then subtract the remainder from the original value and add 80). It's almost like you've got hexadecimal and decimal confused. The actual calculation you're doing is "value = value + 80 - (value & 0x7F)", which would've been a valid optimisation for "value = value - value % 0x80 + 80" (but 0x80 is not 80).

Then there's efficiency. For example, your broken code could've been done with half the instructions (assuming none of the registers are used for returned values) - for example:

Code: Select all

NewLine:
	mov dx,[Cursor]            ;dx = [Cursor]
	mov ax,80                  ;ax = 80
	and dx,0x007F              ;dx = low 7 bits from [Cursor]
	sub ax,dx                  ;ax = 80 - (low 7 bits from [Cursor])
	add [Cursor], ax           ;[Cursor] = [Cursor] + 80 - (low 7 bits from [Cursor])
	mov byte [gs:ebx+2],'H'    ;[unknown + 2] = 'H'
	ret
Anyway, based on a large number of assumptions (caused by inadequate commenting in the original), I'm guessing the code should be something like:

Code: Select all

NewLine:
	movzx eax,word [Cursor]    ;eax = [Cursor]
	xor edx,edx                ;edx:eax = [Cursor]
	mov ebx,80                 ;ebx = 80
	div ebx                    ;eax = [Cursor] / 80, edx = [Cursor] % 80
	sub ebx,edx                ;ebx = 80 - [Cursor] % 80
	add bx,[Cursor]            ;ebx = [Cursor] - [Cursor] % 80 + 80
	mov [Cursor],bx            ;[Cursor] = [Cursor] - [Cursor] % 80 + 80
	mov byte [gs:ebx*2],'H'    ;Put a "H' where the new cursor is
	ret

Cheers,

Brendan

Re: Ret Triple Faults After Call

Posted: Mon Nov 15, 2010 10:59 am
by Muneer
Thanks Brendan,


I Got the Answer , It was just as your first guess i.e Bad SS:ESP. And I was just experimenting the way linker links and whether the call function and Global and Extern works as intended before starting with my original kernal and functions. It was just that whatever i had written was just to test rather than to focus on its functions. Well thanks for the tip and the efficient code sample. I see that I was wrong in finding the Cursor Position. And the Decimal 80 was for the bios 80 x 25 video mode to do a new Line. Well Thanks Man and Could you just say how to mark a topic as solved ( I am a Newbie in Forums ).
Cheers... :D

Re: Ret Triple Faults After Call

Posted: Mon Nov 15, 2010 12:05 pm
by Brendan
Hi,
HardCoder wrote:I Got the Answer
Cool :)
HardCoder wrote:Well Thanks Man and Could you just say how to mark a topic as solved ( I am a Newbie in Forums ).
You should see an "edit" button in your first post. If you click that you'll be able to edit it and also change the subject line (e.g. add "[SOLVED]" to it).


Cheers,

Brendan

Re: [SOLVED] Ret Triple Faults After Call

Posted: Mon Nov 15, 2010 12:45 pm
by Muneer
Thanks