[UCRT][ASM] Make asm code GCC compatible

This commit is contained in:
Timo Kreuzer 2024-10-21 19:43:26 +03:00
parent 4fec953e6e
commit 94eb475177
22 changed files with 698 additions and 555 deletions

View file

@ -316,8 +316,10 @@ ENDM
.endm
/* MASM compatible ALIGN */
#define ALIGN .align
#define align .align
.macro align x
.align x
.endm
#define ALIGN align
/* MASM compatible REPEAT, additional ENDR */
#define REPEAT .rept
@ -352,6 +354,7 @@ ENDM
/* MASM needs an END tag */
#define END
#define end
.macro .MODEL model
.endm
@ -359,6 +362,7 @@ ENDM
.macro .code
.text
.endm
#define CODESEG .code
.macro .const
.section .rdata

View file

@ -1,3 +1,7 @@
#include <asm.inc>
#include <ksamd64.inc>
.code64
#if 0
title strcat - concatenate (append) one string to another
;***
;strcat.asm - contains strcat() and strcpy() routines
@ -73,11 +77,12 @@ include ksamd64.inc
;
;Exceptions:
;*******************************************************************************
#endif
public ___entry_from_strcat_in_strcpy
LEAF_ENTRY_ARG2 strcat, _TEXT, dst:ptr byte, src:ptr byte
LEAF_ENTRY_ARG2 strcat, _TEXT, dst_ptr_byte, src_ptr_byte
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
mov r11, rcx
test cl, 7
@ -94,12 +99,12 @@ strcat_copy_head_loop_begin:
strcat_loop_begin:
mov rax, [rcx]
mov r10, rax
mov r9, 7efefefefefefeffh
mov r9, HEX(7efefefefefefeff)
add r9, r10
xor r10, -1
xor r10, r9
add rcx, 8
mov r9, 8101010101010100h
mov r9, HEX(8101010101010100)
test r10, r9
je strcat_loop_begin
sub rcx, 8
@ -136,16 +141,16 @@ strcat_loop_end:
LEAF_END strcat, _TEXT
LEAF_ENTRY_ARG2 strcpy, _TEXT, dst:ptr byte, src:ptr byte
LEAF_ENTRY_ARG2 strcpy, _TEXT, dst_ptr_byte, src_ptr byte
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
mov r11, rcx
strcat_copy:
___entry_from_strcat_in_strcpy=strcat_copy
; align the SOURCE so we never page fault
; dest pointer alignment not important
sub rcx, rdx ; combine pointers
// align the SOURCE so we never page fault
// dest pointer alignment not important
sub rcx, rdx // combine pointers
test dl, 7
jz qword_loop_entrance
@ -168,12 +173,12 @@ qword_loop_begin:
add rdx, 8
qword_loop_entrance:
mov rax, [rdx]
mov r9, 7efefefefefefeffh
mov r9, HEX(7efefefefefefeff)
add r9, rax
mov r10, rax
xor r10, -1
xor r10, r9
mov r9, 8101010101010100h
mov r9, HEX(8101010101010100)
test r10, r9
jz qword_loop_begin

View file

@ -1,3 +1,7 @@
#include <asm.inc>
#include <ksamd64.inc>
.code64
#if 0
page ,132
title strcmp.asm - compare two strings
;***
@ -54,25 +58,26 @@ include ksamd64.inc
;Exceptions:
;
;*******************************************************************************
#endif
CHAR_TYPE EQU BYTE
CHAR_PTR EQU BYTE PTR
CHAR_SIZE = sizeof CHAR_TYPE
#define CHAR_TYPE BYTE
#define CHAR_PTR BYTE PTR
#define CHAR_SIZE 1 /* = sizeof CHAR_TYPE */
BLK_TYPE EQU QWORD
BLK_PTR EQU QWORD PTR
BLK_SIZE = sizeof BLK_TYPE
#define BLK_TYPE QWORD
#define BLK_PTR QWORD PTR
#define BLK_SIZE 8 /* = sizeof BLK_TYPE */
;PAGE_SIZE = 1000h
PAGE_MASK = PAGE_SIZE - 1 ; mask for offset in MM page
PAGE_SAFE_BLK = PAGE_SIZE - BLK_SIZE ; maximum offset for safe block compare
//PAGE_SIZE = 1000h
PAGE_MASK = PAGE_SIZE - 1 // mask for offset in MM page
PAGE_SAFE_BLK = PAGE_SIZE - BLK_SIZE // maximum offset for safe block compare
LEAF_ENTRY_ARG2 strcmp, _TEXT, str1:ptr byte, str2:ptr byte
LEAF_ENTRY_ARG2 strcmp, _TEXT, str1_ptr_byte, str2_ptr_byte
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
; rcx = src
; rdx = dst
// rcx = src
// rdx = dst
sub rdx, rcx
test cl, (BLK_SIZE - 1)
@ -93,8 +98,8 @@ comp_head_loop_begin:
qword_loop_enter:
mov r11, 8080808080808080h
mov r10, 0fefefefefefefeffh
mov r11, HEX(8080808080808080)
mov r10, HEX(0fefefefefefefeff)
qword_loop_begin:
lea eax, [edx+ecx]
@ -105,24 +110,24 @@ qword_loop_begin:
mov rax, BLK_PTR[rcx]
cmp rax, BLK_PTR[rdx+rcx]
; mismatched string (or maybe null + garbage after)
// mismatched string (or maybe null + garbage after)
jne comp_head_loop_begin
; look for null terminator
// look for null terminator
lea r9, [rax + r10]
not rax
add rcx, BLK_SIZE
and rax, r9
test rax, r11 ; r11=8080808080808080h
test rax, r11 // r11=8080808080808080h
jz qword_loop_begin
return_equal:
xor eax, eax ; gets all 64 bits
xor eax, eax // gets all 64 bits
ret
return_not_equal:
sbb rax, rax ; AX=-1, CY=1 AX=0, CY=0
sbb rax, rax // AX=-1, CY=1 AX=0, CY=0
or rax, 1
ret

View file

@ -1,3 +1,7 @@
#include <asm.inc>
#include <ksamd64.inc>
.code64
#if 0
page ,132
title strlen - return the length of a null-terminated string
;***
@ -42,17 +46,18 @@ include ksamd64.inc
;Exceptions:
;
;*******************************************************************************
#endif
LEAF_ENTRY_ARG1 strlen, _TEXT, buf:ptr byte
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
mov rax, rcx
neg rcx ; for later
neg rcx // for later
test rax, 7
jz main_loop_entry
byte 066h, 090h
.byte HEX(66), HEX(90)
byte_loop_begin:
mov dl, [rax]
@ -63,8 +68,8 @@ byte_loop_begin:
jnz byte_loop_begin
main_loop_entry:
mov r8, 7efefefefefefeffh
mov r11, 8101010101010100h
mov r8, HEX(7efefefefefefeff)
mov r11, HEX(8101010101010100)
main_loop_begin:
mov rdx, [rax]

View file

@ -1,3 +1,7 @@
#include <asm.inc>
#include <ksamd64.inc>
.code64
#if 0
page ,132
title strncat - append n chars of string1 to string2
;***
@ -53,8 +57,9 @@ include ksamd64.inc
;Exceptions:
;
;*******************************************************************************
LEAF_ENTRY_ARG3 strncat, _TEXT, front:ptr byte, back:ptr byte, count:dword
OPTION PROLOGUE:NONE, EPILOGUE:NONE
#endif
LEAF_ENTRY_ARG3 strncat, _TEXT, front_ptr_byte, back_ptr_byte, count_dword
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
mov r11, rcx
or r8, r8
@ -75,12 +80,12 @@ strncat_copy_head_loop_begin:
strncat_loop_begin:
mov rax, [rcx]
mov r10, rax
mov r9, 7efefefefefefeffh
mov r9, HEX(7efefefefefefeff)
add r9, r10
xor r10, -1
xor r10, r9
add rcx, 8
mov r9, 8101010101010100h
mov r9, HEX(8101010101010100)
test r10, r9
je strncat_loop_begin
sub rcx, 8
@ -116,9 +121,9 @@ strncat_loop_end:
jmp strncat_loop_begin
strncat_copy:
; align the SOURCE so we never page fault
; dest pointer alignment not important
sub rcx, rdx ; combine pointers
// align the SOURCE so we never page fault
// dest pointer alignment not important
sub rcx, rdx // combine pointers
test dl, 7
jz qword_loop_entrance
@ -150,12 +155,12 @@ qword_loop_entrance:
mov rax, [rdx]
sub r8, 8
jbe qword_loop_end
mov r9, 7efefefefefefeffh
mov r9, HEX(7efefefefefefeff)
add r9, rax
mov r10, rax
xor r10, -1
xor r10, r9
mov r9, 8101010101010100h
mov r9, HEX(8101010101010100)
test r10, r9
jz qword_loop_begin

View file

@ -1,3 +1,7 @@
#include <asm.inc>
#include <ksamd64.inc>
.code64
#if 0
page ,132
title strncmp - compare first n chars of two strings
;***
@ -51,14 +55,15 @@ include ksamd64.inc
;Exceptions:
;
;*******************************************************************************
#endif
LEAF_ENTRY_ARG3 strncmp, _TEXT, str1:ptr byte, str2:ptr byte, count:dword
LEAF_ENTRY_ARG3 strncmp, _TEXT, str1_ptr_byte, str2_ptr_byte, count_dword
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
; rcx = first
; rdx = last
; r8 = count
// rcx = first
// rdx = last
// r8 = count
sub rdx, rcx
@ -85,13 +90,13 @@ comp_head_loop_begin:
jnz comp_head_loop_begin
qword_loop_enter:
mov r11, 08080808080808080h
mov r10, 0fefefefefefefeffh
mov r11, HEX(08080808080808080)
mov r10, HEX(0fefefefefefefeff)
qword_loop_begin:
lea eax, [rdx+rcx]
and eax, 0fffh
cmp eax, 0ff8h
and eax, HEX(0fff)
cmp eax, HEX(0ff8)
ja comp_head_loop_begin
mov rax, qword ptr[rcx]
@ -106,7 +111,7 @@ qword_loop_begin:
lea r9, [r10+rax]
not rax
and rax, r9
test rax, r11 ; 8080808080808080h
test rax, r11 // 8080808080808080h
jz qword_loop_begin
@ -114,10 +119,10 @@ return_equal:
xor eax, eax
ret
; align 16
// align 16
return_not_equal:
sbb rax, rax ; AX=-1, CY=1 AX=0, CY=0
sbb rax, rax // AX=-1, CY=1 AX=0, CY=0
or rax, 1
ret

View file

@ -1,3 +1,7 @@
#include <asm.inc>
#include <ksamd64.inc>
.code64
#if 0
page ,132
title strncpy - copy at most n characters of string
;***
@ -12,17 +16,18 @@
; Look at strncat.asm for this file
include ksamd64.inc
subttl "strncpy"
#endif
LEAF_ENTRY_ARG3 strncpy, _TEXT, dst:ptr byte, src:ptr byte, count:dword
OPTION PROLOGUE:NONE, EPILOGUE:NONE
LEAF_ENTRY_ARG3 strncpy, _TEXT, dst_ptr_byte, src_ptr_byte, count_dword
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
; align the SOURCE so we never page fault
; dest pointer alignment not important
// align the SOURCE so we never page fault
// dest pointer alignment not important
mov r11, rcx
or r8, r8
jz strncpy_exit
sub rcx, rdx ; combine pointers
sub rcx, rdx // combine pointers
test dl, 7
jz qword_loop_entrance
@ -49,12 +54,12 @@ qword_loop_entrance:
mov rax, [rdx]
sub r8, 8
jbe qword_loop_end
mov r9, 7efefefefefefeffh
mov r9, HEX(7efefefefefefeff)
add r9, rax
mov r10, rax
xor r10, -1
xor r10, r9
mov r9, 8101010101010100h
mov r9, HEX(8101010101010100)
test r10, r9
jz qword_loop_begin
@ -118,12 +123,12 @@ strncpy_exit_2:
mov rax, r11
ret
;this is really just memset
//this is really just memset
filler:
add rcx, rdx
xor rdx, rdx
cmp r8, 16
jb tail ; a quickie
jb tail // a quickie
aligner1:
test cl, 7
jz aligned
@ -144,7 +149,7 @@ loop32:
jae loop32
tail_8_enter:
add r8, 32 ; get back the value
add r8, 32 // get back the value
tail_8_begin:
sub r8, 8
jb tail_enter
@ -153,7 +158,7 @@ tail_8_begin:
jmp tail_8_begin
tail_enter:
add r8, 8 ; get back the value
add r8, 8 // get back the value
tail:
sub r8, 1
jb tail_finish

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title memicmp - compare blocks of memory, ignore case
;***
@ -54,77 +56,90 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public __ascii_memicmp
__ascii_memicmp proc \
uses edi esi ebx, \
first:ptr byte, \
last:ptr byte, \
count:IWORD
public ___ascii_memicmp
.PROC ___ascii_memicmp
mov ecx,[count] ; cx = count
// Prolog. Original sources used ML's extended PROC feature to autogenerate this.
push ebp
mov ebp, esp
push edi
push esi
push ebx
#define first ebp + 8
#define last ebp + 12
#define count ebp + 16
mov ecx,[count] // cx = count
or ecx,ecx
jz short toend ; if count=0, nothing to do
jz short toend // if count=0, nothing to do
mov esi,[first] ; si = first
mov edi,[last] ; di = last
mov esi,[first] // si = first
mov edi,[last] // di = last
; C locale
// C locale
mov bh,'A'
mov bl,'Z'
mov dh,'a'-'A' ; add to cap to make lower
mov dh,'a'-'A' // add to cap to make lower
align 4
lupe:
mov ah,[esi] ; ah = *first
add esi,1 ; first++
mov al,[edi] ; al = *last
add edi,1 ; last++
mov ah,[esi] // ah = *first
add esi,1 // first++
mov al,[edi] // al = *last
add edi,1 // last++
cmp ah,al ; test for equality BEFORE converting case
cmp ah,al // test for equality BEFORE converting case
je short dolupe
cmp ah,bh ; ah < 'A' ??
cmp ah,bh // ah < 'A' ??
jb short skip1
cmp ah,bl ; ah > 'Z' ??
cmp ah,bl // ah > 'Z' ??
ja short skip1
add ah,dh ; make lower case
add ah,dh // make lower case
skip1:
cmp al,bh ; al < 'A' ??
cmp al,bh // al < 'A' ??
jb short skip2
cmp al,bl ; al > 'Z' ??
cmp al,bl // al > 'Z' ??
ja short skip2
add al,dh ; make lower case
add al,dh // make lower case
skip2:
cmp ah,al ; *first == *last ??
jne short differ ; nope, found mismatched chars
cmp ah,al // *first == *last ??
jne short differ // nope, found mismatched chars
dolupe:
sub ecx,1
jnz short lupe
jmp short toend ; cx = 0, return 0
jmp short toend // cx = 0, return 0
differ:
mov ecx,-1 ; assume last is bigger
; *** can't use "or ecx,-1" due to flags ***
jb short toend ; last is, in fact, bigger (return -1)
neg ecx ; first is bigger (return 1)
mov ecx,-1 // assume last is bigger
// *** can't use "or ecx,-1" due to flags ***
jb short toend // last is, in fact, bigger (return -1)
neg ecx // first is bigger (return 1)
toend:
mov eax,ecx ; move return value to ax
mov eax,ecx // move return value to ax
ret ; _cdecl return
// Epilog. Original sources used ML's extended PROC feature to autogenerate this.
pop ebx
pop esi
pop edi
pop ebp
__ascii_memicmp endp
ret // _cdecl return
.ENDP // ___ascii_memicmp
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strnicmp - compare n chars of strings, ignore case
;***
@ -62,63 +64,69 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public __ascii_strnicmp
__ascii_strnicmp proc \
uses edi esi ebx, \
first:ptr byte, \
last:ptr byte, \
count:IWORD
public ___ascii_strnicmp
.PROC ___ascii_strnicmp
// Prolog. Original sources used ML's extended PROC feature to autogenerate this.
push ebp
mov ebp, esp
push edi // uses edi esi ebx
push esi
push ebx
#define first ebp + 8 // first:ptr byte
#define last ebp + 12 // last:ptr byte
#define count ebp + 16 // count:IWORD
mov ecx,[count] ; cx = byte count
mov ecx,[count] // cx = byte count
or ecx,ecx
jz toend ; if count = 0, we are done
jz toend // if count = 0, we are done
mov esi,[first] ; si = first string
mov edi,[last] ; di = last string
mov esi,[first] // si = first string
mov edi,[last] // di = last string
mov bh,'A'
mov bl,'Z'
mov dh,'a'-'A' ; add to cap to make lower
mov dh,'a'-'A' // add to cap to make lower
align 4
lupe:
mov ah,[esi] ; *first
mov ah,[esi] // *first
or ah,ah ; see if *first is null
or ah,ah // see if *first is null
mov al,[edi] ; *last
mov al,[edi] // *last
jz short eject ; jump if *first is null
jz short eject // jump if *first is null
or al,al ; see if *last is null
jz short eject ; jump if so
or al,al // see if *last is null
jz short eject // jump if so
add esi,1 ; first++
add edi,1 ; last++
add esi,1 // first++
add edi,1 // last++
cmp ah,bh ; 'A'
cmp ah,bh // 'A'
jb short skip1
cmp ah,bl ; 'Z'
cmp ah,bl // 'Z'
ja short skip1
add ah,dh ; make lower case
add ah,dh // make lower case
skip1:
cmp al,bh ; 'A'
cmp al,bh // 'A'
jb short skip2
cmp al,bl ; 'Z'
cmp al,bl // 'Z'
ja short skip2
add al,dh ; make lower case
add al,dh // make lower case
skip2:
cmp ah,al ; *first == *last ??
cmp ah,al // *first == *last ??
jne short differ
sub ecx,1
@ -126,18 +134,24 @@ skip2:
eject:
xor ecx,ecx
cmp ah,al ; compare the (possibly) differing bytes
je short toend ; both zero; return 0
cmp ah,al // compare the (possibly) differing bytes
je short toend // both zero; return 0
differ:
mov ecx,-1 ; assume last is bigger (* can't use 'or' *)
jb short toend ; last is, in fact, bigger (return -1)
neg ecx ; first is bigger (return 1)
mov ecx,-1 // assume last is bigger (* can't use 'or' *)
jb short toend // last is, in fact, bigger (return -1)
neg ecx // first is bigger (return 1)
toend:
mov eax,ecx
ret ; _cdecl return
// Epilog. Original sources used ML's extended PROC feature to autogenerate this.
pop ebx
pop esi
pop edi
pop ebp
__ascii_strnicmp endp
ret // _cdecl return
.ENDP // ___ascii_strnicmp
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title memccpy - copy bytes until character found
;***
@ -51,85 +53,86 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public _memccpy
_memccpy proc \
dest:ptr byte, \
src:ptr byte, \
_c:byte, \
count:DWORD
public __memccpy
.PROC __memccpy
// dest:ptr byte, \
// src:ptr byte, \
// _c:byte, \
// count:DWORD
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
.FPO ( 0, 4, 0, 0, 0, 0 )
FPO 0, 4, 0, 0, 0, 0
mov ecx,[esp + 10h] ; ecx = max byte count
push ebx ; save ebx
mov ecx,[esp + HEX(10)] // ecx = max byte count
push ebx // save ebx
test ecx,ecx ; if it's nothing to move
jz ret_zero_len ; restore ebx, and return NULL
test ecx,ecx // if it's nothing to move
jz ret_zero_len // restore ebx, and return NULL
mov bh,[esp + 10h] ; bh = byte to look for
push esi ; save esi
mov bh,[esp + HEX(10)] // bh = byte to look for
push esi // save esi
test ecx,1 ; test if counter is odd or even
test ecx,1 // test if counter is odd or even
mov eax,[esp + 0ch] ; eax = dest , don't affect flags
mov esi,[esp + 10h] ; esi = source , don't affect flags
mov eax,[esp + HEX(0c)] // eax = dest , don't affect flags
mov esi,[esp + HEX(10)] // esi = source , don't affect flags
; nop
jz lupe2 ; if counter is even, do double loop
; else do one iteration, and drop into double loop
mov bl,[esi] ; get first byte into bl
add esi,1 ; kick src (esi points to src)
// nop
jz lupe2 // if counter is even, do double loop
// else do one iteration, and drop into double loop
mov bl,[esi] // get first byte into bl
add esi,1 // kick src (esi points to src)
mov [eax],bl ; store it in dest
add eax,1 ; kick dest
mov [eax],bl // store it in dest
add eax,1 // kick dest
cmp bl,bh ; see if we just moved the byte
cmp bl,bh // see if we just moved the byte
je short toend
sub ecx,1 ; decrement counter
jz retnull ; drop into double loop if nonzero
sub ecx,1 // decrement counter
jz retnull // drop into double loop if nonzero
lupe2:
mov bl,[esi] ; get first byte into bl
add esi,2 ; kick esi (src)
mov bl,[esi] // get first byte into bl
add esi,2 // kick esi (src)
cmp bl,bh ; check if we just moved the byte (from bl)
je toend_mov_inc ; store bl & exit
cmp bl,bh // check if we just moved the byte (from bl)
je toend_mov_inc // store bl & exit
mov [eax],bl ; store first byte from bl
mov bl,[esi - 1] ; get second byte into bl
mov [eax],bl // store first byte from bl
mov bl,[esi - 1] // get second byte into bl
mov [eax + 1],bl ; store second byte from bl
add eax,2 ; kick eax (dest)
mov [eax + 1],bl // store second byte from bl
add eax,2 // kick eax (dest)
cmp bl,bh ; see if we just moved the byte
je short toend ; end of string
cmp bl,bh // see if we just moved the byte
je short toend // end of string
sub ecx,2 ; modify counter, and if nonzero continue
jnz lupe2 ; else drop out & return NULL
sub ecx,2 // modify counter, and if nonzero continue
jnz lupe2 // else drop out & return NULL
retnull:
pop esi
ret_zero_len:
xor eax,eax ; null pointer
xor eax,eax // null pointer
pop ebx
ret ; _cdecl return
ret // _cdecl return
toend_mov_inc:
mov [eax],bl ; store first byte from bl
add eax,1 ; eax points right after the value
mov [eax],bl // store first byte from bl
add eax,1 // eax points right after the value
toend: pop esi
pop ebx
ret ; _cdecl return
ret // _cdecl return
_memccpy endp
.ENDP // __memccpy
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strcat - concatenate (append) one string to another
;***
@ -80,39 +82,41 @@ page
;
;Exceptions:
;*******************************************************************************
#endif
CODESEG
.code
% public strcat, strcpy ; make both functions available
strcpy proc \
dst:ptr byte, \
src:ptr byte
public _strcat
public _strcpy // make both functions available
.PROC _strcpy
// dst:ptr byte, \
// src:ptr byte
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
push edi ; preserve edi
mov edi,[esp+8] ; edi points to dest string
push edi // preserve edi
mov edi,[esp+8] // edi points to dest string
jmp short copy_start
strcpy endp
.ENDP // _strcpy
align 16
strcat proc \
dst:ptr byte, \
src:ptr byte
.PROC _strcat
// dst:ptr byte, \
// src:ptr byte
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
.FPO ( 0, 2, 0, 0, 0, 0 )
FPO 0, 2, 0, 0, 0, 0
mov ecx,[esp+4] ; ecx -> dest string
push edi ; preserve edi
test ecx,3 ; test if string is aligned on 32 bits
mov ecx,[esp+4] // ecx -> dest string
push edi // preserve edi
test ecx,3 // test if string is aligned on 32 bits
je short find_end_of_dest_string_loop
dest_misaligned: ; simple byte loop until string is aligned
dest_misaligned: // simple byte loop until string is aligned
mov al,byte ptr [ecx]
add ecx,1
test al,al
@ -123,27 +127,27 @@ dest_misaligned: ; simple byte loop until string is aligned
align 4
find_end_of_dest_string_loop:
mov eax,dword ptr [ecx] ; read 4 bytes
mov edx,7efefeffh
mov eax,dword ptr [ecx] // read 4 bytes
mov edx,HEX(7efefeff)
add edx,eax
xor eax,-1
xor eax,edx
add ecx,4
test eax,81010100h
test eax,HEX(81010100)
je short find_end_of_dest_string_loop
; found zero byte in the loop
// found zero byte in the loop
mov eax,[ecx - 4]
test al,al ; is it byte 0
test al,al // is it byte 0
je short start_byte_0
test ah,ah ; is it byte 1
test ah,ah // is it byte 1
je short start_byte_1
test eax,00ff0000h ; is it byte 2
test eax,HEX(00ff0000) // is it byte 2
je short start_byte_2
test eax,0ff000000h ; is it byte 3
test eax,HEX(0ff000000) // is it byte 3
je short start_byte_3
jmp short find_end_of_dest_string_loop
; taken if bits 24-30 are clear and bit
; 31 is set
// taken if bits 24-30 are clear and bit
// 31 is set
start_byte_3:
lea edi,[ecx - 1]
jmp short copy_start
@ -155,15 +159,15 @@ start_byte_1:
jmp short copy_start
start_byte_0:
lea edi,[ecx - 4]
; jmp short copy_start
// jmp short copy_start
; edi points to the end of dest string.
copy_start::
mov ecx,[esp+0ch] ; ecx -> sorc string
test ecx,3 ; test if string is aligned on 32 bits
// edi points to the end of dest string.
GLOBAL_LABEL copy_start
mov ecx,[esp+HEX(0c)] // ecx -> sorc string
test ecx,3 // test if string is aligned on 32 bits
je short main_loop_entrance
src_misaligned: ; simple byte loop until string is aligned
src_misaligned: // simple byte loop until string is aligned
mov dl,byte ptr [ecx]
add ecx,1
test dl,dl
@ -174,58 +178,58 @@ src_misaligned: ; simple byte loop until string is aligned
jne short src_misaligned
jmp short main_loop_entrance
main_loop: ; edx contains first dword of sorc string
mov [edi],edx ; store one more dword
add edi,4 ; kick dest pointer
main_loop: // edx contains first dword of sorc string
mov [edi],edx // store one more dword
add edi,4 // kick dest pointer
main_loop_entrance:
mov edx,7efefeffh
mov eax,dword ptr [ecx] ; read 4 bytes
mov edx,HEX(7efefeff)
mov eax,dword ptr [ecx] // read 4 bytes
add edx,eax
xor eax,-1
xor eax,edx
mov edx,[ecx] ; it's in cache now
mov edx,[ecx] // it's in cache now
add ecx,4 ; kick dest pointer
test eax,81010100h
add ecx,4 // kick dest pointer
test eax,HEX(81010100)
je short main_loop
; found zero byte in the loop
// found zero byte in the loop
; main_loop_end:
test dl,dl ; is it byte 0
test dl,dl // is it byte 0
je short byte_0
test dh,dh ; is it byte 1
test dh,dh // is it byte 1
je short byte_1
test edx,00ff0000h ; is it byte 2
test edx,HEX(00ff0000) // is it byte 2
je short byte_2
test edx,0ff000000h ; is it byte 3
test edx,HEX(0ff000000) // is it byte 3
je short byte_3
jmp short main_loop ; taken if bits 24-30 are clear and bit
; 31 is set
jmp short main_loop // taken if bits 24-30 are clear and bit
// 31 is set
byte_3:
mov [edi],edx
mov eax,[esp+8] ; return in eax pointer to dest string
mov eax,[esp+8] // return in eax pointer to dest string
pop edi
ret
byte_2:
mov [edi],dx
mov eax,[esp+8] ; return in eax pointer to dest string
mov eax,[esp+8] // return in eax pointer to dest string
mov byte ptr [edi+2],0
pop edi
ret
byte_1:
mov [edi],dx
mov eax,[esp+8] ; return in eax pointer to dest string
mov eax,[esp+8] // return in eax pointer to dest string
pop edi
ret
byte_0:
mov [edi],dl
mov eax,[esp+8] ; return in eax pointer to dest string
mov eax,[esp+8] // return in eax pointer to dest string
pop edi
ret
strcat endp
.ENDP // _strcat
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strcmp.asm - compare two strings
;***
@ -58,21 +60,22 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public strcmp
strcmp proc \
str1:ptr byte, \
str2:ptr byte
public _strcmp
.PROC _strcmp
// str1:ptr byte, \
// str2:ptr byte
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
; .FPO (cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame)
.FPO ( 0, 2, 0, 0, 0, 0 )
// .FPO (cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame)
FPO 0, 2, 0, 0, 0, 0
mov edx,[esp + 4] ; edx = src
mov ecx,[esp + 8] ; ecx = dst
mov edx,[esp + 4] // edx = src
mov ecx,[esp + 8] // ecx = dst
test edx,3
jnz short dopartial
@ -110,8 +113,8 @@ doneeq:
align 8
donene:
; The instructions below should place -1 in eax if src < dst,
; and 1 in eax if src > dst.
// The instructions below should place -1 in eax if src < dst,
// and 1 in eax if src > dst.
sbb eax,eax
or eax,1
@ -149,6 +152,6 @@ doword:
add ecx,2
jmp short dodwords
strcmp endp
.ENDP // _strcmp
end

View file

@ -1,3 +1,4 @@
#if 0
;***
;strcspn.asm -
;
@ -14,3 +15,7 @@
SSTRCSPN EQU 1
INCLUDE STRSPN.ASM
#else
#define SSTRCSPN 1
#include "strspn.s"
#endif

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strlen - return the length of a null-terminated string
;***
@ -46,26 +48,27 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public strlen
public _strlen
strlen proc \
buf:ptr byte
.PROC _strlen
// buf:ptr byte
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
.FPO ( 0, 1, 0, 0, 0, 0 )
FPO 0, 1, 0, 0, 0, 0
string equ [esp + 4]
#define string [esp + 4]
mov ecx,string ; ecx -> string
test ecx,3 ; test if string is aligned on 32 bits
mov ecx,string // ecx -> string
test ecx,3 // test if string is aligned on 32 bits
je short main_loop
str_misaligned:
; simple byte loop until string is aligned
// simple byte loop until string is aligned
mov al,byte ptr [ecx]
add ecx,1
test al,al
@ -73,31 +76,31 @@ str_misaligned:
test ecx,3
jne short str_misaligned
add eax,dword ptr 0 ; 5 byte nop to align label below
add eax,dword ptr 0 // 5 byte nop to align label below
align 16 ; should be redundant
align 16 // should be redundant
main_loop:
mov eax,dword ptr [ecx] ; read 4 bytes
mov edx,7efefeffh
mov eax,dword ptr [ecx] // read 4 bytes
mov edx,HEX(7efefeff)
add edx,eax
xor eax,-1
xor eax,edx
add ecx,4
test eax,81010100h
test eax,HEX(81010100)
je short main_loop
; found zero byte in the loop
// found zero byte in the loop
mov eax,[ecx - 4]
test al,al ; is it byte 0
test al,al // is it byte 0
je short byte_0
test ah,ah ; is it byte 1
test ah,ah // is it byte 1
je short byte_1
test eax,00ff0000h ; is it byte 2
test eax,HEX(00ff0000) // is it byte 2
je short byte_2
test eax,0ff000000h ; is it byte 3
test eax,HEX(0ff000000) // is it byte 3
je short byte_3
jmp short main_loop ; taken if bits 24-30 are clear and bit
; 31 is set
jmp short main_loop // taken if bits 24-30 are clear and bit
// 31 is set
byte_3:
lea eax,[ecx - 1]
@ -120,6 +123,6 @@ byte_0:
sub eax,ecx
ret
strlen endp
.ENDP // _strlen
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strncat - append n chars of string1 to string2
;***
@ -57,29 +59,30 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public strncat
strncat proc
; front:ptr byte,
; back:ptr byte,
; count:IWORD
public _strncat
.PROC _strncat
// front:ptr byte,
// back:ptr byte,
// count:IWORD
.FPO ( 0, 3, 0, 0, 0, 0 )
FPO 0, 3, 0, 0, 0, 0
mov ecx,[esp + 0ch] ; ecx = count
push edi ; preserve edi
mov ecx,[esp + HEX(0c)] // ecx = count
push edi // preserve edi
test ecx,ecx
jz finish ; leave if count is zero
jz finish // leave if count is zero
mov edi,[esp + 8] ; edi -> front string
push esi ; preserve esi
test edi,3 ; is string aligned on dword (4 bytes)
push ebx ; preserve ebx
mov edi,[esp + 8] // edi -> front string
push esi // preserve esi
test edi,3 // is string aligned on dword (4 bytes)
push ebx // preserve ebx
je short find_end_of_front_string_loop
; simple byte loop until string is aligned
// simple byte loop until string is aligned
front_misaligned:
mov al,byte ptr [edi]
@ -90,27 +93,27 @@ front_misaligned:
jne short front_misaligned
find_end_of_front_string_loop:
mov eax,dword ptr [edi] ; read dword (4 bytes)
mov edx,7efefeffh
mov eax,dword ptr [edi] // read dword (4 bytes)
mov edx,HEX(7efefeff)
add edx,eax
xor eax,-1
xor eax,edx
add edi,4
test eax,81010100h
test eax,HEX(81010100)
je short find_end_of_front_string_loop
; found zero byte in the loop
// found zero byte in the loop
mov eax,[edi - 4]
test al,al ; is it byte 0
test al,al // is it byte 0
je short start_byte_0
test ah,ah ; is it byte 1
test ah,ah // is it byte 1
je short start_byte_1
test eax,00ff0000h ; is it byte 2
test eax,HEX(00ff0000) // is it byte 2
je short start_byte_2
test eax,0ff000000h ; is it byte 3
test eax,HEX(0ff000000) // is it byte 3
jne short find_end_of_front_string_loop
; taken if bits 24-30 are clear and bit
; 31 is set
// taken if bits 24-30 are clear and bit
// 31 is set
start_byte_3:
sub edi,1
jmp short copy_start
@ -123,20 +126,20 @@ start_byte_1:
start_byte_0:
sub edi,4
; edi now points to the end of front string.
// edi now points to the end of front string.
copy_start:
mov esi,[esp + 14h] ; esi -> back string
test esi,3 ; is back string is dword aligned?
mov esi,[esp + HEX(14)] // esi -> back string
test esi,3 // is back string is dword aligned?
jnz back_misaligned
mov ebx,ecx ; store count for tail loop
mov ebx,ecx // store count for tail loop
shr ecx,2
jnz short main_loop_entrance
jmp short tail_loop_start ; 0 < counter < 4
jmp short tail_loop_start // 0 < counter < 4
; simple byte loop until back string is aligned
// simple byte loop until back string is aligned
back_misaligned:
mov dl,byte ptr [esi]
@ -149,14 +152,14 @@ back_misaligned:
jz empty_counter
test esi,3
jne short back_misaligned
mov ebx,ecx ; store count for tail loop
shr ecx,2 ; convert ecx to dword count
mov ebx,ecx // store count for tail loop
shr ecx,2 // convert ecx to dword count
jnz short main_loop_entrance
tail_loop_start:
mov ecx,ebx
and ecx,3 ; ecx = count of leftover bytes after the
; dwords have been concatenated
and ecx,3 // ecx = count of leftover bytes after the
// dwords have been concatenated
jz empty_counter
tail_loop:
@ -165,88 +168,88 @@ tail_loop:
mov [edi],dl
add edi,1
test dl,dl
je short finish1 ; '\0' was already copied
je short finish1 // '\0' was already copied
sub ecx,1
jnz tail_loop
empty_counter:
mov [edi],cl ; cl=0;
mov [edi],cl // cl=0;
finish1:
pop ebx
pop esi
finish:
mov eax,[esp + 8] ; return in eax pointer to front string
mov eax,[esp + 8] // return in eax pointer to front string
pop edi
ret ; _cdecl return
ret // _cdecl return
byte_0:
mov [edi],dl
mov eax,[esp + 10h] ; return in eax pointer to front string
mov eax,[esp + HEX(10)] // return in eax pointer to front string
pop ebx
pop esi
pop edi
ret ; _cdecl return
ret // _cdecl return
main_loop: ; edx contains first dword of back string
mov [edi],edx ; store one more dword
add edi,4 ; kick pointer to front string
main_loop: // edx contains first dword of back string
mov [edi],edx // store one more dword
add edi,4 // kick pointer to front string
sub ecx,1
jz tail_loop_start
main_loop_entrance:
mov edx,7efefeffh
mov eax,dword ptr [esi] ; read 4 bytes
mov edx,HEX(7efefeff)
mov eax,dword ptr [esi] // read 4 bytes
add edx,eax
xor eax,-1
xor eax,edx
mov edx,[esi] ; it's in cache now
mov edx,[esi] // it's in cache now
add esi,4 ; kick pointer to back string
test eax,81010100h
add esi,4 // kick pointer to back string
test eax,HEX(81010100)
je short main_loop
; may be found zero byte in the loop
test dl,dl ; is it byte 0
// may be found zero byte in the loop
test dl,dl // is it byte 0
je short byte_0
test dh,dh ; is it byte 1
test dh,dh // is it byte 1
je short byte_1
test edx,00ff0000h ; is it byte 2
test edx,HEX(00ff0000) // is it byte 2
je short byte_2
test edx,0ff000000h ; is it byte 3
jne short main_loop ; taken if bits 24-30 are clear and bit
; 31 is set
test edx,HEX(0ff000000) // is it byte 3
jne short main_loop // taken if bits 24-30 are clear and bit
// 31 is set
byte_3:
mov [edi],edx
mov eax,[esp + 10h] ; return in eax pointer to front string
mov eax,[esp + HEX(10)] // return in eax pointer to front string
pop ebx
pop esi
pop edi
ret ; _cdecl return
ret // _cdecl return
byte_2:
mov [edi],dx
xor edx,edx
mov eax,[esp + 10h] ; return in eax pointer to front string
mov eax,[esp + HEX(10)] // return in eax pointer to front string
mov [edi + 2],dl
pop ebx
pop esi
pop edi
ret ; _cdecl return
ret // _cdecl return
byte_1:
mov [edi],dx
mov eax,[esp + 10h] ; return in eax pointer to front string
mov eax,[esp + HEX(10)] // return in eax pointer to front string
pop ebx
pop esi
pop edi
ret ; _cdecl return
ret // _cdecl return
strncat endp
.ENDP // _strncat
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strncmp.asm - compare two strings
;***
@ -73,43 +75,44 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
CHAR_TYPE EQU BYTE
CHAR_PTR EQU BYTE PTR
CHAR_SIZE = sizeof CHAR_TYPE
#define CHAR_TYPE BYTE
#define CHAR_PTR BYTE PTR
#define CHAR_SIZE 1 // = sizeof CHAR_TYPE
BLK_TYPE EQU DWORD
BLK_PTR EQU DWORD PTR
BLK_SIZE = sizeof BLK_TYPE
BLK_CHARS = BLK_SIZE / CHAR_SIZE
#define BLK_TYPE DWORD
#define BLK_PTR DWORD PTR
#define BLK_SIZE 4 // = sizeof BLK_TYPE
#define BLK_CHARS 4 // = BLK_SIZE / CHAR_SIZE
PAGE_SIZE = 1000h
PAGE_MASK = PAGE_SIZE - 1 ; mask for offset in MM page
PAGE_SAFE_BLK = PAGE_SIZE - BLK_SIZE ; maximum offset for safe block compare
PAGE_SIZE = HEX(1000)
PAGE_MASK = PAGE_SIZE - 1 // mask for offset in MM page
PAGE_SAFE_BLK = PAGE_SIZE - BLK_SIZE // maximum offset for safe block compare
public strncmp
strncmp proc \
uses ebx esi, \
str1:ptr byte, \
str2:ptr byte, \
count:IWORD
public _strncmp
.PROC _strncmp
// uses ebx esi, \
// str1:ptr byte, \
// str2:ptr byte, \
// count:IWORD
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
push ebx
push esi
; .FPO (cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame)
.FPO ( 0, 3, $ - strncmp, 2, 0, 0 )
// .FPO (cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame)
FPO 0, 3, ($ - _strncmp), 2, 0, 0
mov ecx,[esp + 12] ; ecx = str1
mov edx,[esp + 16] ; edx = str2
mov ebx,[esp + 20] ; ebx = count
mov ecx,[esp + 12] // ecx = str1
mov edx,[esp + 16] // edx = str2
mov ebx,[esp + 20] // ebx = count
; Check for a limit of zero characters.
test ebx, 0FFFFFFFFh
// Check for a limit of zero characters.
test ebx, HEX(0FFFFFFFF)
jz return_equal
sub ecx, edx
@ -146,11 +149,11 @@ dword_loop_begin:
sub ebx, BLK_CHARS
jbe return_equal
lea esi, [eax+0fefefeffh]
lea esi, [eax+HEX(0fefefeff)]
add edx, BLK_SIZE
not eax
and eax, esi
test eax, 80808080h
test eax, HEX(80808080)
jz dword_loop_begin
return_equal:
@ -162,12 +165,12 @@ return_equal:
align 16
return_not_equal:
sbb eax, eax ; AX=-1, CY=1 AX=0, CY=0
sbb eax, eax // AX=-1, CY=1 AX=0, CY=0
or eax, 1
pop esi
pop ebx
ret
strncmp endp
.ENDP // _strncmp
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strncpy - copy at most n characters of string
;***
@ -55,95 +57,96 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public strncpy
strncpy proc \
dest:ptr byte, \
source:ptr byte, \
count:dword
public _strncpy
.PROC _strncpy
// dest:ptr byte, \
// source:ptr byte, \
// count:dword
OPTION PROLOGUE:NONE, EPILOGUE:NONE
//OPTION PROLOGUE:NONE, EPILOGUE:NONE
.FPO ( 0, 3, 0, 0, 0, 0 )
FPO 0, 3, 0, 0, 0, 0
mov ecx,[esp + 0ch] ; ecx = count
push edi ; preserve edi
mov ecx,[esp + HEX(0c)] // ecx = count
push edi // preserve edi
test ecx,ecx
jz finish ; leave if count is zero
jz finish // leave if count is zero
push esi ; preserve edi
push ebx ; preserve ebx
mov ebx,ecx ; store count for tail loop
mov esi,[esp + 14h] ; esi -> source string
test esi,3 ; test if source string is aligned on 32 bits
mov edi,[esp + 10h] ; edi -> dest string
jnz short src_misaligned ; (almost always source is aligned)
push esi // preserve edi
push ebx // preserve ebx
mov ebx,ecx // store count for tail loop
mov esi,[esp + HEX(14)] // esi -> source string
test esi,3 // test if source string is aligned on 32 bits
mov edi,[esp + HEX(10)] // edi -> dest string
jnz short src_misaligned // (almost always source is aligned)
shr ecx,2 ; convert ecx to dword count
shr ecx,2 // convert ecx to dword count
jnz main_loop_entrance
jmp short copy_tail_loop ; 0 < count < 4
jmp short copy_tail_loop // 0 < count < 4
; simple byte loop until string is aligned
// simple byte loop until string is aligned
src_misaligned:
mov al,byte ptr [esi] ; copy a byte from source to dest
mov al,byte ptr [esi] // copy a byte from source to dest
add esi,1
mov [edi],al
add edi,1
sub ecx,1
jz fill_tail_end1 ; if count == 0, leave
test al,al ; was last copied byte zero?
jz short align_dest ; if so, go align dest and pad it out
; with zeros
test esi,3 ; esi already aligned ?
jz fill_tail_end1 // if count == 0, leave
test al,al // was last copied byte zero?
jz short align_dest // if so, go align dest and pad it out
// with zeros
test esi,3 // esi already aligned ?
jne short src_misaligned
mov ebx,ecx ; store count for tail loop
mov ebx,ecx // store count for tail loop
shr ecx,2
jnz short main_loop_entrance
tail_loop_start:
and ebx,3 ; ebx = count_before_main_loop%4
jz short fill_tail_end1 ; if ebx == 0 then leave without
; appending a null byte
and ebx,3 // ebx = count_before_main_loop%4
jz short fill_tail_end1 // if ebx == 0 then leave without
// appending a null byte
; while ( EOS (end-of-string) not found and count > 0 ) copy bytes
// while ( EOS (end-of-string) not found and count > 0 ) copy bytes
copy_tail_loop:
mov al,byte ptr [esi] ; load byte from source
mov al,byte ptr [esi] // load byte from source
add esi,1
mov [edi],al ; store byte to dest
mov [edi],al // store byte to dest
add edi,1
test al,al ; EOS found?
je short fill_tail_zero_bytes ; '\0' was already copied
test al,al // EOS found?
je short fill_tail_zero_bytes // '\0' was already copied
sub ebx,1
jnz copy_tail_loop
fill_tail_end1:
mov eax,[esp + 10h] ; prepare return value
mov eax,[esp + HEX(10)] // prepare return value
pop ebx
pop esi
pop edi
ret
; EOS found. Pad with null characters to length count
// EOS found. Pad with null characters to length count
align_dest:
test edi,3 ; dest string aligned?
test edi,3 // dest string aligned?
jz dest_align_loop_end
dest_align_loop:
mov [edi],al
add edi,1
sub ecx,1 ; count == 0?
jz fill_tail_end ; if so, finished
test edi,3 ; is edi aligned ?
sub ecx,1 // count == 0?
jz fill_tail_end // if so, finished
test edi,3 // is edi aligned ?
jnz dest_align_loop
dest_align_loop_end:
mov ebx,ecx ; ebx > 0
shr ecx,2 ; convert ecx to count of dwords
mov ebx,ecx // ebx > 0
shr ecx,2 // convert ecx to count of dwords
jnz fill_dwords_with_EOS
; pad tail bytes
finish_loop: ; 0 < ebx < 4
// pad tail bytes
finish_loop: // 0 < ebx < 4
mov [edi],al
add edi,1
fill_tail_zero_bytes:
@ -152,68 +155,68 @@ fill_tail_zero_bytes:
pop ebx
pop esi
finish:
mov eax,[esp + 8] ; return in eax pointer to dest string
mov eax,[esp + 8] // return in eax pointer to dest string
pop edi
ret
; copy (source) string to (dest). Also look for end of (source) string
// copy (source) string to (dest). Also look for end of (source) string
main_loop: ; edx contains first dword of source string
mov [edi],edx ; store one more dword
add edi,4 ; kick dest pointer
main_loop: // edx contains first dword of source string
mov [edi],edx // store one more dword
add edi,4 // kick dest pointer
sub ecx,1
jz tail_loop_start
main_loop_entrance:
mov edx,7efefeffh
mov eax,dword ptr [esi] ; read 4 bytes (dword)
mov edx,HEX(7efefeff)
mov eax,dword ptr [esi] // read 4 bytes (dword)
add edx,eax
xor eax,-1
xor eax,edx
mov edx,[esi] ; it's in cache now
add esi,4 ; kick dest pointer
test eax,81010100h
mov edx,[esi] // it's in cache now
add esi,4 // kick dest pointer
test eax,HEX(81010100)
je short main_loop
; may have found zero byte in the dword
// may have found zero byte in the dword
test dl,dl ; is it byte 0
test dl,dl // is it byte 0
je short byte_0
test dh,dh ; is it byte 1
test dh,dh // is it byte 1
je short byte_1
test edx,00ff0000h ; is it byte 2
test edx,HEX(00ff0000) // is it byte 2
je short byte_2
test edx,0ff000000h ; is it byte 3
jne short main_loop ; taken if bits 24-30 are clear and bit
; 31 is set
test edx,HEX(0ff000000) // is it byte 3
jne short main_loop // taken if bits 24-30 are clear and bit
// 31 is set
; a null character was found, so dest needs to be padded out with null chars
; to count length.
// a null character was found, so dest needs to be padded out with null chars
// to count length.
mov [edi],edx
jmp short fill_with_EOS_dwords
byte_2:
and edx,0ffffh ; fill high 2 bytes with 0
and edx,HEX(0ffff) // fill high 2 bytes with 0
mov [edi],edx
jmp short fill_with_EOS_dwords
byte_1:
and edx,0ffh ; fill high 3 bytes with 0
and edx,HEX(0ff) // fill high 3 bytes with 0
mov [edi],edx
jmp short fill_with_EOS_dwords
byte_0:
xor edx,edx ; fill whole dword with 0
xor edx,edx // fill whole dword with 0
mov [edi],edx
; End of string was found. Pad out dest string with dwords of 0
// End of string was found. Pad out dest string with dwords of 0
fill_with_EOS_dwords: ; ecx > 0 (ecx is dword counter)
fill_with_EOS_dwords: // ecx > 0 (ecx is dword counter)
add edi,4
xor eax,eax ; it is instead of ???????????????????
xor eax,eax // it is instead of ???????????????????
sub ecx,1
jz fill_tail ; we filled all dwords
jz fill_tail // we filled all dwords
fill_dwords_with_EOS:
xor eax,eax
@ -222,17 +225,17 @@ fill_with_EOS_loop:
add edi,4
sub ecx,1
jnz short fill_with_EOS_loop
fill_tail: ; let's pad tail bytes with zero
and ebx,3 ; ebx = ebx % 4
jnz finish_loop ; taken, when there are some tail bytes
fill_tail: // let's pad tail bytes with zero
and ebx,3 // ebx = ebx % 4
jnz finish_loop // taken, when there are some tail bytes
fill_tail_end:
mov eax,[esp + 10h]
mov eax,[esp + HEX(10)]
pop ebx
pop esi
pop edi
ret
strncpy endp
.ENDP // _strncpy
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strnset - set first n characters to one char.
;***
@ -50,40 +52,49 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public _strnset
_strnset proc \
uses edi ebx, \
string:ptr byte, \
val:byte, \
count:IWORD
public __strnset
.PROC __strnset
// Prolog. Original sources used ML's extended PROC feature to autogenerate this.
push ebp
mov ebp, esp
push edi // uses edi ebx
push ebx
#define string ebp + 8 // string:ptr byte
#define val ebp + 12 // val:byte
#define count ebp + 16 // count:IWORD
mov edi,[string] ; di = string
mov edx,edi ; dx=string addr; save return value
mov ebx,[count] ; cx = max chars to set
xor eax,eax ; null byte
mov edi,[string] // di = string
mov edx,edi // dx=string addr; save return value
mov ebx,[count] // cx = max chars to set
xor eax,eax // null byte
mov ecx,ebx
jecxz short done ; zero length specified
jecxz short done // zero length specified
repne scasb ; find null byte & count bytes in cx
jne short nonull ; null not found
add ecx,1 ; don't want the null
repne scasb // find null byte & count bytes in cx
jne short nonull // null not found
add ecx,1 // don't want the null
nonull:
sub ebx,ecx ; bx=strlen (not null)
mov ecx,ebx ; cx=strlen (not null)
sub ebx,ecx // bx=strlen (not null)
mov ecx,ebx // cx=strlen (not null)
mov edi,edx ; restore string pointer
mov al,val ; byte value
rep stosb ; fill 'er up
mov edi,edx // restore string pointer
mov al,[val] // byte value
rep stosb // fill 'er up
done:
mov eax,edx ; return value: string addr
mov eax,edx // return value: string addr
ret ; _cdecl return
// Epilog. Original sources used ML's extended PROC feature to autogenerate this.
pop ebx
pop edi
pop ebp
ret // _cdecl return
_strnset endp
.ENDP // __strnset
end

View file

@ -1,3 +1,4 @@
#if 0
;***
;strpbrk.asm -
;
@ -14,3 +15,7 @@
SSTRPBRK EQU 1
INCLUDE STRSPN.ASM
#else
#define SSTRPBRK 1
#include "strspn.s"
#endif

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strrev - reverse a string in place
;***
@ -63,43 +65,52 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public _strrev
_strrev proc \
uses edi esi, \
string:ptr byte
public __strrev
.PROC __strrev
// Prolog. Original sources used ML's extended PROC feature to autogenerate this.
push ebp
mov ebp, esp
push edi // uses edi esi
push esi
#define string ebp + 8 // string:ptr byte
mov edi,[string] ; di = string
mov edx,edi ; dx=pointer to string; save return value
mov edi,[string] // di = string
mov edx,edi // dx=pointer to string; save return value
mov esi,edi ; si=pointer to string
xor eax,eax ; search value (null)
or ecx,-1 ; cx = -1
repne scasb ; find null
cmp ecx,-2 ; is string empty? (if offset value is 0, the
je short done ; cmp below will not catch it and we'll hang).
mov esi,edi // si=pointer to string
xor eax,eax // search value (null)
or ecx,-1 // cx = -1
repne scasb // find null
cmp ecx,-2 // is string empty? (if offset value is 0, the
je short done // cmp below will not catch it and we'll hang).
sub edi,2 ; string is not empty, move di pointer back
; di points to last non-null byte
sub edi,2 // string is not empty, move di pointer back
// di points to last non-null byte
lupe:
cmp esi,edi ; see if pointers have crossed yet
jae short done ; exit when pointers meet (or cross)
cmp esi,edi // see if pointers have crossed yet
jae short done // exit when pointers meet (or cross)
mov ah,[esi] ; get front byte...
mov al,[edi] ; and end byte
mov [esi],al ; put end byte in front...
mov [edi],ah ; and front byte at end
add esi,1 ; front moves up...
sub edi,1 ; and end moves down
jmp short lupe ; keep switching bytes
mov ah,[esi] // get front byte...
mov al,[edi] // and end byte
mov [esi],al // put end byte in front...
mov [edi],ah // and front byte at end
add esi,1 // front moves up...
sub edi,1 // and end moves down
jmp short lupe // keep switching bytes
done:
mov eax,edx ; return value: string addr
mov eax,edx // return value: string addr
ret ; _cdecl return
// Epilog. Original sources used ML's extended PROC feature to autogenerate this.
pop esi
pop edi
pop ebp
ret // _cdecl return
_strrev endp
.ENDP // __strrev
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strset - set all characters of string to character
;***
@ -48,31 +50,39 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
CODESEG
.code
public _strset
_strset proc \
uses edi, \
string:ptr byte, \
val:byte
public __strset
.PROC __strset
// Prolog. Original sources used ML's extended PROC feature to autogenerate this.
push ebp
mov ebp, esp
push edi // uses edi
#define string ebp + 8 // string:ptr byte
#define val ebp + 12 // val:byte
mov edi,[string] ; di = string
mov edx,edi ; dx=string addr; save return value
mov edi,[string] // di = string
mov edx,edi // dx=string addr; save return value
xor eax,eax ; ax = 0
or ecx,-1 ; cx = -1
repne scasb ; scan string & count bytes
add ecx,2 ; cx=-strlen
neg ecx ; cx=strlen
mov al,[val] ; al = byte value to store
mov edi,edx ; di=string addr
xor eax,eax // ax = 0
or ecx,-1 // cx = -1
repne scasb // scan string & count bytes
add ecx,2 // cx=-strlen
neg ecx // cx=strlen
mov al,[val] // al = byte value to store
mov edi,edx // di=string addr
rep stosb
mov eax,edx ; return value: string addr
mov eax,edx // return value: string addr
ret ; _cdecl return
// Epilog. Original sources used ML's extended PROC feature to autogenerate this.
pop edi
pop ebp
_strset endp
ret // _cdecl return
.ENDP // __strset
end

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132
title strspn - search for init substring of chars from control str
;***
@ -165,54 +167,58 @@ page
;Exceptions:
;
;*******************************************************************************
#endif
ifdef SSTRCSPN
#ifdef SSTRCSPN
_STRSPN_ equ <strcspn>
#define _STRSPN_ _strcspn
elseifdef SSTRPBRK
#elif defined(SSTRPBRK)
_STRSPN_ equ <strpbrk>
#define _STRSPN_ _strpbrk
else ; SSTRCSPN
#else // SSTRCSPN
; Default is to build strspn()
// Default is to build strspn()
SSTRSPN equ 1
_STRSPN_ equ <strspn>
#define SSTRSPN 1
#define _STRSPN_ _strspn
endif ; SSTRCSPN
#endif // SSTRCSPN
% public _STRSPN_
public _STRSPN_
CODESEG
.code
_STRSPN_ proc \
uses esi, \
string:ptr byte, \
control:ptr byte
.PROC _STRSPN_
// Prolog. Original sources used ML's extended PROC feature to autogenerate this.
push ebp
mov ebp, esp
push esi // uses esi
#define string ebp + 8 // string:ptr byte
#define control ebp + 12 // control:ptr byte
; create and zero out char bit map
// create and zero out char bit map
xor eax,eax
push eax ; 32
push eax // 32
push eax
push eax
push eax ; 128
push eax // 128
push eax
push eax
push eax
push eax ; 256
push eax // 256
map equ [esp]
#define map [esp]
; Set control char bits in map
// Set control char bits in map
mov edx,control ; si = control string
mov edx,[control] // si = control string
align @WordSize
lab listnext ; init char bit map
align 4 // @WordSize
listnext: // init char bit map
mov al,[edx]
or al,al
jz short listdone
@ -220,18 +226,22 @@ lab listnext ; init char bit map
bts map,eax
jmp short listnext
lab listdone
listdone:
; Loop through comparing source string with control bits
// Loop through comparing source string with control bits
mov esi,string ; si = string
mov esi,[string] // si = string
_ifnd SSTRPBRK, <or ecx,-1> ; set ecx to -1
#ifndef SSTRPBRK
or ecx,-1 // set ecx to -1
#endif
align @WordSize
lab dstnext
align 4 // @WordSize
dstnext:
_ifnd SSTRPBRK, <add ecx,1>
#ifndef SSTRPBRK
add ecx,1
#endif
mov al,[esi]
or al,al
@ -239,24 +249,30 @@ _ifnd SSTRPBRK, <add ecx,1>
add esi,1
bt map, eax
ifdef SSTRSPN
jc short dstnext ; strspn: found char, continue
elseifdef SSTRCSPN
jnc short dstnext ; strcspn: did not find char, continue
elseifdef SSTRPBRK
jnc short dstnext ; strpbrk: did not find char, continue
lea eax,[esi - 1] ; found char, return address of it
endif ; SSTRSPN
#ifdef SSTRSPN
jc short dstnext // strspn: found char, continue
#elif defined SSTRCSPN
jnc short dstnext // strcspn: did not find char, continue
#elif defined SSTRPBRK
jnc short dstnext // strpbrk: did not find char, continue
lea eax,[esi - 1] // found char, return address of it
#endif // SSTRSPN
; Return code
// Return code
lab dstdone
dstdone:
_ifnd SSTRPBRK, <mov eax,ecx> ; strspn/strcspn: return index
#ifndef SSTRPBRK
mov eax,ecx // strspn/strcspn: return index
#endif
add esp,32
ret ; _cdecl return
// Epilog. Original sources used ML's extended PROC feature to autogenerate this.
pop esi
pop ebp
_STRSPN_ endp
ret // _cdecl return
.ENDP // _STRSPN_
end