Files
MentOS/mentos/src/process/user.asm
T
Luigi Capogrosso 7d9085fecf Finish v0.3.0
2019-05-08 17:07:11 +02:00

83 lines
3.1 KiB
NASM

; MentOS, The Mentoring Operating system project
; @file user.asm
; @brief
; @copyright (c) 2019 This file is distributed under the MIT License.
; See LICENSE.md for details.
; Enter userspace (ring3) (from Ring 0, namely Kernel)
; Usage: enter_userspace(uintptr_t location, uintptr_t stack);
; On stack
; | stack |
; | location |
; | return address |
; | EBP | EBP
; | SS |
; | ESP |
; | EFLAGS |
; | CS |
; | EIP |
global enter_userspace ; Allows the C code to call enter_userspace(...).
enter_userspace:
push ebp ; Save current ebp
mov ebp, esp ; open a new stack frame
;==== Segment selector =====================================================
mov ax, 0x23
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; we don't need to worry about SS. it's handled by iret
;---------------------------------------------------------------------------
; We have to prepare the following stack before executing iret
; SS --> Segment selector
; ESP --> Stack address
; EFLAGS --> CPU state flgas
; CS --> Code segment
; EIP --> Entry point
;
;==== User data segmenet with bottom 2 bits set for ring3 ?=================
push 0x23 ; push SS on Kernel's stack
;---------------------------------------------------------------------------
;==== (ESP) Stack address ==================================================
mov eax, [ebp + 0xC] ; get uintptr_t stack
push eax ; push process's stack address on Kernel's stack
;---------------------------------------------------------------------------
;==== (EFLAGS) =============================================================
pushf ; push EFLAGS into Kernel's stack
pop eax ; pop EFLAGS into eax
or eax, 0x200 ; enable interrupt ?request ring3
push eax ; push new EFLAGS on Kernel's stack
;---------------------------------------------------------------------------
;==== (CS) Code Segment ====================================================
push 0x1B ;
;---------------------------------------------------------------------------
;==== (EIP) Entry point ====================================================
mov eax, [ebp + 0x8] ; get uintptr_t location
push eax ; push uintptr_t location on Kernel's stack
;---------------------------------------------------------------------------
iret ; interrupt return
; WE SHOULD NOT STILL BE HERE! :(
;==== Reset segment selector ===============================================
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
;---------------------------------------------------------------------------
add esp, 0x14 ; reset stack pointer (20 bytes)
pop ebp ; reset value of ebp
ret ; return to kernel code