Problems with INT services

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
Cjmovie

Problems with INT services

Post by Cjmovie »

I'm actually very close to putting this under "general programming", but oh well.

Problem:
Calling a function which calls a function which calls a function causes problems when passing an address (to a string), making it jibberish input to the final function.

I have code as such:

Code: Select all

UINT arg;

void ThisFunc(char* a){
 arg = (UINT)a;
 ThatFunc();
}

ASM:

_ThatFunc:
 mov ebx, [_arg]
 int 0x55
 ret

_int55:
 push ebx ;Push argument to c code in kernel
 call _ThatCFunction
 pop ebx
 iret

More C-Code
void ThatCFunction(char* a){
 PrintString(a);
}
My problem? it doesn't seem to be passing the correct address for the string. The INT 55 is part of the kernel, the other 2 are part of the program it is executing. For some reason, the kernel gets the address 0x00000001 instead of 0x00001000. Even weirder, if I replace the line:

Code: Select all

arg = (UINT)a;
with

Code: Select all

arg = (UINT)0x1000;
It works! Any idea what could cause this? Kind of on the end of my head right now, really odd problem....

Thanks for any help :)
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Problems with INT services

Post by Candy »

Did you try single-stepping that bit of code with Bochs (debugging version) to see which instructions were executed in both cases?

If not, please do so. You will figure out the cause yourself and you'll understand why and how much better.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Problems with INT services

Post by Pype.Clicker »

so roughly, that means all you've written is correct but your program that calls int55 isn't quite correctly linked ... right ?
Cjmovie

Re:Problems with INT services

Post by Cjmovie »

I did step through it, everything looks fine except instead of the correct address of the string data (0x00001000) it has a seemingly random address (0x00000001).

Heres something else weird I noted after trying out my code with two ints: For some reason, some calls to asm code are being cut out by the compiler or whatnot: For instance, I have one ASM code function that does "mov ax, 0x00\n int 0x50" and another that does "mov ax, 0x01\n int 0x50". I can call either one as much as I like, but if I do a call to the first function _at the start of the program_, it never generates the call to the function! I then tried using inline ASM for it -> same results, it cut it out.

I have a feeling this might be, in fact, either a compiler problem (on my side, probably) or something with linking it. If I do both files (the services.asm and main function) in ASM, it works fine.
Cjmovie

Re:Problems with INT services

Post by Cjmovie »

Oops, knowing this might help:

Compilation Script:

Code: Select all

gcc -c -ffreestanding -I./Kernel/Include -O Apps/Shell.c -o Apps/Shell.o
nasm Apps/Services.asm -o Apps/Services.a -f elf

ld -T Apps/Shell.ld -o Apps/Shell.o.ld Apps/Services.a Apps/*.o
objcopy -S -O binary Apps/Shell.o.ld Object/Shell.APP
Linker Script:

Code: Select all

ENTRY(_Main)
phys = 0x00000000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)

  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
  }
  end = .;
}
AR

Re:Problems with INT services

Post by AR »

Are you using segmentation or a higher half kernel? If not then that link address (0x00000000) will yield a broken binary that will access data pointers in the wrong part of the address space.
Cjmovie

Re:Problems with INT services

Post by Cjmovie »

Paging :P.
Kernel at 0xc000000, shared librarys/message qeue at 0x80000000, program/data at 0x00000000.
Cjmovie

Re:Problems with INT services

Post by Cjmovie »

Where did all those last few posts go? Did it have something to do with the forum not working earlier?

Anyways, post again I must.

I'm getting a GPF if a task switch occurs during the execution of an INT. I have switched the int type from to a TRAP gate, as pype recommended. When I get the error:

EFLAGS: 0x10002 (Aren't the top 16 bits reserved/0?)
Error Code: 0x210

Code:
(Application)

Code: Select all

global _PrintString
global _ClearScreen

global _ArgA

global _Main
_Main:
 ;call _ClearScreen
 
.L1
 mov ebx, StrN1
 call _PrintString
 jmp .L1
 
 call _GetChar
 
 mov ebx, StrN2
 call _PrintString
 
 ret

_ClearScreen:
 mov ax, 0x00
 int 0x50 ;Call text services
 ret ;Return to C code

_PrintString:
 mov ax, 0x01
 int 0x50 ;Call text services
 ret ;Return to C code

_GetChar:
.Le1:
 mov ax, 0x02
 int 0x50
 ;cmp al, 0
 ;je .Le1
 ret

StrN1 db "Hello world! Type a letter:", 10, 0
StrN2 db 10, "You typed a letter!", 10, 0
(I have the infinite print string loop so that it almost garuantees it will be running an INT while a task switch occurs/IRQ0.

(INT handler)

Code: Select all

;Text mode services handler!

extern _ClearScreen
extern _PrintString
extern _GetChar

global _SRV_TextModeService

_SRV_TextModeService:
 cmp ax, 0x00 ;Clear Screen?
 je ClearScreenService ;Yes
 
 cmp ax, 0x01 ;Print String?
 je PrintStringService ;Yes
 
 cmp ax, 0x02 ;Getchar?
 je GetCharService ;Yes
 
 iret ;Invalid function, just return

ClearScreenService: ;Clear screen function
 call _ClearScreen ;Clear the screen (call C code)
 jmp ServiceCommonReturn

PrintStringService: ;Print string function
 push ebx ;Push argument to C code, pointer to string
 call _PrintString ;Print it (call C code)
 add esp, 4
 jmp ServiceCommonReturn

GetCharService:
.L1:
 xor eax, eax
 call _GetChar
 cmp al, 0
 je .L1
 jmp ServiceCommonReturn

ServiceCommonReturn:
 cli
 iret
(Task Switch Handler)

Code: Select all

global _ASM_TaskStub
extern _MT_SwitchTask
extern _CurrentCR3

;When called by an IRQ from processor, allows task switches
_ASM_TaskStub:
 cli
 pushad              ;Push all general purpose registers
 
 push ds             ;Push data segment
 push es             ;Push data segment 'e'
 push fs             ;Push data segment 'f'
 push gs             ;Push data segment 'g'
 
 mov eax, esp        ;Get current stack pointer
 push eax            ;Push it as argument to C function
 
 call _MT_SwitchTask ;Call 'C code' task scheduler
 
 add esp, 4          ;Clean up pushed argument to 'C code'
 
 mov esp, eax        ;Set new task's stack pointer. (EAX from C code return value)
 
 mov eax, [_CurrentCR3] ;Get CR3 from C code data
 mov cr3, eax        ;Set new CR3 for task
 
 pop gs              ;Pop off data segment 'g'
 pop fs              ;Pop off data segment 'f'
 pop es              ;Pop off data segment 'e'
 pop ds              ;Pop off data segmemt
 
 popad               ;Pop all general purpose registers
 iret                ;Interrupt Return. Installs EIP etc. of new task
Cjmovie

Re:Problems with INT services

Post by Cjmovie »

Also, somehow the code segment (Kernel one, 0x08) gets put into GS...The others, including the real code segment (in CS) is set correctly.
Cjmovie

Re:Problems with INT services

Post by Cjmovie »

Oi! Another one of those "I'm such an idiot" moments!

I redid all of my task switching code, and it worked perfect...until the stack was changed from where it left it! I had forgotten to save new ESP values on task switch....Anyways, still got good things done from the process, such as trap gates instead of interrupt gates, and some little things in my service code.
Cjmovie

Re:Problems with INT services

Post by Cjmovie »

I'm back to the first problem: GCC is cutting out some of my ASM, even though I clearly have declared it using "volatile". Here is what bochs says the code looks like:

Code: Select all

Next at t=9351387
(0) [0x01ff8000] 0018:00000000 (unk. ctxt): push ebp                  ; 55
<bochs:3> s
Next at t=9351388
(0) [0x01ff8001] 0018:00000001 (unk. ctxt): mov ebp, esp              ; 89e5
<bochs:4> s
Next at t=9351389
(0) [0x01ff8003] 0018:00000003 (unk. ctxt): mov ax, 0x1               ; 66b80100

<bochs:5> s
Next at t=9351390
(0) [0x01ff8007] 0018:00000007 (unk. ctxt): int 0x50                  ; cd50
<bochs:6> s
Next at t=9351391
(0) [0x00110ef0] 0008:c0000ef0 (unk. ctxt): pushad                    ; 60
<bochs:7> s
Next at t=9351392
(0) [0x00110ef1] 0008:c0000ef1 (unk. ctxt): push ds                   ; 1e
<bochs:8> s
Next at t=9351393
(0) [0x00110ef2] 0008:c0000ef2 (unk. ctxt): push es                   ; 06
<bochs:9> s
Next at t=9351394
(0) [0x00110ef3] 0008:c0000ef3 (unk. ctxt): push fs                   ; 0fa0
<bochs:10>
Here is the C source:

Code: Select all

void ClearScreen(){
 __asm__ __volatile__ ("mov %0, %%ax" : : "I" (0x00));
 __asm__ __volatile__ ("int $0x50");
}

void PrintString(char* c){
 __asm__ __volatile__ ("mov %0, %%ax" : : "I" (0x01));
 __asm__ __volatile__ ("mov %0, %%ebx" : : "i" (c));
 __asm__ __volatile__ ("int $0x50");
}


int Main(int argc, char* argv[]){
 PrintString("Hello World!");
 return 0;
}
Not really sure what's going on here :). It completly cuts out the MOV for EBX, which is where the pointer to the string should go. This makes it print out bogus data (which happens to be wherever EBX points to, in this case it being 0x00000000).
AR

Re:Problems with INT services

Post by AR »

At a guess, I'd suggest using "g"(c) instead of "i"(c). You may also want to combine that code together:

Code: Select all

__asm__ ("mov %0, %%eax\n\t"
       "mov %1, %%ebx\n\t"
       "int $0x50" : : "I"(0x01), "g"(c));
Or even:

Code: Select all

__asm__ ("int $0x50" : : "a"(0x01), "b"(c));
Cjmovie

Re:Problems with INT services

Post by Cjmovie »

Well this is interesting. It seems my "entry" directive in my link script was, in an odd way, being ignored. It was entering into the _ClearScreen_ Function, causing it to clear the screen every time without doing anything else.

I thought about it, so I moved the functions below Main and added declarations for them. Sure enough, it worked. Any idea why that's happening?

Link Script:
ENTRY(_Main)
phys = 0x00000000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)

}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
}
end = .;
}
Compile Batch File:
@echo off

gcc -c -ffreestanding -O Apps/Main.c -o Apps/Main.a

ld -T Apps/Shell.ld -o Apps/Shell.o.ld Apps/Main.a
objcopy -S -O binary Apps/Shell.o.ld Object/Shell.APP

bin\GenFileSys floppy.img Object\boot.bin Object\Kernel.KRNL Object\Shell.APP
bin\dd if=object\stage2.bin of=floppy.img obs=512 count=72 seek=2808
Thanks for your help though, my code looks a lot more pretty now :P. That, and it made me learn a new inline ASM format :).
AR

Re:Problems with INT services

Post by AR »

I'd say that has something to do with the objdump converting, you may want to link directly to a flat binary output.
Post Reply