2019年8月1日 星期四

自製64位元作業系統17──64位元暫時版讀取程式

我們現在來製作一個暫時版的64位元檔案讀取系統。我們其實就是利用以前32位元版本的,把他改成支援64位元的地址。
# readInodeBlock64
# protect:
#  RBX RDI RBP
# STACK:
# +48 No. zero block LBA
# +40 read block count
# +32  block number (start from zero)
# +24  inode pos
# +16  address to put
# +8  return address
# +0  rbp
# Number Zero Block is at LBA 33
# Return Value: Total read block count

readInodeBlock64:
  pushq %rbp
  movq %rsp, %rbp

  pushq %rdi
  pushq %rbx

  movq 24(%rbp), %rbx
  movq 32(%rbp), %rdx
  movq 40(%rbp), %rcx
  movl 28(%rbx), %eax
  shr %rax

.riblock_loop:
  test %rcx, %rcx
  jz .riblock_ret_val
  cmp %rax, %rdx
  jge .riblock_ret_val
  cmp $12, %rdx
  jl .riblock_directBlocks
  cmp $268, %rdx
  jl .riblock_indirect
  cmp $65804, %rdx
  jl .riblock_db_indirect
  cmp $16843020, %rdx
  jl .riblock_tp_indirect
  jge .riblock_ret_val

# Current Register Status
# RAX 512 bytes block count
# RBX INODE POS
# RCX Counter
# RDX CURRENT BLOCK NO.
.riblock_directBlocks:
  pushq %rax
  pushq %rbx
  pushq %rcx
  pushq %rdx

  movl 40(%rbx, %rdx, 4), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx
  movq 16(%rbp), %rdi

  call readATA64

  movq %rdi, 16(%rbp)

  jmp .riblock_loop_end

.riblock_indirect:
  pushq %rax
  pushq %rbx
  pushq %rcx
  pushq %rdx

# ======================= STAGE I ==============================
  movl 88(%rbx), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx
  movq 16(%rbp), %rdi

  call readATA64

  movq (%rsp), %rdx
  movq 8(%rsp), %rcx
  movq 16(%rsp), %rbx
  movq 24(%rsp), %rax
# ======================= STAGE II ==============================
  movq 16(%rbp), %rdi
  subq $12, %rdx
  movl (%rdi, %rdx, 4), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx

  call readATA64

  movq %rdi, 16(%rbp)

  jmp .riblock_loop_end

.riblock_db_indirect:
  pushq %rax
  pushq %rbx
  pushq %rcx
  pushq %rdx

# ======================= STAGE I ==============================
  movl 92(%rbx), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx
  movq 16(%rbp), %rdi

  call readATA64

  movq (%rsp), %rdx
  movq 8(%rsp), %rcx
  movq 16(%rsp), %rbx
  movq 24(%rsp), %rax
# ======================= STAGE II ==============================
  movq 16(%rbp), %rdi
  subq $268, %rdx
  shrq $8, %rdx

  movl (%rdi, %rdx, 4), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx

  call readATA64

  movq (%rsp), %rdx
  movq 8(%rsp), %rcx
  movq 16(%rsp), %rbx
  movq 24(%rsp), %rax
# ======================= STAGE III ==============================
  movq 16(%rbp), %rdi
  subq $268, %rdx
  andq $256, %rdx

  movl (%rdi, %rdx, 4), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx

  call readATA64

  movq %rdi, 16(%rbp)

  jmp .riblock_loop_end

.riblock_tp_indirect:
  pushq %rax
  pushq %rbx
  pushq %rcx
  pushq %rdx

# ======================= STAGE I ==============================
  movl 96(%rbx), %edx
  movq 24(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx
  movq 16(%rbp), %rdi

  call readATA64

  movq (%rsp), %rdx
  movq 8(%rsp), %rcx
  movq 16(%rsp), %rbx
  movq 24(%rsp), %rax
# ======================= STAGE II ==============================
  movq 16(%rbp), %rdi
  subq $65804, %rdx
  shrq $16, %rdx

  movl (%rdi, %rdx, 4), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx

  call readATA64

  movq (%rsp), %rdx
  movq 8(%rsp), %rcx
  movq 16(%rsp), %rbx
  movq 24(%rsp), %rax
# ======================= STAGE III ==============================
  movq 16(%rbp), %rdi
  subq $65804, %rdx
  shrq $8, %rdx
  andq $256, %rdx

  movl (%rdi, %rdx, 4), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx

  call readATA64

  movq (%rsp), %rdx
  movq 8(%rsp), %rcx
  movq 16(%rsp), %rbx
  movq 24(%rsp), %rax
# ======================= STAGE IV ==============================
  movq 16(%rbp), %rdi
  subq $65804, %rdx
  andq $256, %rdx

  movl (%rdi, %rdx, 4), %edx
  movq 48(%rbp), %rbx
  shlq %rdx
  addq %rdx, %rbx
  movq $2, %rcx

  call readATA64

  movq %rdi, 16(%rbp)

  jmp .riblock_loop_end

.riblock_loop_end:

  popq %rdx
  popq %rcx
  popq %rbx
  popq %rax

  decq %rcx
  incq %rdx
  jmp .riblock_loop
.riblock_ret_val:
  movq 40(%rbp), %rax
  subq %rcx, %rax
.riblock_leave:
  popq %rbx
  popq %rdi

  leave
  ret
# ===============================================================================
# readATA64
# rbx = LBA 28 bits
# rcx = sectors to read count
# rdi = position to put
# ===============================================================================
readATA64:
  pushq %rdx
  movw $0x1F6, %dx
  movq %rbx, %rax
  shrq $24, %rax
  orb $0xE0, %al
  outb %al, %dx

  movw $0x1F2, %dx
  movb %cl, %al
  outb %al, %dx

  movw $0x1F3, %dx
  movq %rbx, %rax
  outb %al, %dx

  movw $0x1F4, %dx
  shrq $8, %rax
  outb %al, %dx

  movw $0x1F5, %dx
  shrq $8, %rax
  outb %al, %dx

  movw $0x1F7, %dx
  movb $0x20, %al
  outb %al, %dx

  .wait_ready:
    inb %dx, %al
    inb %dx, %al
    inb %dx, %al
    inb %dx, %al
    inb %dx, %al
    test $0x80, %al # BSY bit
    jnz .wait_ready
    test $0x1, %al # ERR bit
    jnz .wait_ready
    test $0x20, %al # DF bit
    jnz .wait_ready
    test $0x8, %al # DRQ bit
    jz .wait_ready

  # ecx * 512 / 2 = ecx * 256 = ecx << 8
  movq %rcx, %rax
  movq $256, %rcx
  movw $0x1F0, %dx
  rep insw

  movq %rax, %rcx
  movw $0x1F7, %dx
  loop .wait_ready
  popq %rdx
  ret

KERN_FILENAME:
  .asciz "kernel64.elf"
searchFile:
  pushq %rbx
  pushq %rcx
  pushq %rdx
  pushq %rsi
  pushq %rdi
  movq $0x1C00, %rbx
  movq $0x0, %rdx
  .loop_search_file:
    movl (%rbx, %rdx, 1), %eax
    cmp $0, %eax
    je .next_search_file
    movzbl 6(%rbx, %rdx, 1), %eax
    cmp $12, %eax         # kernel64.elf 12 bytes
    jne .next_search_file
    leaq 8(%rbx, %rdx, 1), %rdi
    leaq KERN_FILENAME, %rsi
    movq $10, %rcx
    repe cmpsb
    cmp $0, %rcx
    jne .next_search_file
    movl (%rbx, %rdx, 1), %eax
    jmp .search_file_exit
  .next_search_file:
    movzwq 4(%rbx, %rdx, 1), %rax
    addq %rax, %rdx
    cmp $0x400, %rdx
    jl .loop_search_file

  .search_file_end:
  movq $0, %rax

  .search_file_exit:
  popq %rdi
  popq %rsi
  popq %rdx
  popq %rcx
  popq %rbx
  ret

# =============================================================
# searchKernel : search kernel.elf
# =============================================================
searchKernel:
# Read superblock to 0x1000 and block descriptor table to 0x1400
  movq $34, %rbx
  movq $4, %rcx
  movq $0x1000, %rdi
  call readATA64

# Read INODE Table to find root directory
  movq 0x1408, %rbx
  addq $16, %rbx
  shlq %rbx
  movq $2, %rcx
  movq $0x1800, %rdi
  call readATA64

# block number zero
  movq $0x0, %rcx
  jmp .read_next_root_block

.searchKernel_Root_Block_Loop:
  pushq %rcx
  call searchFile
  popq %rcx
  cmp $0, %rax
  jne .found_kernel_inode
.read_next_root_block:
  pushq %rcx
  movq $32, %rax
  pushq %rax

  movq $1, %rax
  pushq %rax

  pushq %rcx

  movq $0x1880, %rax # Root Inode Position
  pushq %rax

  movq $0x1c00, %rax
  pushq %rax

  call readInodeBlock64

  addq $40, %rsp
  popq %rcx
  incq %rcx
  test %rax, %rax
  jnz .searchKernel_Root_Block_Loop
.kernel_not_found:
  hlt
.found_kernel_inode:
  decq %rax
  movq $0, %rdx
  divq 0x1000 + 40
  shlq $5, %rax
  movq 0x1408(%rax), %rbx
  addq $16, %rbx
  movq %rdx, %rax
  xorq %rdx, %rdx
  movq $8, %rcx
  divq %rcx
  addq %rax, %rbx
  shlq %rbx
  movq $2, %rcx
  movq $0x2000, %rdi
  call readATA64
  shlq $7, %rdx

  pushq %rdx
  movq $32, %rax
  pushq %rax

  movq $1, %rax
  pushq %rax

  movq $0, %rax
  pushq %rax

  leaq 0x2000(%rdx), %rax
  pushq %rax

  movq $0x10000, %rax
  pushq %rax
  call readInodeBlock64

  addq $40, %rsp
  popq %rdx

  movq %rdx, %rax
  ret

# RDX = INODE POS
readAllKernel:
  movzwq 0x10038, %rcx
  movq 0x10020, %rbx          # Program header start position
  leaq 0x10000(%rbx), %rbx
.load_elf_loop:
  pushq %rcx
  pushq %rdx

  movl (%rbx), %eax
  cmp $1, %rax
  je .load_elf
  popq %rdx
  jmp .add_elf_header
.load_elf:
  movq $32, %rax
  pushq %rax

  movq 0x20(%rbx), %rax
  test $0x3ff, %rax
  jz .load_less
  addq $0x400, %rax
  .load_less:
  shrq $10, %rax
  pushq %rax

  movq 8(%rbx), %rax
  shrq $10, %rax
  pushq %rax

  leaq 0x2000(%rdx), %rax
  pushq %rax

  movq 0x10(%rbx), %rax
  pushq %rax
  call readInodeBlock64

  addq $40, %rsp
  popq %rdx
  movq 0x8(%rbx), %rsi
  andq $1023, %rsi
  
  test %rsi, %rsi
  
  jz .add_elf_header
  movq 0x8(%rbx), %rsi
  movq 0x10(%rbx), %rdi
  addq %rdi, %rsi
  movq 0x20(%rbx), %rcx
  rep movsb
  .add_elf_header:

  popq %rcx
  addq $0x38, %rbx
  loop .load_elf_loop

  movq 0x10018, %rax
  ret




👉【幫我們一個忙!】👈

👋如果您喜歡這篇文章,請在下方按5個Like!
 ❤您的支持是我們最大的動力!

您只要登入帳號(Facebook、Google),在下方按5個Like,我們就會收到來自LikeCoin基金會的贊助。
您只需要支持我們,完全不會花到錢!