For Programmers: Free Programming Magazines  


Home > Archive > A86 Assembler > July 2004 > [Source Code] Windows XP Home/Professional combined CD Boot Loader









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author [Source Code] Windows XP Home/Professional combined CD Boot Loader
wsw

2004-07-20, 8:55 pm

;=======================================
========================================
==
;=======================================
========================================
==
;=======================================
========================================
==
;
;[Source Code] Windows XP Home/Professional combined CD Boot Loader
;
;Disassembler: Source v7.0
;
;Tools: Turbo Assembler 4.1
; Turbo Linker Version 7.1.30.1
; EXE2BIN.EXE found in Windows XP c:\windows\system32
;
;Assemble
; tasm boot.asm
;
;Link
; tlink boot.obj,boot.exe
;
;Convert to BIN
; exe2bin boot.exe
;
;
;I do not know what compiler/assembler the M$ guy who wrote this used.
;Parts of the code seem like written in C language. I tried to translate
;those codes to C but failed. It must be a C compiler with extreme
;optimization ability to generate codes like this. Especially to declare
;an external label in assembly for a goto in a C function.(ReadSector,jc MemErr)
;Does anyone know how to declare an external label, please tell me.
;
;The machine code generated are exactly the same to the binary extracted
;from CD. Some conditional jumps(jc/je...) TASM generates are rel8, but rel16
;in original binary. I have to overwrite them with exact bytes to match the
;original binary.
;
;
;
;Have fun !!
;
;A bored engineer
;8 July 2004
;

..386
model tiny

INT8VECTOR equ 20h
PRIMARY_DIRECTORY_RECORD equ 09ch

DISK_ADDRESS_PACKET struc
SizeOfPacket db ?
Reserved db ?
NumOfBlock dw ?
Buffer dd ?
sBlockNumberL dd ?
sBlockNumberH dd ?
ends

IOS_DIRECTORY_RECORD struc
rec_length db ?
ext_attr_length db ?
extent dd ?
extent_bigendian dd ?
entsize dd ?
entsize_bigendian dd ?
date db 7 dup(?)
flags db ?
file_unit_size db ?
interleave db ?
volumn_sequence_number dd ?
entname_len db ?
entname db ?
ends

cdboot segment byte public use16 'CODE'
assume cs:cdboot, ds:cdboot

org 0

start:
cli
xor ax,ax
mov ss,ax
mov sp,7C00h
sti
mov ax,cs
mov ds,ax
push dx ; save drive number
call $+3
here:
pop si
sub si,offset here

jz short ipzero ; jump if IP=0
cmp si,7C00h
jne short Error1 ; error code 1 if IP != 7c00h
mov ax,cs
cmp ax,0
jne short Error2 ; error code 2 if cs != 0

db 0EAh ; jmp far to segment 7c0h
dw offset continue
dw 7c0h

ipzero:
mov byte ptr aCannotBoot+24h,'3' ; set error code 3
nop
mov ax,cs
cmp ax,7C0h
jne short Error3 ; error code 3 if not 7c0h:0

; cs must be 7c0h here
continue:
mov ax,cs
mov ds,ax
mov byte ptr aCannotBoot+24h,'4' ; set error code 4
nop
cmp dl,80h
jb short BootErr3 ; Jump if drive number < 80h,
; error 4
mov byte ptr aCannotBoot+24h,'5' ; set error code 5
nop
mov bx,offset MagicMark
mov ax,[bx]
cmp ax,0AA55h ; check magic mark
jne short BootErr3 ; Jump if not equal, error 5
jmp short SetupLoader
nop

Error1:
jmp short BootErr1
nop

Error2:
jmp short BootErr2
nop

Error3:
jmp short BootErr3
nop

SetupLoader:
pop dx
mov DriveNum,dl
push offset aBootfix ; param3, file name 'BOOTFIX.BIN'
push 11 ; param2, file name length
push 2000h ; param1, memory address to load
call LoadFile
;-------------------------------
;jb NoBootFix ; Jump if failed
db 0fh,82h
dw offset NoBootFix - offset Here1
Here1:
;-------------------------------
pusha
push ds
push es
mov dl,DriveNum

db 9Ah
dw 0, 2000h ; call bootfix 2000h:0

pop es
pop ds
popa ; Restore all regs

NoBootFix:
call ChooseOption ; display option message

push offset aSetupldr ; param3, file name 'SETUPLDR.BIN'
push 12 ; param2, file name length
push 2000h ; param1, memory address to load
call LoadFile
;-------------------------------
;jc short NTLDRErr ; Jump if failed
db 0fh,82h
dw offset NTLDRErr - offset Here2
Here2:
;-------------------------------
mov dl,DriveNum ; dl = drive number
xor ax,ax
push 2000h
push ax
retf ; go to 2000h:0 SETUPLDR, no return

BootErr1:
push si
mov bx,si
add bx,offset aCannotBoot+24h
mov byte ptr [bx],'1' ; Set error code 1
add si,offset aCannotBoot
jmp short ShowError
nop
BootErr2:
push si
mov bx,si
add bx,offset aCannotBoot+24h
mov byte ptr [bx],'2' ; 'Set error code 2
add si,offset aCannotBoot
jmp short ShowError
nop
BootErr3:
push 0
mov si,offset aCannotBoot ; error code 0
jmp short ShowError
nop
NTLDRErr:
push 0
mov si,offset aNoNTLDR ; NTLDR error
jmp short ShowError
nop
MemErr:
push 0
mov si,offset aMemError ; Memory error
jmp short ShowError
nop
ShowError:
call PrintStr
pop si
jmp Restart

;---------------------------------------------------------------------------

PrintStr:
lodsb ; read [si] to al
or al,al ; end of string ?
;-------------------------------
;jz PrintStr_ret ; Jump if end of string
db 0fh,84h
dw offset PrintStr_ret - offset Here3
Here3:
;-------------------------------
mov ah,0Eh
mov bx,7
int 10h ; Video display ah=functn 0Eh, print a character
jmp short short PrintStr
PrintStr_ret:
ret

;---------------------------------------------------------------------------

ChooseOption:
push si
mov si,offset aBootMessage
call PrintStr1
mov cx,80h ;

clearloop:
; clear all keystrokes
mov ah,1
int 16h ; check for key stroke
; get status, if zf=0 al=char
;-------------------------------
;jz short GetKey ; Jump if NO keystroke available
db 0fh,84h
dw offset GetKey - offset Here4
Here4:
;-------------------------------

mov ah,0 ;
int 16h ; Get keystroke
loop clearloop ; and discard

GetKey:
mov ah,0
int 16h

GetKey1:
cmp al,'A'
jl short GetKey ; Jump if < 'A' discard
cmp al,'z'
jg short GetKey ; Jump if > 'z' discard
dec al
and al,1Fh
cmp al,NumOfOptions
;-------------------------------
;jl short OptionAllowed ; Jump if < NumOfOptions
db 0fh,8ch
dw offset OptionAllowed - offset Here5
Here5:
;-------------------------------
jmp short GetKey

OptionAllowed:
mov OptionSelected,al
push ax
push bx
add al,'A'
mov ah,0Eh
mov bx,7
int 10h ; print the key out
pop bx
pop ax

mov ah,0
int 16h ; Get keystroke
cmp al,0Dh
;-------------------------------
;je short coret ; jump if 'enter' pressed
db 0fh,84h
dw offset coret - offset Here6
Here6:
;-------------------------------

push ax
mov al,8
mov ah,0Eh
mov bx,7
int 10h ; write char al
pop ax
jmp short GetKey1
coret:
pop si
ret

;---------------------------------------------------------------------------

PrintStr1:
push ax
push bx
psloop:
lodsb
cmp al,0
;-------------------------------
;je short psret
db 0fh,84h
dw offset psret - offset Here7
Here7:
;-------------------------------
mov ah,0Eh
mov bx,7
int 10h

jmp short psloop
psret:
pop bx
pop ax
ret

;---------------------------------------------------------------------------

Restart:
mov TimeCount[si],24h
cli
push es
xor ax,ax
mov es,ax

; save old int8 vector

mov bx,INT8VECTOR
mov ax,es:[bx]
mov OldInt8Off[si],ax
mov ax,es:[bx+2]
mov OldInt8Seg[si],ax
mov es:[bx],si
add word ptr es:[bx],offset int8isr
mov es:[bx+2],cs
pop es
sti ; Enable interrupts

WaitTimeOut:
cmp TimeCount[si],0
jne short WaitTimeOut ; continue till timeout

; restore int8 vector
cli
push es
xor ax,ax
mov es,ax
mov bx,INT8VECTOR
mov ax,OldInt8Off[si]
mov es:[bx],ax
mov ax,OldInt8Seg[si]
mov es:[bx+2],ax
pop es
sti ; Enable interrupts

; copy entire body to 2000h:0
push ds
push es
mov ax,2000h
mov es,ax
mov ax,cs
mov ds,ax
xor di,di
mov cx,800h
rep movsb
pop es
pop ds

db 0EAh
dw offset RestartPoint, 2000h ; jmp 2000h:RestartPoint

;-------------------
RestartPoint:
push es
mov ax,7c0h
mov es,ax
mov bx,0
mov ax,201h
mov cx,1
mov dx,80h
int 13h ; Disk dl=drive 0 ah=func 02h
; read sectors to memory es:bx
; al=#,ch=cyl,cl=sectr,dh=head
;-------------------------------
;jnc short readok ; Jump if carry=0
db 0fh,83h
dw offset readok - offset Here8
Here8:
;-------------------------------
deadloop:
jmp short deadloop
readok:
pop es
mov dl,80h

db 0EAh
dw 7C00h, 0 ; jmp far 0:7c00h


;-------- Timer ISR -------------
int8isr:
pushf
cli
cmp cs:TimeCount[si],0
;-------------------------------
;je short CountEnd ; Jump if TimeCount == 0
db 0fh,84h
dw offset CountEnd - offset Here9
Here9:
;-------------------------------
dec cs:TimeCount[si] ; decrese by 1
CountEnd:
popf
push cs:OldInt8Seg[si]
push cs:OldInt8Off[si]
retf ; back to original ISR


aCannotBoot db 'CDBOOT: Cannot boot from CD - Code: 0', 0Dh, 0Ah, 0
aNoNTLDR db 'CDBOOT: Couldn', 27h, 't find NTLDR', 0Dh, 0Ah, 0
aMemError db 'CDBOOT: Memory overflow error', 0Dh, 0Ah, 0

;---------------------------------------------------------------------------
;---------------------------------------------------------------------------

FindEntry proc near
mov byte ptr SegmentCrossing,0
nop
mov cx,BytesToReadL
cld ; Clear direction
xor bx,bx ; Zero register
xor dx,dx ; Zero register
loc_37:
mov si,DirName
mov dl,es:[bx]
cmp dl,0
;-------------------------------
;je loc_42 ; Jump if equal
db 0fh,84h
dw offset loc_42 - offset Here10
Here10:
;-------------------------------
mov ax,bx
add ax,21h
mov di,ax
push cx
xor cx,cx ; Zero register
mov cl,DirNameLen
repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di]
pop cx
;-------------------------------
;jz loc_51 ; Jump if zero
db 0fh,84h
dw offset loc_51 - offset Here10_1
Here10_1:
;-------------------------------
loc_39:
cmp dx,cx
;-------------------------------
;jae loc_46 ; Jump if above or =
db 0fh,83h
dw offset loc_46 - offset Here10_2
Here10_2:
;-------------------------------
sub cx,dx
cmp byte ptr SegmentCrossing,1
;-------------------------------
;je loc_43 ; Jump if equal
db 0fh,84h
dw offset loc_43 - offset Here10_3
Here10_3:
;-------------------------------
loc_41:
add dx,bx
mov bx,dx
and bx,0Fh
push cx
mov cl,4
shr dx,cl ; Shift w/zeros fill
pop cx
mov ax,es
add ax,dx
mov es,ax
jmp short loc_37
loc_42:
mov dx,1
jmp short loc_39
loc_43:
inc cx
mov byte ptr SegmentCrossing,0
nop
jmp short loc_41
loc_45:
mov byte ptr SegmentCrossing,1
nop
jmp short loc_49
nop
loc_46:
cmp BytesToReadH,0
;-------------------------------
;jne loc_47 ; Jump if not equal
db 0fh,85h
dw offset loc_47 - offset Here11
Here11:
;-------------------------------
stc ; Set carry flag
retn
loc_47:
sub BytesToReadH,1
add bx,dx
push bx
push cx
mov cl,4
shr bx,cl ; Shift w/zeros fill
pop cx
mov ax,es
add ax,bx
mov es,ax
pop bx
and bx,0Fh
sub dx,cx
jz loc_45 ; Jump if zero
dec dx
loc_49:
mov ax,0FFFFh
sub ax,dx
mov cx,ax
jmp loc_37
loc_51:
cmp byte ptr FindDirEntry,1
;-------------------------------
;je loc_52 ; Jump if equal
db 0fh,84h
dw offset loc_52 - offset Here12
Here12:
;-------------------------------
test byte ptr es:[bx+ IOS_DIRECTORY_RECORD.flags],2
jnz short loc_39 ; Jump if not zero
jmp short loc_53
nop
loc_52:
test byte ptr es:[bx+IOS_DIRECTORY_RECORD.flags],2
jz loc_39 ; Jump if zero
loc_53:
mov al,DirNameLen
cmp es:[bx+20h],al
jne loc_39 ; Jump if not equal
clc ; Clear carry flag
retn
FindEntry endp


;---------------------------------------------------------------------------
;---------------------------------------------------------------------------

ReadSectors proc near

PARAMETER_1 = 4 ; bp+4
PARAMETER_2 = 6 ; bp+6
PARAMETER_3 = 8 ; bp+8
PARAMETER_4 = 0Ah ; bp+0Ah
PARAMETER_5 = 0Ch ; bp+0Ch

push bp
mov bp,sp
push bx
push si
push dx
push ax
mov bx,offset dap
mov byte ptr [bx+DISK_ADDRESS_PACKET.SizeOfPacket],10h
mov byte ptr [bx+DISK_ADDRESS_PACKET.Reserved],0
mov byte ptr [bx+DISK_ADDRESS_PACKET.NumOfBlock+1],0
mov word ptr [bx+DISK_ADDRESS_PACKET.Buffer],0
mov word ptr [bx+DISK_ADDRESS_PACKET.sBlockNumberH],0
mov word ptr [bx+DISK_ADDRESS_PACKET.sBlockNumberH+2],0
mov ax,[bp+PARAMETER_5]
mov TotalBlockToReadL,ax
mov ax,[bp+PARAMETER_4]
mov TotalBlockToReadH,ax
mov ax,[bp+PARAMETER_3]
mov BufferAddr,ax
mov ax,[bp+PARAMETER_2]
mov BlockNumberL,ax
mov ax,[bp+PARAMETER_1]
mov BlockNumberH,ax
loc_56:
;-------------------------------
;cmp word ptr TotalBlockToReadH,0
db 81h,3eh
dw offset TotalBlockToReadH
dw 0
;-------------------------------
;-------------------------------
;jnz loc_58 ; Jump if not zero
db 0fh,85h
dw offset loc_58 - offset Here13
Here13:
;-------------------------------
;-------------------------------
;cmp TotalBlockToReadL,20h
db 81h,3eh
dw offset TotalBlockToReadL
dw 20h
;-------------------------------
;-------------------------------
;jg loc_58 ; Jump if >
db 0fh,8fh
dw offset loc_58 - offset Here13_1
Here13_1:
;-------------------------------
mov byte ptr fMoreBlocks,0
nop
mov ax,TotalBlockToReadL
mov BlockToRead,al
jmp short loc_59
nop
loc_58:
mov byte ptr fMoreBlocks,1
nop
mov byte ptr BlockToRead,20h ; ' '
nop
loc_59:
mov al,BlockToRead
mov byte ptr [bx+DISK_ADDRESS_PACKET.NumOfBlock],al
mov ax,BufferAddr
mov word ptr [bx+DISK_ADDRESS_PACKET.Buffer+2],ax
mov ax,BlockNumberL
mov word ptr [bx+DISK_ADDRESS_PACKET.sBlockNumberL],ax
mov ax,BlockNumberH
mov word ptr [bx+DISK_ADDRESS_PACKET.sBlockNumberL+2],ax
mov si,offset dap
mov ah,42h ; 'B'
mov dl,DriveNum
int 13h ; ??int non-standard interrupt
cmp byte ptr fMoreBlocks,1
;-------------------------------
;jne loc_61 ; Jump if not equal
db 0fh,85h
dw offset loc_61 - offset Here14
Here14:
;-------------------------------
sub TotalBlockToReadL,20h
sbb TotalBlockToReadH,0
add BufferAddr,1000h
jc MemErr
;-------------------------------
;add BlockNumberL,20h
db 81h,06h
dw offset BlockNumberL
dw 20h
;-------------------------------
;-------------------------------
;adc BlockNumberH,0
db 81h,16h
dw offset BlockNumberH
dw 0
;-------------------------------
jmp short loc_56
loc_61:
pop ax
pop dx
pop si
pop bx
mov sp,bp
pop bp
retn
ReadSectors endp


;---------------------------------------------------------------------------
;---------------------------------------------------------------------------

ReadToMemory proc near

PARAMETER_1 = 4 ; bp+4

push bp
mov bp,sp
push cx
push bx
push ax
mov cl,0Bh
mov bx,BytesToReadH
mov ax,BytesToReadL
shrd ax,bx,cl ; Double shift right
shr bx,cl ; Shift w/zeros fill
test BytesToReadL,7FFh
jz short loc_62 ; Jump if zero
add ax,1
adc bx,0
loc_62:
push ax ; PARAMETER_5
push bx ; PARAMETER_4
push word ptr [bp+PARAMETER_1] ; PARAMETER_3
push StartBlockL ; PARAMETER_2
push StartBlockH ; PARAMETER_1
call ReadSectors
add sp,0Ah
pop ax
pop bx
pop cx
mov sp,bp
pop bp
retn
ReadToMemory endp


;---------------------------------------------------------------------------
;---------------------------------------------------------------------------

GetSectorFromRecord proc near
push ax
mov ax,word ptr es:[bx+IOS_DIRECTORY_RECORD.extent]
mov StartBlockL,ax
mov ax,word ptr es:[bx+IOS_DIRECTORY_RECORD.extent+2]
mov StartBlockH,ax
mov ax,word ptr es:[bx+IOS_DIRECTORY_RECORD.entsize]
mov BytesToReadL,ax
mov ax,word ptr es:[bx+IOS_DIRECTORY_RECORD.entsize+2]
mov BytesToReadH,ax
pop ax
retn
GetSectorFromRecord endp


;---------------------------------------------------------------------------
;---------------------------------------------------------------------------

;LoadFile(BYTE* addr, BYTE namelen, char* filename);
LoadFile proc near

PARAMETER_1 = 4 ; bp+4
PARAMETER_2 = 6 ; bp+6
PARAMETER_3 = 8 ; bp+8

push bp
mov bp,sp
push 1 ; PARAMETER_5
push 0 ; PARAMETER_4
push 1000h ; PARAMETER_3
push 10h ; PARAMETER_2
push 0 ; PARAMETER_1
call ReadSectors
add sp,0Ah
mov ax,1000h
mov es,ax

mov ax,word ptr es:[PRIMARY_DIRECTORY_RECORD+IOS_DIRECTO
RY_RECORD.extent]
mov StartBlockL,ax
mov ax,word ptr es:[PRIMARY_DIRECTORY_RECORD+IOS_DIRECTO
RY_RECORD.extent+2]
mov StartBlockH,ax
mov ax,word ptr es:[PRIMARY_DIRECTORY_RECORD+IOS_DIRECTO
RY_RECORD.entsize]
mov BytesToReadL,ax
mov ax,word ptr es:[PRIMARY_DIRECTORY_RECORD+IOS_DIRECTO
RY_RECORD.entsize+2]
mov BytesToReadH,ax
push 1000h ; PARAMETER_1
call ReadToMemory
add sp,2
mov ax,0
mov al,OptionSelected
mul DirNameLength ; ax = data * al
add ax,offset OptionDirs
mov DirName,ax
mov byte ptr DirNameLen,4
nop
mov byte ptr FindDirEntry,1
nop
call FindEntry
jc short loc_64 ; Jump if carry Set
call GetSectorFromRecord
push 1000h ; PARAMETER_1
call ReadToMemory
add sp,2
mov ax,1000h
mov es,ax
mov ax,[bp+PARAMETER_3]
mov DirName,ax
mov al,[bp+PARAMETER_2]
mov DirNameLen,al
mov byte ptr FindDirEntry,0
nop
call FindEntry
jc short loc_64 ; Jump if carry Set
call GetSectorFromRecord
push word ptr [bp+PARAMETER_1] ; PARAMETER_1
call ReadToMemory
add sp,2
loc_64:
pop bp
retn
LoadFile endp


OldInt8Off dw 0 ; Data table (indexed access)
OldInt8Seg dw 0 ; Data table (indexed access)
TimeCount dw 24h ; Data table (indexed access)
dap dw 8 dup (0)
fMoreBlocks db 0
aSetupldr db 'SETUPLDR.BIN'
aBootfix db 'BOOTFIX.BIN'
aI386 db 'I386'
DriveNum db 0
StartBlockL dw 0
StartBlockH dw 0
BytesToReadL dw 0
BytesToReadH dw 0
TotalBlockToReadL dw 0
TotalBlockToReadH dw 0
BufferAddr dw 0
BlockNumberL dw 0
BlockNumberH dw 0
BlockToRead db 0
DirName dw 0
DirNameLen db 0
FindDirEntry db 0
SegmentCrossing db 0
aBootMessage db 0Dh, 0Ah
db '[A] Windows XP Home Edition - Traditional Chinese', 0Dh, 0Ah
db '[B] Windows XP Professional - Traditional Chinese', 0Dh, 0Ah
db 0Dh, 0Ah, 'Choose an option and press [Enter]: ', 0

OptionSelected db 0
NumOfOptions db 2
DirNameLength db 4
OptionDirs db 'XHTWXPTW'

org 7feh
MagicMark dw 0AA55h

cdboot ends

end start
;=======================================
========================================
==
;=======================================
========================================
==
;=======================================
========================================
==



Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com