| This routine copies a block of physical memory. It is called by:
| phys_copy( (long) source, (long) destination, (long) bytecount)
|
_phys_copy:
pushf
cli
push bp
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
mov bp,sp
|
save flags
disable interrupts
save the registers
save ax
save bx
save cx
save dx
save si
save di
save ds
save es
set bp to point to saved es
|
L0: mov ax,28(bp)
mov di,26(bp)
mov cx,*4
L1: rcr ax,*1
rcr di,*1
loop L1
mov es,di
|
ax = high-order word of 32-bit destination
di = low-order word of 32-bit destination
start extracting click number from dest
click number is destination address / 16
it is used in segment register for copy
4 bits of high-order word are used
es = destination click
|
mov ax,24(bp)
mov si,22(bp)
mov cx,*4
L2: rcr ax,*1
rcr si,*1
loop L2
mov ds,si
|
ax = high-order word of 32-bit source
si = low-order word of 32-bit source
start extracting click number from source
click number is source address / 16
it is used in segment register for copy
4 bits of high-order word are used
ds = source click
|
mov di,26(bp)
and di,*0x000F
mov si,22(bp)
and si,*0x000F
|
di = low-order word of dest address
di = offset from paragraph # in es
si = low-order word of source address
si = offset from paragraph # in ds
|
mov dx,32(bp)
mov cx,30(bp)
|
dx = high-order word of byte count
cx = low-order word of byte count
|
test cx,#0x8000
jnz L3
test dx,#0xFFFF
jnz L3
jmp L4
L3: mov cx,#0x8000
L4: mov ax,ax
|
if bytes >= 32768, only do 32768
per iteration
check high-order 17 bits to see if bytes
if bytes >= 32768 then go to L3
if bytes < 32768 then go to L4
0x8000 is unsigned 32768
save actual count used in ax; needed later
|
test cx,*0x0001
jz L5
rep
movb
jmp L6
|
should we copy a byte or a word at a time?
jump if even
copy 1 byte at a time
byte copy
check for more bytes
|
L5: shr cx,*1
rep
movw
|
word copy
copy 1 word at a time
word copy
|
L6: mov dx,32(bp)
mov cx,30(bp)
xor bx,bx
sub cx,ax
sbb dx,bx
or cx,cx
jnz L7
or dx,dx
jnz L7
|
decr count, incr src & dst, iterate if needed
dx || cx is 32-bit byte count
bx || ax is 32-bit actual count used
compute bytes - actual count
dx || cx is # bytes not yet processed
see if it is 0
if more bytes then go to L7
keep testing
if loop done, fall through
|
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pop bp
popf
ret
|
restore all the saved registers
restore ds
restore di
restore si
restore dx
restore cx
restore bx
restore ax
restore bp
restore flags
return to caller
|
L7: mov 32(bp),dx
mov 30(bp),cx
add 26(bp),ax
adc 28(bp),bx
add 22(bp),ax
adc 24(bp),bx
jmp L0
|
store decremented byte count back in mem
as a long
increment destination
carry from low-order word
increment source
carry from low-order word
start next iteration
|