555 lines
14 KiB
NASM
555 lines
14 KiB
NASM
|
; 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
|