Skip to content

Instantly share code, notes, and snippets.

@leventov
Created December 13, 2011 21:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leventov/1474068 to your computer and use it in GitHub Desktop.
Save leventov/1474068 to your computer and use it in GitHub Desktop.
lab4: protected mode with paging
.arch pentium4
.code16
.section .text
.org 0x100
_gdt: .quad 0
.byte 0xFF, 0xFF, 0, 0, 0xF, 0b10011010, 0b00001111, 0 # код
.byte 0xFF, 0xFF, 0, 0, 0xF, 0b10010000, 0b00001111, 0 # данные
.byte 0x00, 0x80, 0,0x80, 0xB, 0b10010010, 0b00000000, 0 # видео
.byte 0xFF, 0xFF, 0, 0, 9, 0b10010010, 0b00000000, 0 # стек, буфер
.byte 0x00, 0x10, 0, 0,0x12, 0b10010010, 0b00000000, 0 # каталог страниц
_gdt_size = . - _gdt
GDTR: .word _gdt_size - 1
.long 0x10000
_idt: .rept 0x20
.quad 0
.endr
.quad 0
.word i09_handler, 8, 0b1000011000000000, 0
.rept 0xF
.quad 0
.endr
.word i16_handler, 8, 0b1000011000000000, 0
_idt_size = . - _idt
IDTR: .word _idt_size - 1
.long 0x11000
start:
cli
lss %cs:STKPTR, %sp
sti
mov $0x0AA55, %di
mov $3, %bh
mov BEGSEG, %dx
lo:
mov %dx, %ds
cld
xor %si, %si
mov %ds:(%si), %ax
sub %di, %ax
jnz skipp
mov %ds:2, %ah
mov %ax, %cx
add %bh, %ah
not %bh
and %bh, %ah
not %bh
shr $3, %ax
add %ax, %dx
call scanbios
check: cmp $0xF000, %dx
jb lo
call init
call pm
call pg
sti
mov $0x18, %bx
mov %bx, %es
xor %ax, %ax
xor %di, %di
mov $2000, %cx # clear video memory of text mode
rep stosw
xor %di, %di
typing:
hlt
int $0x31
jz typing
# push word ptr COUNT
# push 1
# push dx
# push 1
# int 60h
# add sp, 8
# mov $0xE, %ah
# mov 1, %bx
# int $0x10
mov $0xF, %ah
stosw
jmp typing
skipp: add $0x80, %dx
jmp check
STKPTR: .word 0xFFFE,0x9000
BEGSEG: .word 0xC000
COUNT: .word 0x9000
PCO: .word 0x20
com_l: .byte 0xAA, 0x64, 0xAB, 0x64, 0xFF, 0x60, 0x11
ans_l: .byte 0x55, 0x11 ,0, 0x11, 0xFA, 0xAA, 0x11
pm:
mov %cs, %ax
mov %ax, %ds
mov $_gdt, %si
mov $0x1000, %ax
mov %ax, %es
xor %di, %di
mov $_gdt_size/4, %cx
cld
rep movsl
mov $_idt, %si
mov $0x1100, %ax
mov %ax, %es
xor %di, %di
mov $_idt_size/4, %cx
rep movsl
lgdt GDTR
lidt IDTR
# we do not assign interrupts at all (IDT is empty) -> so disable interrupts at all
cli # disable int#
inb $0x70
or $0x80, %al # disable NMI
outb $0x70
# turn on 16bit i80286+ protected mode
mov %cr0, %eax
or $0x00000001, %eax
mov %eax, %cr0
.byte 0xEA
.word next
.word 8
# load other segment registers
next: mov $0x18, %ax
mov %ax, %es
mov $0x20, %ax
mov %ax, %ds
mov %ax, %ss
inb $0x70
and $0x7F, %al # allow NMI
outb $0x70
sti # allow int#
ret
_pde: .byte 0b010000111, 0, 0, 0 #PS=1, U/S=1, R/W=1, P=1, base=0
pg:
mov $0x28, %ax
mov %ax, %es
mov %cs:_pde, %eax
xor %di, %di
stosl
mov $1023, %cx
xor %eax, %eax
rep stosl
mov $0x120000, %eax
mov %eax, %cr3
mov $1, %eax
shl $4, %eax # PSE=1 // 4th in cr4
mov %cr4, %ebx
or %eax, %ebx
mov %ebx, %cr4
shl $27, %eax # PG=1 //last in cr0
mov %cr0, %ebx
or %eax, %ebx
mov %ebx, %cr0
ret
scanbios:
xor %bl, %bl
chcksm:
lodsw
addb %ah, %al
addb %al, %bl
decw %cx
jnz chcksm
or %bl, %bl
jnz skip
pusha
push %ds
push %es
push %fs
push %gs
push %cs
pushw $__ret
push %ds
pushw $3
lret
__ret:
pop %gs
pop %fs
pop %es
pop %ds
popa
skip:
ret $0
.set P0, 0x20
.set P1, 0xA0
init:
mov $0x20, %al
outb $P0
outb $P1
mov $0b00010000, %al
outb $P0 #icw1 pic0
mov $0x20, %al
outb $P0 + 1 #icw2 pic0
mov 0b100, %al
outb $P0 + 1 #icw3 pic0
# mov al, 00010000b
# out 0A0h, al ;icw1 pic1
#
# mov al, 70h
# out 0A1h, al ;icw2 pic1
#
# mov al, 10b
# out 0A1h, al ;icw3 pic1
mov $0b11111101, %al
outb $P0 + 1 #ocw1 pic0
mov $com_l, %di
mov $ans_l, %si
w4: mov %cs:(%di), %bl
inc %di
cmp $0x11, %bl
jz kb_out
mov $0xFFF0, %cx
w40: inb $0x64
test $2, %al
jz w41
loop w40
jmp error
w41: mov %bl, %al
xor %dx, %dx
mov %cs:(%di), %ah
inc %di
cmp $0x64, %ah
jnz o60
outb $0x64
jmp l5
o60: outb $0x60
# out dx, al
l5: mov %cs:(%si), %bl
inc %si
cmp $0x11, %bl
jz w4
mov $0x2000, %cx
lo4: inb $0x64
test $1, %al
jz w42
inb $0x60
cmp %al, %bl
jz l5 # ok
jmp error
w42: loop lo4
jmp error
kb_out:
xor %ax, %ax
mov %ax, %es
cli
movw $i09_handler, %es:9*4
movw %cs, %es:9*4+2
movw $i16_handler, %es:0x16*4
movw %cs, %es:0x16*4+2
sti
mov %cs:COUNT, %ds # keyboard preparing
mov $1, %al
mov %al, %ds:0
mov $2, %al
mov %al, %ds:1
call timer_init
ret
error:
call wr
call stop
i09_handler:
push %ax
push %bx
push %cx
push %dx
push %si
push %ds
mov $0xAD, %al
outb $0x64
xor %ax, %ax
inb $0x60
test $0b10000000, %al
jnz rls
mov %cs:PCO, %ds
mov %ds:0, %dx
cmp %dl, %dh
jz rls
dec %ax
mov $alpha, %bx
add %ax, %bx
mov %cs:(%bx), %al
xor %cx, %cx
mov %al, %cl # shift randomizing
inb $0x42
test $1, %al
jz sss
xor $32, %cl
sss:
xor %ax, %ax
mov %dh, %al
mov %ax, %si
mov %cl, %ds:(%si)
inc %al
and $0b00011111, %al
jnz nz
mov $2, %al
nz: mov %al, %ds:1
rls:
mov $0x20, %al #eoi
outb $P0
mov $0xAE, %al #scan allow
outb $0x64
pop %ds
pop %si
pop %dx
pop %cx
pop %bx
pop %ax
iret
i16_handler:
lahf
push %dx
push %bx
push %si
push %ds
mov %ax, %bx
mov %cs:PCO, %ds
mov %ds:0, %dx
inc %dl
and $0b00011111, %dl
jnz norm
mov $2, %dl
norm: cmp %dl, %dh
jz sk4
xor %ax, %ax
mov %dl, %al
mov %dl, %ds:0
mov %ax, %si
mov %ds:(%si), %al
and $0b10111111, %bh
jmp sk5
sk4: or $0b1000000, %bh
sk5: mov %bh, %ss:12(%esp)
pop %ds
pop %si
pop %bx
pop %dx
iret
timer_init:
push %ax
inb $0x61
and $0b11111101, %al
or $0b00000001, %al
outb $0x61
mov $0b10110100, %al
outb $0x43
xor %al, %al
outb $0x42
mov $5, %al
outb $0x42
pop %ax
ret
wr:
push %cs
push $msg1
push $0
int $0x60
add $6, %sp
ret
msg1: .asciz "Error!!1"
stop:
cli
hlt
jmp stop
alpha: .ascii " 1234567890-+ "
.ascii "qwertyuiop[] "
.ascii "asdfghjkl;\"` "
.ascii "\\zxcvbnm,./ "
.ascii " "
.byte 0
# real startup entry begins at F000:FFF0
.org 0xFFF0
.byte 0xEA
.word start
.word 0xF000
.org 0xFFFE
.word 0x99FC
.end
.arch pentium4
.code16
.section .text
.org 0x100
_gdt: .quad 0
.byte 0xFF, 0xFF, 0, 0, 0xF, 0b10011010, 0b00001111, 0 # код
.byte 0xFF, 0xFF, 0, 0, 0xF, 0b10010000, 0b00001111, 0 # данные
.byte 0x00, 0x80, 0,0x80, 0xB, 0b10010010, 0b00000000, 0 # видео
.byte 0xFF, 0xFF, 0, 0, 9, 0b10010010, 0b00000000, 0 # стек, буфер
.byte 0x00, 0x10, 0, 0,0x12, 0b10010010, 0b00000000, 0 # каталог страниц
_gdt_size = . - _gdt
GDTR: .word _gdt_size - 1
.long 0x10000
_idt: .rept 0x20
.quad 0
.endr
.quad 0
.word i09_handler, 8, 0b1000011000000000, 0
.rept 0xF
.quad 0
.endr
.word i16_handler, 8, 0b1000011000000000, 0
_idt_size = . - _idt
IDTR: .word _idt_size - 1
.long 0x11000
start:
cli
lss %cs:STKPTR, %sp
sti
mov $0x0AA55, %di
mov $3, %bh
mov BEGSEG, %dx
lo:
mov %dx, %ds
cld
xor %si, %si
mov %ds:(%si), %ax
sub %di, %ax
jnz skipp
mov %ds:2, %ah
mov %ax, %cx
add %bh, %ah
not %bh
and %bh, %ah
not %bh
shr $3, %ax
add %ax, %dx
call scanbios
check: cmp $0xF000, %dx
jb lo
call init
call pm
call pg
sti
mov $0x18, %ax
mov %ax, %es
xor %bx, %bx
mov $0x7FFF, %ax
nan: mov %ax, %di
mov %bx, %es:(%di)
dec %ax
jnz nan
typing:
hlt
int $0x31
jz typing
# push word ptr COUNT
# push 1
# push dx
# push 1
# int 60h
# add sp, 8
# mov $0xE, %ah
# mov 1, %bx
# int $0x10
mov $0xF, %ah
mov %bx, %di
mov %ax, %es:(%di)
add $2, %bx
jmp typing
skipp: add $0x80, %dx
jmp check
STKPTR: .word 0xFFFE,0x9000
BEGSEG: .word 0xC000
COUNT: .word 0x9000
PCO: .word 0x20
com_l: .byte 0xAA, 0x64, 0xAB, 0x64, 0xFF, 0x60, 0x11
ans_l: .byte 0x55, 0x11 ,0, 0x11, 0xFA, 0xAA, 0x11
pm:
mov %cs, %ax
mov %ax, %ds
mov $_gdt, %si
mov $0x1000, %ax
mov %ax, %es
xor %di, %di
mov $_gdt_size/4, %cx
cld
rep movsl
mov $_idt, %si
mov $0x1100, %ax
mov %ax, %es
xor %di, %di
mov $_idt_size/4, %cx
rep movsl
lgdt GDTR
lidt IDTR
# we do not assign interrupts at all (IDT is empty) -> so disable interrupts at all
cli # disable int#
inb $0x70
or $0x80, %al # disable NMI
outb $0x70
# turn on 16bit i80286+ protected mode
mov %cr0, %eax
or $0x00000001, %eax
mov %eax, %cr0
.byte 0xEA
.word next
.word 8
# load other segment registers
next: mov $0x18, %ax
mov %ax, %es
mov $0x20, %ax
mov %ax, %ds
mov %ax, %ss
inb $0x70
and $0x7F, %al # allow NMI
outb $0x70
sti # allow int#
ret
_pde: .byte 0b010000111, 0, 0, 0 #PS=1, U/S=1, R/W=1, P=1, base=0
pg:
mov $0x28, %ax
mov %ax, %es
mov %cs:_pde, %eax
xor %di, %di
stosl
mov $1023, %cx
xor %eax, %eax
rep stosl
mov $0x120000, %eax
mov %eax, %cr3
mov $1, %eax
shl $4, %eax # PSE=1 // 4th in cr4
mov %cr4, %ebx
or %eax, %ebx
mov %ebx, %cr4
shl $27, %eax # PG=1 //last in cr0
mov %cr0, %ebx
or %eax, %ebx
mov %ebx, %cr0
ret
scanbios:
xor %bl, %bl
chcksm:
lodsw
addb %ah, %al
addb %al, %bl
decw %cx
jnz chcksm
or %bl, %bl
jnz skip
pusha
push %ds
push %es
push %fs
push %gs
push %cs
pushw $__ret
push %ds
pushw $3
lret
__ret:
pop %gs
pop %fs
pop %es
pop %ds
popa
skip:
ret $0
.set P0, 0x20
.set P1, 0xA0
init:
mov $0x20, %al
outb $P0
outb $P1
mov $0b00010000, %al
outb $P0 #icw1 pic0
mov $0x20, %al
outb $P0 + 1 #icw2 pic0
mov 0b100, %al
outb $P0 + 1 #icw3 pic0
# mov al, 00010000b
# out 0A0h, al ;icw1 pic1
#
# mov al, 70h
# out 0A1h, al ;icw2 pic1
#
# mov al, 10b
# out 0A1h, al ;icw3 pic1
mov $0b11111101, %al
outb $P0 + 1 #ocw1 pic0
mov $com_l, %di
mov $ans_l, %si
w4: mov %cs:(%di), %bl
inc %di
cmp $0x11, %bl
jz kb_out
mov $0xFFF0, %cx
w40: inb $0x64
test $2, %al
jz w41
loop w40
jmp error
w41: mov %bl, %al
xor %dx, %dx
mov %cs:(%di), %ah
inc %di
cmp $0x64, %ah
jnz o60
outb $0x64
jmp l5
o60: outb $0x60
# out dx, al
l5: mov %cs:(%si), %bl
inc %si
cmp $0x11, %bl
jz w4
mov $0x2000, %cx
lo4: inb $0x64
test $1, %al
jz w42
inb $0x60
cmp %al, %bl
jz l5 # ok
jmp error
w42: loop lo4
jmp error
kb_out:
xor %ax, %ax
mov %ax, %es
cli
movw $i09_handler, %es:9*4
movw %cs, %es:9*4+2
movw $i16_handler, %es:0x16*4
movw %cs, %es:0x16*4+2
sti
mov %cs:COUNT, %ds # keyboard preparing
mov $1, %al
mov %al, %ds:0
mov $2, %al
mov %al, %ds:1
call timer_init
ret
error:
call wr
call stop
i09_handler:
push %ax
push %bx
push %cx
push %dx
push %si
push %ds
mov $0xAD, %al
outb $0x64
xor %ax, %ax
inb $0x60
test $0b10000000, %al
jnz rls
mov %cs:PCO, %ds
mov %ds:0, %dx
cmp %dl, %dh
jz rls
dec %ax
mov $alpha, %bx
add %ax, %bx
mov %cs:(%bx), %al
xor %cx, %cx
mov %al, %cl # shift randomizing
inb $0x42
test $1, %al
jz sss
xor $32, %cl
sss:
xor %ax, %ax
mov %dh, %al
mov %ax, %si
mov %cl, %ds:(%si)
inc %al
and $0b00011111, %al
jnz nz
mov $2, %al
nz: mov %al, %ds:1
rls:
mov $0x20, %al #eoi
outb $P0
mov $0xAE, %al #scan allow
outb $0x64
pop %ds
pop %si
pop %dx
pop %cx
pop %bx
pop %ax
iret
i16_handler:
lahf
push %dx
push %bx
push %si
push %ds
mov %ax, %bx
mov %cs:PCO, %ds
mov %ds:0, %dx
inc %dl
and $0b00011111, %dl
jnz norm
mov $2, %dl
norm: cmp %dl, %dh
jz sk4
xor %ax, %ax
mov %dl, %al
mov %dl, %ds:0
mov %ax, %si
mov %ds:(%si), %al
and $0b10111111, %bh
jmp sk5
sk4: or $0b1000000, %bh
sk5: mov %bh, %ss:12(%esp)
pop %ds
pop %si
pop %bx
pop %dx
iret
timer_init:
push %ax
inb $0x61
and $0b11111101, %al
or $0b00000001, %al
outb $0x61
mov $0b10110100, %al
outb $0x43
xor %al, %al
outb $0x42
mov $5, %al
outb $0x42
pop %ax
ret
wr:
push %cs
push $msg1
push $0
int $0x60
add $6, %sp
ret
msg1: .asciz "Error!!1"
stop:
cli
hlt
jmp stop
alpha: .ascii " 1234567890-+ "
.ascii "qwertyuiop[] "
.ascii "asdfghjkl;\"` "
.ascii "\\zxcvbnm,./ "
.ascii " "
.byte 0
# real startup entry begins at F000:FFF0
.org 0xFFF0
.byte 0xEA
.word start
.word 0xF000
.org 0xFFFE
.word 0x99FC
.end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment