帮Holly Bull晒一晒汇编

这是大牛某天折腾黑苹果时不爽,花了半天工夫自己炮制的,主要时间都花在挑选指令上了,字节数太多的指令不能用,也不能写太多指令。能看出来是啥吗?

;
; For extended disk access: 1int 13h ah = 42h
;
struc extended_disk_access_block

sizeof_block: resb 1
reserved: resb 1
number_of_sectors: resw 1
buffer_offset: resw 1
buffer_seg: resw 1
start_sector_number: resq 1

endstruc ; extended_disk_access_block

;
; Partition table entry format
;

struc partition_table_entry

boot_flag: resb 1
begin_cylin: resb 1
begin_head: resb 1
begin_sector: resb 1
partition_type: resb 1
end_cylin: resb 1
end_head: resb 1
end_sector: resb 1
lba_offset: resd 1
lba_number_of_sectors: resd 1

endstruc ; partition_table_entry

bits 16

org 7c00h

section .text

start_point:

; Move self to high memory; set ss:sp to 9000:7000

xor ax, ax
mov ds, ax

mov ax, 9000h
mov es, ax
mov ss, ax
mov sp, 7000h

mov di, start_point
mov si, start_point
mov cx, 200h
rep movsb

push es
pop ds

push es
mov ax, real_start
push ax
retf

real_start:

; Prompt for boot

prompt_for_boot:

lea si, [input_prompt]
call display_string

wait_for_select:

mov ah, 0
int 16h

mov [crlf], al
lea si, [crlf]
call display_string

;
; verify_select: 0 – 3 in AL, then save to [crlf]
;

mov al, [crlf]

sub al, ‘0’

cmp al, 0
jb prompt_for_boot

cmp al, 3
ja prompt_for_boot

mov [crlf], al

;
; Check partition table for select
;

mov al, 0
mov bx, 7dbeh

check_bootable:
cmp al, [crlf]
jnz set_not_boot

mov byte [bx], 80h
jmp next_partition_entry

set_not_boot:
mov byte [bx], 0

next_partition_entry:

add bx, partition_table_entry_size
inc al

cmp al, 4
jz write_mbr_back
jmp check_bootable

write_mbr_back:

mov ax, 0301h
mov bx, 7c00h
mov cx, 0001h
mov dx, 0080h
int 13h

jnc calculate_partition_sector_offset
jmp write_mbr_error

calculate_partition_sector_offset:

;
; use ax as an index to calculate the absolute sector offset
;

mov al, [crlf]

cbw

mov bx, 7dbeh ; partition table

mov word [block+number_of_sectors], 1
mov word [block+buffer_offset], 7c00h
mov word [block+buffer_seg], 0
mov dword [block+start_sector_number+4], 0

mov cx, partition_table_entry_size
mul cx
add bx, ax
mov ecx, dword [bx+lba_offset] ; bx + sizeof(partition_table_entry) * ax + lba_offset

mov [block+start_sector_number], ecx

;
; Read partition boot sector
;
mov ah, 42h
mov dl, 80h
lea si, [block]
int 13h
jc read_boot_sector_error

; Note I must keep [ds:si] to current partition entry, which is requireed by mac os x booter,
; while ds should be 0000

; clear everything and jump to boot sector

push 0
push 7c00h

; es -> 0000

xor ax, ax
mov es, ax

; move partition table from 9000:7dbe to 0000:7000

cld
mov si, 7dbeh
mov di, 7000h
mov cx, 4 * partition_table_entry_size
rep movsb

; si -> 7000
mov si, 7000h

mov al, [crlf]
cbw
mov cx, partition_table_entry_size
mul cx

add si, ax ; si -> current partition table entry

; ds -> 0000

push es
pop ds

; dl = 80H
mov dl, 80h

retf

write_mbr_error:
lea si, [write_mbr_error_msg]
jmp display_then_halt

read_boot_sector_error:
lea si, [read_boot_sector_error_msg]
jmp display_then_halt

display_then_halt:
call display_string

halt:
hlt
jmp halt

;
; Subroutine: display_string
;
; Entry: ds:si -> c string
;

display_string:

display_str_char:

lodsb
cmp al, 0
jz display_string_ret
call display_char

jmp display_str_char

display_string_ret:
retn

;
; Subroutine: Display char in AL
;
display_char:
mov bx, 1
mov ah, 0eh
int 10h
retn

; ————————————————————————-
; Data area
; ————————————————————————-

crlf db 20h, 0ah, 0dh, 0 ; A digit char, plus crlf

input_prompt db ‘Select boot partition(0-3):’, 0

; A block to contain extended_disk_access_block

block:
istruc extended_disk_access_block
at sizeof_block, db 10h
at reserved, db 0
iend

read_boot_sector_error_msg db ‘Read boot sector error’, 0
write_mbr_error_msg db ‘Write MBR failed’, 0

times 200h-2-$+start_point db 0

db 55h, 0aah

Leave a Reply

Your email address will not be published. Required fields are marked *