Changes in kernel/arch/ia32/src/asm.S [eee047c:b5382d4f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/asm.S
reee047c rb5382d4f 1 # 2 # Copyright (c) 2001-2004 Jakub Jermar 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 29 ## very low and hardware-level functions 30 31 # Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error 32 # word and 1 means interrupt with error word 33 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00 1 /* 2 * Copyright (c) 2001 Jakub Jermar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * - The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** Very low and hardware-level functions 30 * 31 */ 32 33 /** 34 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int 35 * has no error word and 1 means interrupt with error word 36 * 37 */ 38 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00 39 40 #include <arch/pm.h> 41 #include <arch/mm/page.h> 34 42 35 43 .text 36 37 44 .global paging_on 38 45 .global enable_l_apic_in_msr … … 45 52 .global memcpy_to_uspace 46 53 .global memcpy_to_uspace_failover_address 47 48 49 # Wrapper for generic memsetb 54 .global early_putchar 55 56 /* Wrapper for generic memsetb */ 50 57 memsetb: 51 58 jmp _memsetb 52 59 53 # Wrapper for generic memsetw 60 /* Wrapper for generic memsetw */ 54 61 memsetw: 55 62 jmp _memsetw 56 63 57 58 #define MEMCPY_DST 4 59 #define MEMCPY_SRC 8 60 #define MEMCPY_SIZE 12 64 #define MEMCPY_DST 4 65 #define MEMCPY_SRC 8 66 #define MEMCPY_SIZE 12 61 67 62 68 /** Copy memory to/from userspace. … … 68 74 * or copy_to_uspace(). 69 75 * 70 * @param MEMCPY_DST(%esp) 71 * @param MEMCPY_SRC(%esp) 72 * @param MEMCPY_SIZE(%esp) 76 * @param MEMCPY_DST(%esp) Destination address. 77 * @param MEMCPY_SRC(%esp) Source address. 78 * @param MEMCPY_SIZE(%esp) Size. 73 79 * 74 80 * @return MEMCPY_DST(%esp) on success and 0 on failure. 81 * 75 82 */ 76 83 memcpy: 77 84 memcpy_from_uspace: 78 85 memcpy_to_uspace: 79 movl %edi, %edx 80 movl %esi, %eax 86 movl %edi, %edx /* save %edi */ 87 movl %esi, %eax /* save %esi */ 81 88 82 89 movl MEMCPY_SIZE(%esp), %ecx 83 shrl $2, %ecx 90 shrl $2, %ecx /* size / 4 */ 84 91 85 92 movl MEMCPY_DST(%esp), %edi 86 93 movl MEMCPY_SRC(%esp), %esi 87 94 88 rep movsl /* copy whole words */ 89 95 /* Copy whole words */ 96 rep movsl 97 90 98 movl MEMCPY_SIZE(%esp), %ecx 91 andl $3, %ecx 99 andl $3, %ecx /* size % 4 */ 92 100 jz 0f 93 101 94 rep movsb /* copy the rest byte by byte */ 95 96 0: 97 movl %edx, %edi 98 movl %eax, %esi 99 movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */ 100 ret 101 102 /* Copy the rest byte by byte */ 103 rep movsb 104 105 0: 106 107 movl %edx, %edi 108 movl %eax, %esi 109 110 /* MEMCPY_DST(%esp), success */ 111 movl MEMCPY_DST(%esp), %eax 112 ret 113 102 114 /* 103 115 * We got here from as_page_fault() after the memory operations … … 108 120 movl %edx, %edi 109 121 movl %eax, %esi 110 xorl %eax, %eax /* return 0, failure */ 122 123 /* Return 0, failure */ 124 xorl %eax, %eax 111 125 ret 112 126 113 ## Turn paging on 114 # 115 # Enable paging and write-back caching in CR0. 116 # 127 /** Turn paging on 128 * 129 * Enable paging and write-back caching in CR0. 130 * 131 */ 117 132 paging_on: 118 133 movl %cr0, %edx 119 orl $(1 << 31), %edx # paging on 120 # clear Cache Disable and not Write Though 134 orl $(1 << 31), %edx /* paging on */ 135 136 /* Clear Cache Disable and not Write Though */ 121 137 andl $~((1 << 30) | (1 << 29)), %edx 122 movl %edx, %cr0138 movl %edx, %cr0 123 139 jmp 0f 124 0: 125 ret 126 127 128 ## Enable local APIC 129 # 130 # Enable local APIC in MSR. 131 # 140 141 0: 142 ret 143 144 /** Enable local APIC 145 * 146 * Enable local APIC in MSR. 147 * 148 */ 132 149 enable_l_apic_in_msr: 133 150 movl $0x1b, %ecx … … 138 155 ret 139 156 140 # Clear nested flag 141 # overwrites %ecx 157 /** Clear nested flag 158 * 159 */ 142 160 .macro CLEAR_NT_FLAG 143 161 pushfl 144 162 andl $0xffffbfff, (%esp) 145 163 popfl 146 .endm 164 .endm 147 165 148 166 /* … … 158 176 sysenter_handler: 159 177 sti 160 pushl %ebp # remember user stack161 pushl %edi # remember return user address162 163 xorl %ebp, %ebp # stop stack traces here164 165 pushl %gs # remember TLS166 167 pushl %eax # syscall number168 subl $8, %esp # unused sixth and fifth argument169 pushl %esi # fourth argument170 pushl %ebx # third argument171 pushl %ecx # second argument172 pushl %edx # first argument173 178 pushl %ebp /* remember user stack */ 179 pushl %edi /* remember return user address */ 180 181 xorl %ebp, %ebp /* stop stack traces here */ 182 183 pushl %gs /* remember TLS */ 184 185 pushl %eax /* syscall number */ 186 subl $8, %esp /* unused sixth and fifth argument */ 187 pushl %esi /* fourth argument */ 188 pushl %ebx /* third argument */ 189 pushl %ecx /* second argument */ 190 pushl %edx /* first argument */ 191 174 192 movw $16, %ax 175 193 movw %ax, %ds 176 194 movw %ax, %es 177 195 178 196 cld 179 197 call syscall_handler 180 addl $28, %esp # remove arguments from stack 181 182 pop %gs # restore TLS 183 184 pop %edx # prepare return EIP for SYSEXIT 185 pop %ecx # prepare userspace ESP for SYSEXIT 186 187 sysexit # return to userspace 188 189 190 #define ISTATE_OFFSET_EAX 0 191 #define ISTATE_OFFSET_EBX 4 192 #define ISTATE_OFFSET_ECX 8 193 #define ISTATE_OFFSET_EDX 12 194 #define ISTATE_OFFSET_EDI 16 195 #define ISTATE_OFFSET_ESI 20 196 #define ISTATE_OFFSET_EBP 24 197 #define ISTATE_OFFSET_EBP_FRAME 28 198 #define ISTATE_OFFSET_EIP_FRAME 32 199 #define ISTATE_OFFSET_GS 36 200 #define ISTATE_OFFSET_FS 40 201 #define ISTATE_OFFSET_ES 44 202 #define ISTATE_OFFSET_DS 48 203 #define ISTATE_OFFSET_ERROR_WORD 52 204 #define ISTATE_OFFSET_EIP 56 205 #define ISTATE_OFFSET_CS 60 206 #define ISTATE_OFFSET_EFLAGS 64 207 #define ISTATE_OFFSET_ESP 68 208 #define ISTATE_OFFSET_SS 72 198 addl $28, %esp /* remove arguments from stack */ 199 200 pop %gs /* restore TLS */ 201 202 pop %edx /* prepare return EIP for SYSEXIT */ 203 pop %ecx /* prepare userspace ESP for SYSEXIT */ 204 205 sysexit /* return to userspace */ 206 207 #define ISTATE_OFFSET_EAX 0 208 #define ISTATE_OFFSET_EBX 4 209 #define ISTATE_OFFSET_ECX 8 210 #define ISTATE_OFFSET_EDX 12 211 #define ISTATE_OFFSET_EDI 16 212 #define ISTATE_OFFSET_ESI 20 213 #define ISTATE_OFFSET_EBP 24 214 #define ISTATE_OFFSET_EBP_FRAME 28 215 #define ISTATE_OFFSET_EIP_FRAME 32 216 #define ISTATE_OFFSET_GS 36 217 #define ISTATE_OFFSET_FS 40 218 #define ISTATE_OFFSET_ES 44 219 #define ISTATE_OFFSET_DS 48 220 #define ISTATE_OFFSET_ERROR_WORD 52 221 #define ISTATE_OFFSET_EIP 56 222 #define ISTATE_OFFSET_CS 60 223 #define ISTATE_OFFSET_EFLAGS 64 224 #define ISTATE_OFFSET_ESP 68 225 #define ISTATE_OFFSET_SS 72 209 226 210 227 /* 211 * Size of the istate structure without the hardware-saved part and without the 212 * error word. 213 */ 214 #define ISTATE_SOFT_SIZE 52 215 216 ## Declare interrupt handlers 217 # 218 # Declare interrupt handlers for n interrupt 219 # vectors starting at vector i. 220 # 221 # The handlers setup data segment registers 222 # and call exc_dispatch(). 223 # 224 #define INTERRUPT_ALIGN 256 228 * Size of the istate structure without the hardware-saved part 229 * and without the error word. 230 */ 231 #define ISTATE_SOFT_SIZE 52 232 233 /** Declare interrupt handlers 234 * 235 * Declare interrupt handlers for n interrupt 236 * vectors starting at vector i. 237 * 238 * The handlers setup data segment registers 239 * and call exc_dispatch(). 240 * 241 */ 242 #define INTERRUPT_ALIGN 256 243 225 244 .macro handler i n 226 227 .ifeq \i - 0x30 # Syscall handler 228 pushl %ds 229 pushl %es 230 pushl %fs 231 pushl %gs 232 233 # 234 # Push syscall arguments onto the stack 235 # 236 # NOTE: The idea behind the order of arguments passed in registers is to 237 # use all scratch registers first and preserved registers next. 238 # An optimized libc syscall wrapper can make use of this setup. 239 # 240 pushl %eax 241 pushl %ebp 242 pushl %edi 243 pushl %esi 244 pushl %ebx 245 pushl %ecx 246 pushl %edx 247 248 # we must fill the data segment registers 249 movw $16, %ax 250 movw %ax, %ds 251 movw %ax, %es 252 253 xorl %ebp, %ebp 254 255 cld 256 sti 257 # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) 258 call syscall_handler 259 cli 260 261 movl 20(%esp), %ebp # restore EBP 262 addl $28, %esp # clean-up of parameters 263 264 popl %gs 265 popl %fs 266 popl %es 267 popl %ds 268 269 CLEAR_NT_FLAG 270 iret 271 .else 272 /* 273 * This macro distinguishes between two versions of ia32 exceptions. 274 * One version has error word and the other does not have it. 275 * The latter version fakes the error word on the stack so that the 276 * handlers and istate_t can be the same for both types. 277 */ 278 .iflt \i - 32 279 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST 280 # 281 # Exception with error word: do nothing 282 # 283 .else 284 # 285 # Exception without error word: fake up one 286 # 287 pushl $0 288 .endif 289 .else 290 # 291 # Interrupt: fake up one 292 # 293 pushl $0 294 .endif 295 296 subl $ISTATE_SOFT_SIZE, %esp 297 298 # 299 # Save the general purpose registers. 300 # 301 movl %eax, ISTATE_OFFSET_EAX(%esp) 302 movl %ebx, ISTATE_OFFSET_EBX(%esp) 303 movl %ecx, ISTATE_OFFSET_ECX(%esp) 304 movl %edx, ISTATE_OFFSET_EDX(%esp) 305 movl %edi, ISTATE_OFFSET_EDI(%esp) 306 movl %esi, ISTATE_OFFSET_ESI(%esp) 307 movl %ebp, ISTATE_OFFSET_EBP(%esp) 308 309 # 310 # Save the selector registers. 311 # 312 movl %gs, %eax 313 movl %fs, %ebx 314 movl %es, %ecx 315 movl %ds, %edx 316 317 movl %eax, ISTATE_OFFSET_GS(%esp) 318 movl %ebx, ISTATE_OFFSET_FS(%esp) 319 movl %ecx, ISTATE_OFFSET_ES(%esp) 320 movl %edx, ISTATE_OFFSET_DS(%esp) 321 322 # 323 # Switch to kernel selectors. 324 # 325 movl $16, %eax 326 movl %eax, %ds 327 movl %eax, %es 328 329 # 330 # Imitate a regular stack frame linkage. 331 # Stop stack traces here if we came from userspace. 332 # 333 cmpl $8, ISTATE_OFFSET_CS(%esp) 334 jz 0f 335 xorl %ebp, %ebp 336 0: movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp) 337 movl ISTATE_OFFSET_EIP(%esp), %eax 338 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 339 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 340 341 cld 342 343 pushl %esp # pass istate address 344 pushl $(\i) # pass intnum 345 call exc_dispatch # exc_dispatch(intnum, istate) 346 addl $8, %esp # Clear arguments from the stack 347 348 CLEAR_NT_FLAG 349 350 # 351 # Restore the selector registers. 352 # 353 movl ISTATE_OFFSET_GS(%esp), %eax 354 movl ISTATE_OFFSET_FS(%esp), %ebx 355 movl ISTATE_OFFSET_ES(%esp), %ecx 356 movl ISTATE_OFFSET_DS(%esp), %edx 357 358 movl %eax, %gs 359 movl %ebx, %fs 360 movl %ecx, %es 361 movl %edx, %ds 362 363 # 364 # Restore the scratch registers and the preserved registers the handler 365 # cloberred itself (i.e. EBX and EBP). 366 # 367 movl ISTATE_OFFSET_EAX(%esp), %eax 368 movl ISTATE_OFFSET_EBX(%esp), %ebx 369 movl ISTATE_OFFSET_ECX(%esp), %ecx 370 movl ISTATE_OFFSET_EDX(%esp), %edx 371 movl ISTATE_OFFSET_EBP(%esp), %ebp 372 373 addl $(ISTATE_SOFT_SIZE + 4), %esp 374 iret 375 .endif 376 377 .align INTERRUPT_ALIGN 378 .if (\n- \i) - 1 379 handler "(\i + 1)", \n 380 .endif 245 .ifeq \i - 0x30 246 /* Syscall handler */ 247 pushl %ds 248 pushl %es 249 pushl %fs 250 pushl %gs 251 252 /* 253 * Push syscall arguments onto the stack 254 * 255 * NOTE: The idea behind the order of arguments passed 256 * in registers is to use all scratch registers 257 * first and preserved registers next. An optimized 258 * libc syscall wrapper can make use of this setup. 259 * 260 */ 261 pushl %eax 262 pushl %ebp 263 pushl %edi 264 pushl %esi 265 pushl %ebx 266 pushl %ecx 267 pushl %edx 268 269 /* We must fill the data segment registers */ 270 movw $16, %ax 271 movw %ax, %ds 272 movw %ax, %es 273 274 xorl %ebp, %ebp 275 276 cld 277 sti 278 279 /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */ 280 call syscall_handler 281 cli 282 283 movl 20(%esp), %ebp /* restore EBP */ 284 addl $28, %esp /* clean-up of parameters */ 285 286 popl %gs 287 popl %fs 288 popl %es 289 popl %ds 290 291 CLEAR_NT_FLAG 292 iret 293 .else 294 /* 295 * This macro distinguishes between two versions of ia32 296 * exceptions. One version has error word and the other 297 * does not have it. The latter version fakes the error 298 * word on the stack so that the handlers and istate_t 299 * can be the same for both types. 300 */ 301 .iflt \i - 32 302 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST 303 /* 304 * Exception with error word: do nothing 305 */ 306 .else 307 /* 308 * Exception without error word: fake up one 309 */ 310 pushl $0 311 .endif 312 .else 313 /* 314 * Interrupt: fake up one 315 */ 316 pushl $0 317 .endif 318 319 subl $ISTATE_SOFT_SIZE, %esp 320 321 /* 322 * Save the general purpose registers. 323 */ 324 movl %eax, ISTATE_OFFSET_EAX(%esp) 325 movl %ebx, ISTATE_OFFSET_EBX(%esp) 326 movl %ecx, ISTATE_OFFSET_ECX(%esp) 327 movl %edx, ISTATE_OFFSET_EDX(%esp) 328 movl %edi, ISTATE_OFFSET_EDI(%esp) 329 movl %esi, ISTATE_OFFSET_ESI(%esp) 330 movl %ebp, ISTATE_OFFSET_EBP(%esp) 331 332 /* 333 * Save the selector registers. 334 */ 335 movl %gs, %eax 336 movl %fs, %ebx 337 movl %es, %ecx 338 movl %ds, %edx 339 340 movl %eax, ISTATE_OFFSET_GS(%esp) 341 movl %ebx, ISTATE_OFFSET_FS(%esp) 342 movl %ecx, ISTATE_OFFSET_ES(%esp) 343 movl %edx, ISTATE_OFFSET_DS(%esp) 344 345 /* 346 * Switch to kernel selectors. 347 */ 348 movl $16, %eax 349 movl %eax, %ds 350 movl %eax, %es 351 352 /* 353 * Imitate a regular stack frame linkage. 354 * Stop stack traces here if we came from userspace. 355 */ 356 cmpl $8, ISTATE_OFFSET_CS(%esp) 357 jz 0f 358 xorl %ebp, %ebp 359 360 0: 361 362 movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp) 363 movl ISTATE_OFFSET_EIP(%esp), %eax 364 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 365 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 366 367 cld 368 369 pushl %esp /* pass istate address */ 370 pushl $(\i) /* pass intnum */ 371 372 /* Call exc_dispatch(intnum, istate) */ 373 call exc_dispatch 374 375 addl $8, %esp /* clear arguments from the stack */ 376 377 CLEAR_NT_FLAG 378 379 /* 380 * Restore the selector registers. 381 */ 382 movl ISTATE_OFFSET_GS(%esp), %eax 383 movl ISTATE_OFFSET_FS(%esp), %ebx 384 movl ISTATE_OFFSET_ES(%esp), %ecx 385 movl ISTATE_OFFSET_DS(%esp), %edx 386 387 movl %eax, %gs 388 movl %ebx, %fs 389 movl %ecx, %es 390 movl %edx, %ds 391 392 /* 393 * Restore the scratch registers and the preserved 394 * registers the handler cloberred itself 395 * (i.e. EBX and EBP). 396 */ 397 movl ISTATE_OFFSET_EAX(%esp), %eax 398 movl ISTATE_OFFSET_EBX(%esp), %ebx 399 movl ISTATE_OFFSET_ECX(%esp), %ecx 400 movl ISTATE_OFFSET_EDX(%esp), %edx 401 movl ISTATE_OFFSET_EBP(%esp), %ebp 402 403 addl $(ISTATE_SOFT_SIZE + 4), %esp 404 iret 405 406 .endif 407 408 .align INTERRUPT_ALIGN 409 .if (\n - \i) - 1 410 handler "(\i + 1)", \n 411 .endif 381 412 .endm 382 413 383 # keep in sync with pm.h !!! 384 IDT_ITEMS = 64 414 /* Keep in sync with pm.h! */ 415 #define IDT_ITEMS 64 416 385 417 .align INTERRUPT_ALIGN 386 418 interrupt_handlers: 387 h_start: 388 handler 0 IDT_ITEMS 389 h_end: 419 h_start: 420 handler 0 IDT_ITEMS 421 h_end: 422 423 /** Print Unicode character to EGA display. 424 * 425 * If CONFIG_EGA is undefined or CONFIG_FB is defined 426 * then this function does nothing. 427 * 428 * Since the EGA can only display Extended ASCII (usually 429 * ISO Latin 1) characters, some of the Unicode characters 430 * can be displayed in a wrong way. Only the newline character 431 * is interpreted, all other characters (even unprintable) are 432 * printed verbatim. 433 * 434 * @param %ebp+0x08 Unicode character to be printed. 435 * 436 */ 437 early_putchar: 438 439 #if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB))) 440 441 /* Prologue, save preserved registers */ 442 pushl %ebp 443 movl %esp, %ebp 444 pushl %ebx 445 pushl %esi 446 pushl %edi 447 448 movl $(PA2KA(0xb8000)), %edi /* base of EGA text mode memory */ 449 xorl %eax, %eax 450 451 /* Read bits 8 - 15 of the cursor address */ 452 movw $0x3d4, %dx 453 movb $0xe, %al 454 outb %al, %dx 455 456 movw $0x3d5, %dx 457 inb %dx, %al 458 shl $8, %ax 459 460 /* Read bits 0 - 7 of the cursor address */ 461 movw $0x3d4, %dx 462 movb $0xf, %al 463 outb %al, %dx 464 465 movw $0x3d5, %dx 466 inb %dx, %al 467 468 /* Sanity check for the cursor on screen */ 469 cmp $2000, %ax 470 jb early_putchar_cursor_ok 471 472 movw $1998, %ax 473 474 early_putchar_cursor_ok: 475 476 movw %ax, %bx 477 shl $1, %eax 478 addl %eax, %edi 479 480 movl 0x08(%ebp), %eax 481 482 cmp $0x0a, %al 483 jne early_putchar_print 484 485 /* Interpret newline */ 486 487 movw %bx, %ax /* %bx -> %dx:%ax */ 488 xorw %dx, %dx 489 490 movw $80, %cx 491 idivw %cx, %ax /* %dx = %bx % 80 */ 492 493 /* %bx <- %bx + 80 - (%bx % 80) */ 494 addw %cx, %bx 495 subw %dx, %bx 496 497 jmp early_putchar_newline 498 499 early_putchar_print: 500 501 /* Print character */ 502 503 movb $0x0e, %ah /* black background, yellow foreground */ 504 stosw 505 inc %bx 506 507 early_putchar_newline: 508 509 /* Sanity check for the cursor on the last line */ 510 cmp $2000, %bx 511 jb early_putchar_no_scroll 512 513 /* Scroll the screen (24 rows) */ 514 movl $(PA2KA(0xb80a0)), %esi 515 movl $(PA2KA(0xb8000)), %edi 516 movl $1920, %ecx 517 rep movsw 518 519 /* Clear the 24th row */ 520 xorl %eax, %eax 521 movl $80, %ecx 522 rep stosw 523 524 /* Go to row 24 */ 525 movw $1920, %bx 526 527 early_putchar_no_scroll: 528 529 /* Write bits 8 - 15 of the cursor address */ 530 movw $0x3d4, %dx 531 movb $0xe, %al 532 outb %al, %dx 533 534 movw $0x3d5, %dx 535 movb %bh, %al 536 outb %al, %dx 537 538 /* Write bits 0 - 7 of the cursor address */ 539 movw $0x3d4, %dx 540 movb $0xf, %al 541 outb %al, %dx 542 543 movw $0x3d5, %dx 544 movb %bl, %al 545 outb %al, %dx 546 547 /* Epilogue, restore preserved registers */ 548 popl %edi 549 popl %esi 550 popl %ebx 551 leave 552 553 #endif 554 555 ret 390 556 391 557 .data
Note:
See TracChangeset
for help on using the changeset viewer.