But you don't need to put any extra bytes on the stack manually with the code above.
From user code, you would do this:
mov al,funcnumber
int 0x30

And from system code:
call function

If you would like to use eax as a parameter, you could have the interrupt handler be like this instead:
push ebp
mov ebp,esp
mov esp,
call l0
mov ,esp
leave
pop eax
iretd
l0:
push eax
push es
mov eax,
mov es,ax
mov eax,
movzx eax,byte es:
inc dword
pop es
mov eax,
xchg eax,
ret

This would be called in the following way from user code:
int 0x30
db funcnumber
Posted on 2003-07-20 07:29:44 by Sephiroth3

But you don't need to put any extra bytes on the stack manually with the code above.
From user code, you would do this:
mov al,funcnumber
int 0x30

And from system code:
call function

no, i can't do it like that - thats the problem i'm thinking about all the time. the int 0x30-call from ring0 puts eflags, cs, eip on the stack (12 bytes), a call function just eip (4 bytes), a int 0x30-call from ring3 even ss3, esp3, eflags, cs, eip - and switches the stacks. if i have parameters the would be once at esp+16 (when i preserve ebp) and once at esp+8 and once even somewhere else - the function doesn't know. furthermore: what if i have an external ring0 code - it can't call the function directly. but um... is there still a possibility?

using eax as function number seems no problem to me. the mov al,funcNo-instruction just needs 2 bytes. eax is "trashed" for the returnvalue anyway. but that's still a nice idea.

this is the code i'm using currently - i up to know i couldn't test it for ring3 since there are just ring0-things in my code now :):


syscall_handler_new:
cmp al,NUM_SYSCALLs
jge syscall_handler.end
sti ;[b]why is the interrupt-flag cleared when i call the interrupt?[/b]
movzx eax,al
test word [esp+4],0x0003 ;check cs for dpl
jnz @f ;ring3?
call dword [syscall_table_new+eax*4]
jmp syscall_handler.end
@@:
push ecx
push edx ;push on ring0-stack
xor ebx,ebx
mov bx,ss
mov ecx,esp
mov dx,[esp+16] ;ss3 (from taskswitch)
mov esp,[esp+12] ;esp3
mov ss,dx ;now on ring3-stack
push ebx ;save ring0-stack-pointer
push ecx
sub esp,4 ;redundant dword
call dword [syscall_table+eax*4] ;work on ring3-stack!
add esp,4
pop ecx
pop ss
mov esp,ecx ;back on ring0-stack
pop edx
pop ecx
syscall_handler.end:
iret
Posted on 2003-07-20 08:57:09 by hartyl
But since it calls it on the Ring 3 stack, the parameters will be in the right spot.

How about this?

syscall_handler_new:
cmp al,NUM_SYSCALLs
jae sch0
movzx eax,al
test byte ,2
jnz @f
push
popfd
pop
add esp,4
jmp
@@:
push ebp
mov ebp,esp
push eax
mov eax,
call SomehowGetSelectorBase
mov esp,eax
add esp,
xchg eax,
sti
call
push eax
lea eax,
sub eax,
mov ,eax
pop eax
leave
sch0:
iretd

See if that works.
Posted on 2003-07-20 12:39:43 by Sephiroth3
um.. have you typed down the code right now?
i have commented your code, i don't know everywhere what you're doing...
Originally posted by Sephiroth3


syscall_handler_new:
cmp al,NUM_SYSCALLs
jae sch0
movzx eax,al
test byte [esp+4],2 [b];the privilege-level check?[/b]
jnz @f
push [esp+8] [b];restore the flags[/b]
popfd
pop [esp+4] [b];get the eip and overwrite cs?![/b]
add esp,4 [b];correct stack again[/b]
jmp [syscall_table+eax*4] [b];jump to function... how to return? i guess with a iret[/b]
@@: [b];this is now the ring3-handler?[/b]
push ebp
mov ebp,esp
push eax
mov eax,[ebp+20] [b];is this ss3?[/b]
call SomehowGetSelectorBase [b];this sould be no problem[/b]
mov esp,eax
add esp,[ebp+16] [b];the address of parameters?[/b]
xchg eax,[ebp-4] [b];from here on i don't get it anymore...[/b]
sti
call [calltable+eax*4]
push eax
lea eax,[esp+4]
sub eax,[ebp-4]
mov [ebp+16],eax
pop eax
leave
sch0:
iretd



it's very nice when you write code for me - but it's even more helpful when you explain me how to do it. what did you intend with this code?
Posted on 2003-07-20 13:21:20 by hartyl
I was assuming that all of your R0 code was in the same code segment. If they aren't, a few changes are in order. I marked those changes with italics.

Okay, here goes...
Originally posted by Sephiroth3


syscall_handler_new:
cmp al,NUM_SYSCALLs
jae sch0
movzx eax,al
test byte [esp+4],2 ; yep, it's the privilege level check (you'll need the
jnz @f ; system to run at ring 1 for this, so you can trap stack faults with a
push [esp+8] ; ring 0 stack)
popfd
pop [esp+4] ; overwrites the flags with EIP
add esp,4 ; get rid of CS
[i]; if using far procedures, the above two lines are replaced with the following:
;xchg eax,[esp] ; save function number and get EIP
;xchg eax,[esp+4] ; overwrite CS with EIP
;xchg eax,[esp+8] ; overwrite flags with CS
;pop eax ; get function number back[/i]
jmp [syscall_table+eax*4] ; just return with a ret [i](or retf)[/i], since only the return address is on the stack now
@@:
push ebp
mov ebp,esp
push eax ; save function number
mov eax,[ebp+20] ; yup, it's ss3
call SomehowGetSelectorBase
mov esp,eax ; if your ss isn't at 0, just subtract the base first
add esp,[ebp+16] ; and esp3, now esp points to the parameters
xchg eax,[ebp-4] ; get the function number back, and save the ss base
sti
[i]; push cs[/i]
call [calltable+eax*4] ; call the function on the Ring 3 stack
push eax
lea eax,[esp+4]
sub eax,[ebp-4] ; subtract the saved ss base
mov [ebp+16],eax ; and store it
pop eax
leave ; restore esp and ebp
sch0:
iretd ; return to caller with the new esp
Posted on 2003-07-20 14:58:07 by Sephiroth3
erm... i gotta say that this one won't work either.
in the part for ring0 you get rid of the calling cs. what if the sysfunction is called outside of the kernel, i.e. with a different cs, i couldn't return to it anymore.
i still don't get your ring3-part. how are you doing? you seem to access the parameters by the linear address of em. actually i don't like this idea.
btw, how have you been writing this code? directly out of your head or are you developing an os too and been dealing with that problem?
but you don't need to break your head about my problems anymore. i think i'll keep my 20 bytes per call and let it as is.
Posted on 2003-07-21 14:22:10 by hartyl
It's just out of the top of my head (written in 5 minutes or so) :P
The reason I suggested to use your own SS was so you could have it be the same as DS and use pointers interchangeably, but it might not be a good idea after all... Anyway, if you uncomment the italicized code and remove the two lines above it, you should be able to call the system functions from Ring 0 code in different segment. Just return with a retf instead of a ret. You would have to save DS in the functions. And maybe prefix the indirect jump and call up there with cs:.
Posted on 2003-07-21 14:40:37 by Sephiroth3
i had not much time in the last days (and actually i don't feel like programming... - hating myself for that :))
but i've created a macro for my c-like-calling-convention. you know, i want to push (reverse) all arguments, put the funciton-number into al, call my sys-int and correct the stack. this is what i have, but theres one problem (following):



macro syscall funcNo, [arg]
{ common local argsize
argsize=0
reverse pushd arg
argsize=argsize+4
common mov al,funcNo
common int 0x30
if argsize>0
add esp,argsize
end if
}

calling like that:

syscall PrintDword,0xba5ec0de


the problem: this piece doesn't work for functions like



syscall BootLog


any solutions?

@Sephiroth3: ds=ss is what i want to do (not implemented yet...); i need the "compatibility" between pointers on stack/data-segment. i think that's what windows also does - but with paging to prevent the stack-pointer from moving to data-section.

greets, hartyl
Posted on 2003-08-05 13:34:21 by hartyl
in the last days i was working on a completely new approach of my system, a complete
redesign. i found the paging-mechanism is the only possibility to make a good memory-
management. finally i chose the flat memory model and it's now possible to design the
systemcalls completely different.

i've found 2 instructions that are just like *made for me* - like made for my purposes.
the instructions are sysenter and sysexit. the use some MSRs to transfer the execution
to ring0/ring3. the require the flat model to do that. this is how i'll do the syscalls:
- on initializing i set the cs:eip for a function in the os-code that will use the
sysenter/sysexit-instructions. the function number is still passed in eax (al).



push params
mov al,funcNo
call dword [execute_function]

execute_function:
dd ring3_execute ;that value will be set by the loader

;in the os-code
ring3_execute:
;al still has funcNo
;ebx becomes stackpointer
mov ebx,esp
pop edx ;the return address to ring3-app
sysenter ;transfer modifies cs:eip will transfer the execution
;into ring0. the destination is 0008:enter_ring0 and esp
;will get a dump-value like zero, but i'll backup it in ebx
enter_ring0:
mov esp,ebx
movzx eax,al
call dword [syscall_table+eax*4] ;edx musnt be changed here (and won't)
push edx ;the return address to ring3-app
push ecx ;value souldn't be changed
mov ecx,esp ;esp=ecx after transfer
mov edx,leave_ring0
sysexit ;transfer execution to 0018:edx, the new esp will be ecx and
;things will continue in ring3
leave_ring0:
pop ecx ;restore the value
ret ;the return address to ring3-app is still on the stack

-----------------------------------------------------------------------------------

in an ring0-app things won't look different, but things behind it will:
push params
mov al,funcNo
call dword [execute_function]

execute_function:
dd ring0_execute ;loader sets a different value for ring0/ring3 apps

ring0_execute:
movzx eax,al
jmp dword [syscall_table+eax*4] ;the ret in the function will return to the ring0-app


well, what do you think of that method? would it make the system insecure in any
point of view?
i'd like to get rid of the "functionNumber in al"-thingy, does anyone have an idea for that?

thanks all!
greets, hartyl
Posted on 2003-08-19 13:35:14 by hartyl