Simple Operating System
interrupts.asm
1 ;;
2 ; @file interrupts-asm.c
3 ; @brief Kernel's interruptions
4 ; @details About interrupts:
5 ; @details When interrupt handler is called on stack are: [esp]=old eip [esp+2]=old cs [esp+4] old flags
6 ; @details to use local interrupt's variables DS must be changed to local i.e. KERNEL_ADDRESS
7 ; @details all cs of interrupt handler are KERNEL_ADDRESS - only kernel should handle
8 ; @todo divZero is error handle, not only zero division https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#x86-Function-Attributes see error code
9 ;;
10 %include "lib.asm"
11 bits 16
12 global setInterrupts
13 global addInterrupt
14 extern __printf
15 ;;
16 ; @brief Set system interruptions
17 ; @details set syscall and errors handles
18 ;;
19 setInterrupts:
20  push ebp
21  mov ebp, esp
22  push ds
23 
24  ;handle 0 division
25  mov bx, 0
26  mov ds, bx
27  mov WORD[ds:bx+2], KERNEL_ADDRESS
28  mov WORD[ds:bx], divZero
29  ;handle syscall
30  mov bx, 0x20*4
31  mov WORD[ds:bx+2], KERNEL_ADDRESS
32  mov WORD[ds:bx], syscall
33 
34  pop ds
35  mov esp, ebp
36  pop ebp
37  ret
38 
39 ;;
40 ; @brief add interruption
41 ; @details set *(number*4)=function
42 ; @details set *(number*4+2)=KERNEL_ADDRESS - only kernel can handle interruptions
43 ; @param number new interruption number [ebp+8]
44 ; @param function interruption handler [ebp+12]
45 ;;
46 addInterrupt:
47  push ebp
48  mov ebp, esp
49  push ds
50 
51  mov bx, 0
52  mov ds, bx
53  mov ax, [ebp+8] ; set ax as parameter then ax*=4
54  mov bx, 4
55  mul bx
56  mov bx, ax
57  mov ax, WORD[ebp+12]
58  mov WORD[ds:bx], ax
59  mov WORD[ds:bx+2], KERNEL_ADDRESS
60 
61  pop ds
62  mov esp, ebp
63  pop ebp
64  ret
65 
66 ;;
67 ; @brief System interruption 0x20
68 ; @details it adds:
69 ; | AH | Description | AL | BX |
70 ; | :---: | :---------- | :-------- | :------------------------------------------------------------------- |
71 ; | 0 | putc() | character | |
72 ; | 1 | puts() | | address of string |
73 ; | 2 | puti() | | unsigned number |
74 ; | 3 | printf() | | address of first parameter on stack, next is 4B behind on stack etc. |
75 ;;
76 syscall:
77  enter 0, 0
78  ; system calls
79  cmp ah, 0
80  je .putc
81  cmp ah, 1
82  je .puts
83  cmp ah, 2
84  je .puti
85  cmp ah, 3
86  je .printf
87  ; if not recognised print message
88  setDS KERNEL_ADDRESS
89  push .message
90  call puts
91  add sp, 2
92  pop ds
93  jmp .exit
94  .message db "SYSCALL YAY!",0xa,0
95 
96  .putc:
97  ; al is character to put
98  xor ah, ah
99  push ax
100  call putc
101  add sp, 2
102  jmp .exit
103 
104  .puts:
105  ; bx is address of string to put
106  push bx
107  call puts
108  add sp, 2
109  jmp .exit
110 
111  .puti:
112  ; bx is number to print
113  push bx
114  call puti
115  add sp, 2
116  jmp .exit
117 
118  .printf:
119  push WORD 0
120  push bx
121  call DWORD __printf
122  jmp .exit
123  .exit:
124  leave
125  iret
126 
127 divZero:
128  ; zero division handler
129  dbg
130  setDS KERNEL_ADDRESS
131  push .err
132  call puts
133  add sp, 2
134  pop ds
135 
136  cmp esi, 0 ; when C divides it uses idiv - 3 byte and divides by esi
137  jne .Csrc
138  add WORD[esp], 2 ; if esi register is divider then add 2 and 1 byte
139  .Csrc: ; if it is 'normal' div add 2 bytes
140  add WORD[esp], 2
141 
142  mov ax, 1
143  iret
144  .err db "ERROR: Zero division!",0xa,0
145 
146 %include "boot/io.asm"