FreeDOS/kernel/asmsupt.asm

555 lines
14 KiB
NASM
Raw Normal View History

2012-10-15 02:08:06 +02:00
; File:
; asmsupt.asm
; Description:
; Assembly support routines for miscellaneous functions
;
; Copyright (c) 1995, 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; version 1.4 by tom.ehlert@ginko.de
; added some more functions
; changed bcopy, scopy, sncopy,...
; to memcpy, strcpy, strncpy
; Bart Oldeman: optimized a bit: see /usr/include/bits/string.h from
; glibc 2.2
;
; $Id: asmsupt.asm 1568 2011-04-09 02:42:51Z bartoldeman $
;
; for OW on Linux:
%ifdef owlinux
%define WATCOM
%endif
%ifdef WATCOM
%ifdef _INIT
%define WATCOM_INIT ; no seperate init segment for watcom.
%endif
%endif
%ifndef WATCOM_INIT
%include "segs.inc"
%ifdef _INIT
segment INIT_TEXT
%define FMEMCPYBACK INIT_FMEMCPYBACK
%define MEMCPY INIT_MEMCPY
%define FMEMCPY INIT_FMEMCPY
%define MEMSET INIT_MEMSET
%define FMEMSET INIT_FMEMSET
%define STRCPY INIT_STRCPY
%define FSTRCPY INIT_FSTRCPY
%define STRLEN INIT_STRLEN
%define FSTRLEN INIT_FSTRLEN
%define FMEMCHR INIT_FMEMCHR
%define FSTRCHR INIT_FSTRCHR
%define STRCHR INIT_STRCHR
%define FSTRCMP INIT_FSTRCMP
%define STRCMP INIT_STRCMP
%define FSTRNCMP INIT_FSTRNCMP
%define STRNCMP INIT_STRNCMP
%define FMEMCMP INIT_FMEMCMP
%define MEMCMP INIT_MEMCMP
%else
segment HMA_TEXT
%endif
;*********************************************************************
; this implements some of the common string handling functions
;
; every function has 1 entry
;
; NEAR FUNC()
;
; currently done:
;
; fmemcpyBack(void FAR *dest, void FAR *src, int count)
; memcpy(void *dest, void *src, int count)
; fmemcpy(void FAR *dest, void FAR *src, int count)
; memset(void *dest, int ch, int count);
; fmemset(void FAR *dest, int ch, int count);
; strcpy (void *dest, void *src);
; fstrcpy (void FAR*dest, void FAR *src);
; strlen (void *dest);
; fstrlen (void FAR*dest);
; fmemchr (BYTE FAR *src , int ch);
; fstrchr (BYTE FAR *src , int ch);
; strchr (BYTE *src , int ch);
; fstrcmp (BYTE FAR *s1 , BYTE FAR *s2);
; strcmp (BYTE *s1 , BYTE *s2);
; fstrncmp(BYTE FAR *s1 , BYTE FAR *s2, int count);
; strncmp(BYTE *s1 , BYTE *s2, int count);
; fmemcmp(BYTE FAR *s1 , BYTE FAR *s2, int count);
; memcmp(BYTE *s1 , BYTE *s2, int count);
;***********************************************
; pascal_setup - set up the standard calling frame for C-functions
; and save registers needed later
; also preload the args for the near functions
; di=arg1
; si=arg2
; cx=arg3
;
pascal_setup:
pop ax ; get return address
push bp ; Standard C entry
mov bp,sp
%ifdef WATCOM
push bx
push cx
push es
%endif
push si
push di
push ds
; Set both ds and es to same segment (for near copy)
push ds
pop es
; Set direction to autoincrement
cld
mov bl,6 ; majority (4) wants that
mov cx,[4+bp] ; majority (8) wants that (near and far)
mov si,[6+bp] ; majority (3) wants that (near)
mov di,[8+bp] ; majority (3) wants that (near)
jmp ax
;***********************************************
;
; VOID memcpy(REG BYTE *s, REG BYTE *d, REG COUNT n);
;
global MEMCPY
MEMCPY:
call pascal_setup
;mov cx,[4+bp] - preset above
;mov si,[6+bp] - preset above
;mov di,[8+bp] - preset above
;mov bl,6 - preset above
domemcpy:
; And do the built-in byte copy, but do a 16-bit transfer
; whenever possible.
shr cx,1
rep movsw
jnc memcpy_return
movsb
memcpy_return:
%if 0 ; only needed for fmemcpyback
cld
%endif
;
; pascal_return - pop saved registers and do return
;
jmp short pascal_return
;************************************************************
;
; VOID fmemcpy(REG BYTE FAR *d, REG BYTE FAR *s,REG COUNT n);
; VOID fmemcpyBack(REG BYTE FAR *d, REG BYTE FAR *s,REG COUNT n);
;
global FMEMCPY
%if 0
global FMEMCPYBACK
FMEMCPYBACK:
std ; force to copy the string in reverse order
%endif
FMEMCPY:
call pascal_setup
; Get the repetition count, n preset above
; mov cx,[bp+4]
; Get the far source pointer, s
lds si,[bp+6]
; Get the far destination pointer d
les di,[bp+10]
mov bl,10
jmp short domemcpy
;***************************************************************
;
; VOID fmemset(REG VOID FAR *d, REG BYTE ch, REG COUNT n);
;
global FMEMSET
FMEMSET:
call pascal_setup
; Get the repetition count, n - preset above
; mov cx,[bp+4]
; Get the fill byte ch
mov ax,[bp+6]
; Get the far source pointer, s
les di,[bp+8]
mov bl,8
domemset:
mov ah, al
shr cx,1
rep stosw
jnc pascal_return
stosb
jmp short pascal_return
;***************************************************************
;
; VOID memset(REG VOID *d, REG BYTE ch, REG COUNT n);
;
global MEMSET
MEMSET:
call pascal_setup
; Get the repitition count, n - preset above
; mov cx,[bp+4]
; Get the char ch
mov ax, [bp+6]
; Get the far source pointer, d - preset above
; mov di,[bp+8]
;mov bl, 6 ; preset above
jmp short domemset
;*****
pascal_return:
lds di, [bp] ; return address in ds, saved bp in di
mov bh, 0
add bp, bx ; point bp to "as if there were 0 args"
mov [bp+2], ds ; put return address at first arg
mov [bp], di ; saved bp below that one
pop ds
pop di
pop si
%ifdef WATCOM
pop es
pop cx
pop bx
%endif
mov sp,bp
pop bp
ret
;*****************************************************************
; fstrcpy (void FAR*dest, void FAR *src);
%ifndef _INIT
global FSTRCPY
FSTRCPY:
call pascal_setup
; Get the source pointer, ss
lds si,[bp+4]
; and the destination pointer, d
les di,[bp+8]
mov bl,8
jmp short dostrcpy
%endif
;******
global STRCPY
STRCPY:
call pascal_setup
; Get the source pointer, ss
mov si,[bp+4]
; and the destination pointer, d
mov di,[bp+6]
mov bl,4
dostrcpy:
strcpy_loop:
lodsb
stosb
test al,al
jne strcpy_loop
jmp short pascal_return
;******************************************************************
%ifndef _INIT
global FSTRLEN
FSTRLEN:
call pascal_setup
; Get the source pointer, ss
les di,[bp+4]
mov bl,4
jmp short dostrlen
%endif
;**********************************************
global STRLEN
STRLEN:
call pascal_setup
; Get the source pointer, ss
mov di,[bp+4]
mov bl,2
dostrlen:
mov al,0
mov cx,0xffff
repne scasb
mov ax,cx
not ax
dec ax
jmp short pascal_return
;************************************************************
; strchr (BYTE *src , int ch);
global STRCHR
STRCHR:
call pascal_setup
; Get the source pointer, ss
; mov cx,[bp+4] - preset above
; mov si,[bp+6] - preset above
mov bl,4
strchr_loop:
lodsb
cmp al,cl
je strchr_found
test al,al
jne strchr_loop
strchr_retzero:
xor ax, ax ; return NULL if not found
mov dx, ax ; for fstrchr()
jmp short pascal_return
strchr_found:
mov ax, si
mov dx, ds ; for fstrchr()
strchr_found1:
dec ax
jmp short pascal_return
%ifndef _INIT
;*****
; fstrchr (BYTE far *src , int ch);
global FSTRCHR
FSTRCHR:
call pascal_setup
; Get ch (preset above)
;mov cx, [bp+4]
;and the source pointer, src
lds si, [bp+6]
;mov bl, 6 - preset above
jmp short strchr_loop
;******
global FMEMCHR
FMEMCHR:
call pascal_setup
; Get the length - preset above
; mov cx, [bp+4]
; and the search value
mov ax, [bp+6]
; and the source pointer, ss
les di, [bp+8]
mov bl, 8
jcxz strchr_retzero
repne scasb
jne strchr_retzero
mov dx, es
mov ax, di
jmp short strchr_found1
;**********************************************************************
global FSTRCMP
FSTRCMP:
call pascal_setup
; Get the source pointer, ss
lds si,[bp+4]
; and the destination pointer, d
les di,[bp+8]
mov bl,8
%if 0
jmp short dostrcmp
;******
global STRCMP
STRCMP:
call pascal_setup
mov bl,4
; Get the source pointer, ss
; mov si,[bp+4]
; and the destination pointer, d
; mov di,[bp+6]
xchg si,di
dostrcmp:
%endif
; replace strncmp(s1,s2)-->
; strncmp(s1,s2,0xffff)
mov cx,0xffff
%if 0
jmp short dostrncmp
;**********************************************************************
global FSTRNCMP
FSTRNCMP:
call pascal_setup
; Get the source pointer, ss
lds si,[bp+4]
; and the destination pointer, d
les di,[bp+8]
mov cx,[bp+12]
mov bl,10
jmp short dostrncmp
;******
global _strncmp
_strncmp:
call pascal_setup
; Get the source pointer, ss
;mov si,[bp+4]
; and the destination pointer, d
;mov di,[bp+6]
;mov cx,[bp+8]
xchg si,di
dostrncmp:
%endif
jcxz strncmp_retzero
strncmp_loop:
lodsb
scasb
jne strncmp_done
test al,al
loopne strncmp_loop
jmp short strncmp_retzero
%endif
;**********************************************************************
; fmemcmp(BYTE FAR *s1 , BYTE FAR *s2, int count);
global FMEMCMP
FMEMCMP:
call pascal_setup
; the length - preset above
; mov cx, [bp+4]
; Get the source pointer, ss
les di,[bp+6]
; and the destination pointer, d
lds si,[bp+10]
mov bl,10
jmp short domemcmp
;******
; memcmp(BYTE *s1 , BYTE *s2, int count);
global MEMCMP
MEMCMP:
call pascal_setup
; all preset: Get the source pointer, ss
;mov si,[bp+6]
; and the destination pointer, d
;mov di,[bp+8]
;mov cx,[bp+4]
;mov bl,6
xchg si,di
domemcmp:
jcxz strncmp_retzero
repe cmpsb
jne strncmp_done
strncmp_retzero:
xor ax, ax
jmp short strncmp_done2
strncmp_done:
lahf
ror ah,1
%ifdef _INIT
strncmp_done2: jmp short pascal_return
%else
strncmp_done2: jmp pascal_return
%endif
%endif