; 32-bit copy, overlap safe
;
; Inputs:
-; ESI - source pointer
+; ESI - source pointer (-1 means do bzero rather than bcopy)
; EDI - target pointer
; ECX - byte count
; DF - zero
;
; Outputs:
-; ESI - first byte after source
+; ESI - first byte after source (garbage if ESI == -1 on entry)
; EDI - first byte after target
; ECX - zero
;
bcopy: push eax
+ push ebx
push esi
push edi
push ecx
pushf ; Saves, among others, the IF flag
push ds
push es
+ push fs
+ push gs
cli
call enable_a20
+ mov bx,ss ; Save the stack segment value!
+
o32 lgdt [cs:bcopy_gdt]
mov eax,cr0
or al,1
mov es,ax
mov ds,ax
- ; Don't mess with ss, fs, and gs. They are never changed
- ; and should be able to make it back out of protected mode.
- ; This works because (and only because) we don't take
- ; interrupt in protected mode.
+ ; Set ss, fs, and gs, in case we're on a virtual machine
+ ; running on Intel VT hardware -- it can't deal with a
+ ; partial transition, for no good reason. However,
+ ; ss is NOT zero in general, so we have to preserve
+ ; the value.
+
+ mov ax,18h ; Real-mode-like segment
+ mov fs,ax
+ mov gs,ax
+ mov ss,ax
+
+ cmp esi,-1
+ je .bzero
cmp esi,edi ; If source > destination, we might
ja .reverse ; have to copy backwards
a32 rep movsd
cld
+ jmp .exit
+
+.bzero:
+ xor eax,eax
+ mov si,cx ; Save low bits
+ and si,3
+ shr ecx,2
+ a32 rep stosd
+
+ mov cx,si ; Write fractional dword
+ a32 rep stosb
+ ; jmp .exit
.exit:
mov ax,18h ; "Real-mode-like" data segment
jmp 0:.in_rm
.in_rm: ; Back in real mode
+ mov ss,bx
+ pop gs
+ pop fs
pop es
pop ds
call disable_a20
pop esi
add edi,eax
add esi,eax
+ pop ebx
pop eax
ret
The copies are overlap-safe, like memmove().
+ Starting in version 3.40, if the source address is -1
+ (FFFFFFFFh) then the block specified by the destination
+ address and the length is set to all zero.
+
Normal boot sectors expect DL to contain the drive number,
and, for hard drives (DL >= 80h) DS:SI to contain a pointer to
the 16-byte partition table entry. The memory between