mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
908 lines
13 KiB
NASM
Executable file
908 lines
13 KiB
NASM
Executable file
;Loaded by the bootloader
|
|
;This will load the highlevel vmm code at the highest memory
|
|
;location possible, and setup the system to protected and paged mode
|
|
|
|
BITS 16
|
|
GLOBAL amain
|
|
amain:
|
|
|
|
;should be 3000:0000
|
|
;load vmm code into memory
|
|
;
|
|
;
|
|
jmp real_entry
|
|
|
|
|
|
column:
|
|
db 0
|
|
|
|
row:
|
|
db 0
|
|
|
|
display16:
|
|
;cl=byte to send
|
|
push ax
|
|
push dx
|
|
|
|
mov dl, byte [ds:bp+column-begin]
|
|
mov dh, byte [ds:bp+row-begin]
|
|
|
|
|
|
mov ax,0xb800
|
|
mov es,ax
|
|
|
|
mov al,dh
|
|
mov ah,160
|
|
imul ah ; ax=ah*al (row*160)
|
|
|
|
;add the column
|
|
push dx
|
|
and dx,0x00ff ;remove the row part of the dx register
|
|
shl dx,1 ;multiply by 2
|
|
add ax, dx
|
|
pop dx
|
|
|
|
xchg si,ax
|
|
|
|
;mov si,0
|
|
|
|
|
|
mov byte [es:si], cl ;//dl ;cl
|
|
mov byte [es:si+1], 15
|
|
|
|
;mov byte [es:si+2], dh
|
|
;mov byte [es:si+3], 15
|
|
|
|
xchg si,ax
|
|
|
|
|
|
inc dl
|
|
cmp dl, 80
|
|
jae nextrow
|
|
jmp display16_done
|
|
|
|
nextrow:
|
|
mov dl,0 ;set column to 0
|
|
inc dh ;go to next row
|
|
|
|
cmp dh,25
|
|
jb display16_done
|
|
|
|
mov dh,0
|
|
|
|
|
|
display16_done:
|
|
mov byte [ds:bp+column-begin], dl
|
|
mov byte [ds:bp+row-begin], dh
|
|
pop dx
|
|
pop ax
|
|
ret
|
|
|
|
|
|
;some 16-bit general purpose functions
|
|
sendstring16:
|
|
;ds:si=pointer to string
|
|
mov cl,[si]
|
|
call send16
|
|
|
|
inc si
|
|
cmp byte [si],'$'
|
|
jne sendstring16
|
|
ret
|
|
|
|
|
|
send16:
|
|
|
|
;param cl=byte to send
|
|
push ax
|
|
push dx
|
|
|
|
waitforready:
|
|
%ifdef SERIALPORT
|
|
%if SERIALPORT != 0
|
|
mov dx,SERIALPORT+5 ;3fdh
|
|
in al,dx
|
|
and al,0x20
|
|
cmp al,0x20
|
|
jne waitforready
|
|
|
|
mov dx,SERIALPORT ;0x3f8
|
|
mov al,cl
|
|
out dx,al
|
|
%endif
|
|
%endif
|
|
|
|
|
|
|
|
pop dx
|
|
pop ax
|
|
ret
|
|
|
|
inttostr16:
|
|
;ax = value
|
|
;di = pointer to buffer
|
|
;si = start of string (output)
|
|
;cx = max length of buffer
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push di
|
|
|
|
|
|
mov si,di
|
|
add si,cx
|
|
dec si
|
|
mov byte [si],'$'
|
|
dec si
|
|
|
|
;worker
|
|
inttostr16_worker:
|
|
cmp si,di
|
|
jb inttostr16_end ; end of stringspace
|
|
|
|
xor dx,dx
|
|
mov bx,10
|
|
div bx
|
|
|
|
add dl,030h
|
|
mov [si],dl
|
|
dec si
|
|
|
|
cmp ax,0
|
|
jne inttostr16_worker
|
|
|
|
mov cx,si
|
|
inc cx
|
|
|
|
inttostr16_fillspace:
|
|
cmp si,di
|
|
jb inttostr16_end
|
|
mov byte [si],0x20
|
|
dec si
|
|
|
|
jmp inttostr16_fillspace
|
|
|
|
|
|
|
|
inttostr16_end:
|
|
mov si,cx
|
|
|
|
pop di
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
|
|
ret
|
|
|
|
|
|
|
|
inttohex16:
|
|
;ax = value
|
|
;di = pointer to buffer
|
|
;si = start of string (output)
|
|
;cx = max length of buffer
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push di
|
|
|
|
|
|
mov si,di
|
|
add si,cx
|
|
dec si
|
|
mov byte [si],'$' ;make this 0
|
|
dec si
|
|
|
|
;worker
|
|
inttohex16_worker:
|
|
cmp si,di
|
|
jb inttohex16_end ; end of stringspace
|
|
|
|
xor dx,dx
|
|
mov bx,16
|
|
div bx
|
|
|
|
cmp dl,09h
|
|
ja alpha
|
|
add dl,'0' ; add from '0'
|
|
jmp writehex
|
|
|
|
alpha:
|
|
sub dl,0ah
|
|
add dl,'a' ; add from 'a'
|
|
|
|
|
|
|
|
writehex:
|
|
mov [si],dl
|
|
dec si
|
|
|
|
cmp ax,0
|
|
jne inttohex16_worker
|
|
|
|
mov cx,si
|
|
inc cx
|
|
|
|
inttohex16_fillspace:
|
|
cmp si,di
|
|
jb inttohex16_end
|
|
mov byte [si],0x20
|
|
dec si
|
|
|
|
jmp inttohex16_fillspace
|
|
|
|
|
|
|
|
inttohex16_end:
|
|
mov si,cx
|
|
|
|
pop di
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
|
|
ret
|
|
|
|
generatestring16:
|
|
|
|
|
|
str88: db '88=$'
|
|
stre801: db 'e801:$'
|
|
stre820: db 'e820:',13,10,'$'
|
|
strax: db 'ax=$'
|
|
strbx: db 'bx=$'
|
|
strcx: db 'cx=$'
|
|
strdx: db 'dx=$'
|
|
strsmaperror: db 'SMAP ERROR!',13,10,'$'
|
|
tempbuf: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
|
|
newline: db 13,10,'$'
|
|
|
|
GLOBAL reservedmem_listcount
|
|
reservedmem_listcount: dd 0
|
|
|
|
GLOBAL readerror
|
|
readerror: dd 0
|
|
|
|
global sectorsread
|
|
sectorsread: dd 0
|
|
|
|
global a20state
|
|
a20state: dd 0
|
|
|
|
global bootdisk
|
|
bootdisk: dd 0
|
|
|
|
global SectorsPerTrack
|
|
SectorsPerTrack: dd 0
|
|
|
|
global NumberOfHeads
|
|
NumberOfHeads: dd 0
|
|
|
|
global NumberOfCylinders
|
|
NumberOfCylinders: dd 0
|
|
|
|
vesa_info_success:
|
|
db "get VESA info success",13,10,"$"
|
|
|
|
vesa_info_fail:
|
|
db "get VESA info failed",13,10,"$"
|
|
|
|
str_failed_getting_data:
|
|
db " Failure"
|
|
|
|
str_videomode:
|
|
db "videomode 0x$"
|
|
|
|
|
|
|
|
checka20:
|
|
push ds
|
|
push es
|
|
|
|
xor ax,ax
|
|
mov ds,ax
|
|
dec ax
|
|
mov es,ax
|
|
|
|
mov ax,[es:10h] ; read word at FFFF:0010 (1 meg)
|
|
not ax ; 1's complement
|
|
push word [0] ; save word at 0000:0000 (0)
|
|
mov [0],ax ; word at 0 = ~(word at 1 meg)
|
|
mov ax,[0] ; read it back
|
|
cmp ax,[es:10h] ; fail if word at 0 == word at 1 meg
|
|
pop word [0]
|
|
|
|
pop es
|
|
pop ds
|
|
je checka20_noa20 ;it's the same
|
|
|
|
mov ax,1
|
|
ret
|
|
|
|
checka20_noa20:
|
|
mov ax,0
|
|
ret
|
|
;^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
retry: db 'retry reading disk',13
|
|
|
|
waitforkeypress:
|
|
%ifdef SERIALPORT
|
|
%if SERIALPORT != 0
|
|
mov dx,SERIALPORT+5 ;0x3fd
|
|
waitforkeypress2:
|
|
in al,dx
|
|
and al,1
|
|
cmp al,1
|
|
jne waitforkeypress2
|
|
mov dx,SERIALPORT ;0x3f8
|
|
in al,dx
|
|
%endif
|
|
%endif
|
|
ret
|
|
|
|
|
|
real_entry:
|
|
|
|
;ok
|
|
|
|
;setup rs232 (serial port communications)
|
|
|
|
|
|
|
|
;ok
|
|
|
|
;-----------------------Real Entry point--------------------
|
|
|
|
|
|
|
|
mov ax,0x8000
|
|
cli
|
|
mov ss,ax
|
|
mov sp,0xfff0
|
|
sti
|
|
|
|
xor ebp,ebp
|
|
xor esi,esi
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov es,ax
|
|
|
|
start:
|
|
call begin
|
|
begin:
|
|
pop bp ; bp now contains the address of begin
|
|
|
|
;ok
|
|
|
|
|
|
|
|
lea di,[ds:bp+reservedmem_listcount-begin]
|
|
cmp byte [ds:di],0
|
|
jne gdtsetup
|
|
|
|
mov [ds:bp+bootdisk-begin],dl ;save bootdisk
|
|
|
|
cmp byte [bp+reservedmem_listcount-begin],0
|
|
jne gdtsetup ;skip setting up hardware and enumerating memory, it's already done
|
|
|
|
%ifdef SERIALPORT
|
|
%if SERIALPORT !=0
|
|
;jmp serialsetupdone
|
|
mov dx,SERIALPORT+1 ;3f9h
|
|
mov al,0h
|
|
out dx,al
|
|
|
|
mov dx,SERIALPORT+3; 3fbh
|
|
mov al,80h
|
|
out dx ,al ;access baud rate generator
|
|
|
|
mov dx,SERIALPORT; 3f8h
|
|
mov al,1h ;0c=9600 (1152000/divisor)
|
|
out dx,al ;9600 baud
|
|
|
|
mov dx,SERIALPORT+1; 3f9h
|
|
mov al,0h ;high part of devisor
|
|
out dx,al ;
|
|
|
|
mov dx,SERIALPORT+3; 3fbh
|
|
mov al,3h
|
|
out dx,al ;8 bits, no parity, one stop
|
|
%endif
|
|
%endif
|
|
|
|
serialsetupdone:
|
|
|
|
|
|
|
|
;begin with setting up diskinfo
|
|
mov ax,0x6000
|
|
mov es,ax
|
|
xor di,di
|
|
|
|
mov ax,0x0800
|
|
mov dl,[ds:bp+bootdisk-begin]
|
|
int 13h
|
|
|
|
inc dh
|
|
mov [ds:bp+NumberOfHeads-begin],dh
|
|
mov ax,cx
|
|
and ax,3fh
|
|
inc ax
|
|
mov [ds:bp+SectorsPerTrack-begin],ax
|
|
mov al,ch
|
|
shr ch,6
|
|
mov ah,ch
|
|
mov [ds:bp+NumberOfCylinders-begin],ax
|
|
|
|
|
|
;enumerate the memory regions that can not be used by dbvm
|
|
;int 15h
|
|
|
|
;init buffer
|
|
mov ax,08000h
|
|
mov es,ax
|
|
mov di,0
|
|
mov ebx,0
|
|
|
|
enummem:
|
|
;mov byte [es:0xdead],2
|
|
;enumerate the memory regions available to the operating system and save them
|
|
xor eax,eax
|
|
mov eax,0e820h
|
|
mov ecx,20
|
|
mov edx,0534D4150h
|
|
clc
|
|
int 15h
|
|
|
|
jc endofenummem
|
|
cmp eax,0534D4150h
|
|
jne endofenummem
|
|
|
|
cmp ecx,20
|
|
jne endofenummem
|
|
|
|
push di
|
|
lea di,[ds:bp+reservedmem_listcount-begin]
|
|
inc dword [ds:di]
|
|
pop di
|
|
add di,20
|
|
|
|
cmp ebx,0
|
|
jne enummem ;still more to go
|
|
|
|
endofenummem:
|
|
|
|
|
|
|
|
lea di,[ds:bp+reservedmem_listcount-begin]
|
|
mov ax,word [di]
|
|
|
|
lea di,[ds:bp+tempbuf-begin]
|
|
mov cx,16
|
|
call inttohex16
|
|
|
|
|
|
|
|
lea si,[ds:bp+strnormal-begin]
|
|
call sendstring16
|
|
|
|
|
|
mov cl,';'
|
|
call send16
|
|
|
|
;call waitforkeypress
|
|
|
|
|
|
gdtsetup:
|
|
|
|
|
|
|
|
|
|
;enable a20
|
|
in al,92h
|
|
test al,02h
|
|
jne hasa20
|
|
|
|
or al,02h
|
|
out 92h,al
|
|
|
|
|
|
noa20:
|
|
hasa20:
|
|
|
|
call checka20
|
|
lea di,[bp+a20state-begin]
|
|
mov [di],ax
|
|
|
|
|
|
;------------------GDT setup
|
|
mov ax,0x4000
|
|
mov es,ax
|
|
|
|
mov word [es:0],0x6f
|
|
mov dword [es:2],0x50000
|
|
|
|
; 0x3000:0x02b3
|
|
mov ax,0x5000
|
|
mov es,ax
|
|
mov dword [es:0],0
|
|
mov dword [es:4],0
|
|
mov dword [es:8],0x0000ffff ;32-bit data
|
|
mov dword [es:12],0x00cf9200
|
|
mov dword [es:16],0x0000ffff ;stack (unused)
|
|
mov dword [es:20],0x00cf9600
|
|
|
|
;lea ax,[bp+entry32-begin]
|
|
;shl eax,16
|
|
;add eax,0xffff
|
|
mov dword [es:24],0x0000ffff ;32-bit code
|
|
mov dword [es:28],0x00cf9b00 ;limit=ffff*4KB base=0
|
|
|
|
|
|
|
|
mov dword [es:32],0x0000ffff ;16-bit code
|
|
mov dword [es:36],0x00009a00
|
|
|
|
mov dword [es:40],0x0000ffff ;16-bit data
|
|
mov dword [es:44],0x00009200
|
|
|
|
mov dword [es:48],0x0000ffff ;16-bit code, base 0x30000
|
|
mov dword [es:52],0x00009a03
|
|
|
|
mov dword [es:56],0 ;32-bit task , main vmm task
|
|
mov dword [es:60],0
|
|
|
|
mov dword [es:64],0 ;64-bit task , main vmm64 task
|
|
mov dword [es:68],0
|
|
|
|
mov dword [es:72],0 ;
|
|
mov dword [es:76],0
|
|
|
|
;64-bit code segment
|
|
mov dword [es:80], 0x0000ffff ;64-bit code (there is no limit checking)
|
|
mov dword [es:84], 0x00AF9B00
|
|
mov dword [es:88],0
|
|
mov dword [es:92],0
|
|
|
|
;64bit tss descriptor (initialized later)
|
|
mov dword [es:96], 0
|
|
mov dword [es:100],0
|
|
mov dword [es:104],0
|
|
mov dword [es:108],0
|
|
|
|
;64-bit data segment
|
|
;there is none...
|
|
|
|
mov ax,0x4000
|
|
mov fs,ax
|
|
db 0x66
|
|
LGDT [fs:0]
|
|
|
|
|
|
|
|
|
|
mov ax,0xffff
|
|
mov ds,ax
|
|
|
|
|
|
|
|
;setup to protected mode
|
|
cli ;no more ints for now
|
|
|
|
mov ebx,cr0
|
|
or ebx,1
|
|
mov cr0,ebx
|
|
|
|
jmp short shortjump
|
|
shortjump:
|
|
|
|
nop
|
|
nop
|
|
mov bx,cs
|
|
|
|
bits 32
|
|
db 0x66
|
|
jmp 24:entry32
|
|
|
|
;----------------------------------------------------------;
|
|
; PROTECTED MODE :32 bit section ;
|
|
;----------------------------------------------------------;
|
|
bits 32
|
|
|
|
|
|
|
|
|
|
jmp short entry32
|
|
|
|
extern _vmloader_main
|
|
|
|
strnormal:
|
|
db 'normal boot',13,10,'$'
|
|
|
|
strcalledlgdt:
|
|
db 'Called LGDT (not)',13,10,'$'
|
|
|
|
sendstring32:
|
|
;esi=pointer to zstring
|
|
mov cl,[esi]
|
|
call sendchar32
|
|
|
|
inc esi
|
|
cmp byte [esi],0
|
|
jne sendstring32
|
|
ret
|
|
|
|
|
|
sendchar32:
|
|
%ifdef SERIALPORT
|
|
%if SERIALPORT != 0
|
|
mov edx,SERIALPORT+5 ;3fdh
|
|
in al,dx
|
|
and al,0x20
|
|
cmp al,0x20
|
|
jne sendchar32
|
|
|
|
|
|
mov edx,SERIALPORT; 0x3f8
|
|
mov al,cl
|
|
out dx,al
|
|
%endif
|
|
%endif
|
|
ret
|
|
|
|
|
|
entry32:
|
|
|
|
shl ebx,16
|
|
mov bx,ds
|
|
|
|
mov cx,es
|
|
shl ecx,16
|
|
mov cx,fs
|
|
|
|
|
|
;set segments to valid entries (ss is kinda important)
|
|
mov ax,8
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov fs,ax
|
|
mov gs,ax
|
|
mov ss,ax
|
|
;mov esp,0x003ffffc ;4mb , the user should have that at least, else i will crash anyhow
|
|
mov esp,0x0002fffc
|
|
|
|
;mov [readerror],ebx
|
|
;mov [sectorsread],ecx
|
|
|
|
;zero the stack
|
|
xor eax,eax
|
|
mov edi,esp
|
|
and edi,0xffff0000
|
|
mov ecx,0xffff
|
|
rep stosb
|
|
|
|
;0018:0303de
|
|
call _vmloader_main ; 0x30452
|
|
|
|
|
|
mov al,1
|
|
lp:
|
|
mov byte [0x0b8000],'l'
|
|
mov byte [0x0b8001],al
|
|
inc al
|
|
mov byte [0x0b8002],'o'
|
|
mov byte [0x0b8003],al
|
|
inc al
|
|
mov byte [0x0b8004],'s'
|
|
mov byte [0x0b8005],al
|
|
inc al
|
|
mov byte [0x0b8006],'e'
|
|
mov byte [0x0b8007],al
|
|
inc al
|
|
mov byte [0x0b8008],'r'
|
|
mov byte [0x0b8009],al
|
|
inc al
|
|
|
|
|
|
jmp lp
|
|
|
|
strInsideVMM: db 'Inside gotoVMM',13,10,0
|
|
strSetGDT: db 'Have set the GDT',13,10,0
|
|
|
|
|
|
global PageMapLevel4
|
|
PageMapLevel4: dd 0
|
|
|
|
global vmmPA
|
|
vmmPA: dd 0
|
|
|
|
global GDTVA
|
|
GDTVA: dd 0
|
|
|
|
global gotoVMM
|
|
gotoVMM:
|
|
;the new gdt address is at VMMSIZE+1*4096 & 0xfff
|
|
;the pagetablebase (cr3) should be at VMMSIZE+2*4096 & 0xfffff000
|
|
|
|
mov ebx,[vmmPA]
|
|
|
|
mov esi,strInsideVMM
|
|
call sendstring32
|
|
|
|
|
|
|
|
mov eax,[PageMapLevel4]
|
|
mov cr3,eax
|
|
|
|
;set the gdt
|
|
mov word [0x40000],0x6f
|
|
mov eax,[GDTVA]
|
|
mov dword [0x40002],eax ;was 0x00400000+VMMSIZE+1*4096 & 0xfffff000
|
|
lgdt [0x40000]
|
|
|
|
mov esi,strSetGDT
|
|
call sendstring32
|
|
|
|
|
|
mov dl,[bootdisk] ;so the vmm knows the bootdisk, for whatever reason it migth need it
|
|
|
|
;mov eax,cr4
|
|
;or eax,0x30 ; enable PAE and PSE (to enable 2MB pages)
|
|
;mov cr4,eax
|
|
mov eax,0x30
|
|
mov cr4,eax
|
|
|
|
|
|
;set IA32_EFER_LME to 1 (enable 64 bits)
|
|
mov ecx,0xc0000080
|
|
rdmsr
|
|
or eax,0x100
|
|
wrmsr
|
|
|
|
mov eax,cr0
|
|
or eax,0x80000020 ;set the pg bit (and ne bit)
|
|
mov cr0,eax
|
|
xor eax,eax ;tell the vmm that it's loaded from a clean setup
|
|
|
|
|
|
|
|
jmp 80:0x00400000 ; go to 64-bit
|
|
|
|
global halt
|
|
;----------------------------;
|
|
;int halt(void);
|
|
;----------------------------;
|
|
halt:
|
|
hlt
|
|
jmp halt
|
|
|
|
global readsectorasm
|
|
;----------------------------;
|
|
;int readsectorasm(void);
|
|
;----------------------------;
|
|
;7000:0000 contains the data to read, 7000:8000 the data needed to return
|
|
;6000:0000 points to the data to fill in
|
|
;This routine will switch to realmode , execute int13, and then switch back to realmode
|
|
readsectorasm:
|
|
;save state
|
|
mov dword [0x00078000],eax
|
|
mov dword [0x00078004],ebx
|
|
mov dword [0x00078008],ecx
|
|
mov dword [0x0007800c],edx
|
|
mov dword [0x00078010],esi
|
|
mov dword [0x00078014],edi
|
|
mov dword [0x00078018],ebp
|
|
mov dword [0x0007801c],esp
|
|
|
|
|
|
mov eax,readsector16protected
|
|
and eax,0xffff
|
|
mov dword [0x00078020],eax
|
|
mov dword [0x00078024],48 ;16-bit code segment starting at 0x30000
|
|
|
|
|
|
|
|
nop
|
|
nop
|
|
nop
|
|
jmp far dword [0x00078020]
|
|
|
|
readsector16protected:
|
|
;in 16bit protected mode now
|
|
|
|
bits 16
|
|
mov ax,40 ;set segment registers to 16-bit
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov fs,ax
|
|
mov gs,ax
|
|
mov ss,ax
|
|
|
|
;switch to real
|
|
xor eax,eax
|
|
mov cr0,eax
|
|
|
|
mov ax,0x6000
|
|
mov ds,ax
|
|
mov eax,readsector16
|
|
mov word [0],ax
|
|
mov word [2],0x3000
|
|
jmp far word [0] ;refresh cs to point to proper base
|
|
|
|
readsector16:
|
|
|
|
|
|
;realmode here
|
|
mov ax,0x7000
|
|
mov ds,ax
|
|
mov ax,0x6000 ;target to write to (512 bytes)
|
|
mov es,ax
|
|
|
|
mov ss,ax
|
|
mov sp,0xfffe ;end of that segment
|
|
|
|
sti
|
|
|
|
;call int13
|
|
mov ax,0x0201 ;read 1 sector
|
|
xor bx,bx ;write to 0x0 ;(so ds:bx=7000:0000)
|
|
|
|
;mov word [0xdead],0xdead ;;debug for bochs (watch write 0x7dead)
|
|
|
|
mov cl,[0] ;sector
|
|
mov dh,[1] ;head
|
|
mov ch,[2] ;cylinder
|
|
mov dl,[3] ;drive
|
|
|
|
int 0x13
|
|
|
|
jc readsector_error
|
|
mov eax,1
|
|
jmp readsector_afterread
|
|
|
|
readsector_error:
|
|
xor eax,eax
|
|
|
|
|
|
readsector_afterread:
|
|
mov bx,0x7000
|
|
mov ds,bx
|
|
mov dword [0x8000],eax ;set new eax value
|
|
|
|
;go back to the protected mode caller
|
|
cli ;no more ints for now
|
|
|
|
mov ebx,cr0
|
|
or ebx,1
|
|
mov cr0,ebx
|
|
|
|
jmp short readsector_sj
|
|
readsector_sj:
|
|
|
|
nop
|
|
nop
|
|
|
|
bits 32
|
|
db 0x66
|
|
jmp 24:readsector_return
|
|
|
|
readsector_return:
|
|
mov ax,8
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov fs,ax
|
|
mov gs,ax
|
|
mov ss,ax
|
|
|
|
mov eax,dword [0x00078000]
|
|
mov ebx,dword [0x00078004]
|
|
mov ecx,dword [0x00078008]
|
|
mov edx,dword [0x0007800c]
|
|
mov esi,dword [0x00078010]
|
|
mov edi,dword [0x00078014]
|
|
mov ebp,dword [0x00078018]
|
|
mov esp,dword [0x0007801c]
|
|
|
|
ret
|