.code32 
.section .text

.global disable_interrupts
disable_interrupts:
    cli 
    ret

.global enable_interrupts
enable_interrupts:
    sti 
    ret

.global io_wait 
io_wait:
    outb %al, $0x80
    ret

.global liftoff
liftoff:
    cli

    mov 4(%esp), %ecx 
    mov 8(%esp), %ebx  

    mov $0x23, %ax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs

    pushl $0x23         # User Data Segment (SS)
    pushl %ebx          # User Stack Pointer (ESP)
    pushl $0x202        # EFLAGS (Interrupts enabled, bit 1 standard)
    pushl $0x1B         # User Code Segment (CS)
    pushl %ecx          # User Entry Point (EIP)

    xor %eax, %eax
    xor %ebx, %ebx
    xor %ecx, %ecx
    xor %edx, %edx
    xor %esi, %esi
    xor %edi, %edi
    xor %ebp, %ebp

    iret

.global outb
outb: 
    push %ebp
    mov %esp, %ebp

    # 8(%ebp) port
    # 12(%ebp) data
    mov 8(%ebp), %edx 
    mov 12(%ebp), %eax
    outb %al, %dx

    leave
    ret

.global inb
inb:
    push %ebp
    mov %esp, %ebp

    # 8(%ebp) port
    mov 8(%ebp), %edx 
    xor %eax, %eax
    inb %dx, %al

    leave 
    ret

.global insw 
insw:
    push %ebp
    mov %esp, %ebp 

    push %edi
    push %ecx 
    push %edx

    # 8(%ebp) addr
    # 12(%ebp) buf
    # 16(%ebp) sz
    mov 8(%ebp), %edx 
    mov 12(%ebp), %edi
    mov 16(%ebp), %ecx

    cld
    rep insw

    pop %edx
    pop %ecx
    pop %edi
    leave
    ret

.global outsw
outsw:
    push %ebp
    mov %esp, %ebp 

    push %esi
    push %ecx 
    push %edx

    # 8(%ebp) address
    # 12(%ebp) buf
    # 16(%ebp) sz
    mov 8(%ebp), %edx 
    mov 12(%ebp), %esi
    mov 16(%ebp), %ecx

    cld
    rep outsw

    pop %edx
    pop %ecx
    pop %esi
    leave
    ret

.global fetch_cr3
fetch_cr3: 
    mov %cr3, %eax 
    ret

.global kpanic
kpanic:
    cli
    hlt