home *** CD-ROM | disk | FTP | other *** search
- ; a fast MEMMOVE routine that uses the 80836 if present
- ; this function can replace the memmove routine supplied with
- ; Microsoft and Borland C runtime libraries (sample coded in
- ; (small model)
- ;
- ; Author: M. Steven Baker
- ; Date: January 19, 1989
- ; Last Revision: January 31, 1989
- ;
- ; added test to force word alignment of source
-
- ; PROCEDURE cputype
- ;
- ; find out if we have an 80386 CPU to use
- ; This routine can be used from the real or virtual
- ; 8086 mode only. Otherwise will likely cause a
- ; protection violation (PUSHF instruction is
- ; privileged)
- ;
- ; Based on COMPAQ DESKPRO 386/20 Technical Reference Guide
- ; (originally suggested by INTEL)
- ;
- ; Entry: none
- ; Exit: AX = CPU type
- ; 0086h if 8088/8086
- ; 0286h if 80286
- ; 0386h if 80386
- ; Stack: 8 bytes
- ;
- .MODEL small
- .CODE
-
- public _cputype
-
- _cputype proc near
- pushf ;save the real flags register
- ;
- pop ax ;get register off stack
- push ax ;and save it again
- ;
- and ax,0fffh ;zero out bits 12-15
- push ax
- popf ;try to put into flags
- pushf
- pop ax ;let's see what came out
- ;of flags
- and ax,0F000h ;mask off bits 12-15
- cmp ax,0F000h ;were these bits all 1's
- je is_86 ;if so, it's an 8086
- ;
- pop ax ;get flags register to AX
- push ax ;and save it again
- ;
- or ax,0F000h ;now try to set bits 12-15
- push ax
- popf ;of the flags register
- pushf
- pop ax ;and see what came out
- and ax,0F000h ;are high bits set
- je is_286 ;if so, we have a 386
- is_386: mov ax,0386h
- jmp short cpu_exit
- ;
- is_286: mov ax,0286h
- jmp short cpu_exit
- ;
- is_86: mov ax,86h
- ;
- cpu_exit:
- popf ;restore flags
- ret
- _cputype endp
- ;
-
- ; PROCEDURE memmove
- ;
- ; void * memmove(void *dest,const void *src,size_t count);
- ; returns *dest
-
- public _memmove
-
- _memmove proc near
- push bp
- mov bp,sp ;use BP to get variables
- mov dx,di ;save register variables
- mov bx,si ;into BX and DX
- mov ax,ds
- mov es,ax ;force ES to DS (small model
- mov di,[bp+4] ;get destination ptr
- mov si,[bp+6] ;and source ptr
- mov cx,[bp+8] ;and byte count
- ;
- mov ax,di ;memmove returns dest ptr
- jcxz mmov_ret ;if count=0, where done
- ;
- cmp di,si ;do we have possible overlap
- jb forward1 ;if not go do it
- ;
- je mmov_ret ;if dest=src, then do nothing
- mov ax,si ;
- add ax,cx ;find end point of source
- cmp di,ax ;do we overlap with dest ?
- mov ax,di ;memmove must return dest ptr
- jae forward ;no overlap
- ;
- add si,cx ;copy from end of string back
- add di,cx
- std ;set reverse direction
- dec si
- dec di
- ;
- test si,1 ;are we at least word aligned?
- jz back1
- movsb ;get word aligned
- dec cx
- ;
- back1: shr cx,1 ;convert to words
- jnc back2 ;carry if odd count
- movsb
- back2: dec si ;set index for word
- dec di
- shr cx,1
- patch_o1:
- jnc back4
- movsw
- back4: sub di,2
- sub si,2
- db 66h ;operand size [refix
- patch_i1:
- rep movsw
- cld ;force forward direction
- mmov_ret:
- mov si,bx ;restore register variables
- mov di,dx
- pop bp
- ret
- forward1:
- test si,1 ;are we at least word aligned?
- jz forward
- movsb ;get word aligned
- dec cx
- forward:
- shr cx,1 ;byte count to words
- jnc forwd4 ;if no carry, then even count
- movsb
- forwd4: shr cx,1 ;word count to dwords
- patch_o2:
- db 66h ;operand size prefix
- rep movsw ;(rep movsd) move double words
- adc cx,cx ;if carry was odd
- rep movsw ;if CX<>0 movsw
- ;
- mov si,bx ;restore register variables
- mov di,dx
- pop bp
- ret
- _memmove endp
-
- public _cpupatch
-
- _cpupatch proc near
- call _cputype
- cmp ax,0386h
- jne patch_mmove
- ret
- ;
- patch_mmove:
- push ds ;save registers
- push es
- push si
- push di
- push cx
- ;
- mov ax,cs ;set DS=ES to CS
- mov ds,ax
- mov es,ax
- mov si,offset patch_i1 ;input patch
- mov di,offset patch_o1
- mov cx,(offset forward- offset patch_i1)
- rep movsb
- ;
- mov si,offset patch_i1
- mov di,offset patch_o2
- mov cx,(offset forward - offset patch_i1)
- rep movsb
- ;
- pop cx
- pop di
- pop si
- pop es
- pop ds
- ret
-
- _cpupatch endp
-
- end