[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 .endm
/* MASM compatible ALIGN */ /* MASM compatible ALIGN */
#define ALIGN .align .macro align x
#define align .align .align x
.endm
#define ALIGN align
/* MASM compatible REPEAT, additional ENDR */ /* MASM compatible REPEAT, additional ENDR */
#define REPEAT .rept #define REPEAT .rept
@ -352,6 +354,7 @@ ENDM
/* MASM needs an END tag */ /* MASM needs an END tag */
#define END #define END
#define end
.macro .MODEL model .macro .MODEL model
.endm .endm
@ -359,6 +362,7 @@ ENDM
.macro .code .macro .code
.text .text
.endm .endm
#define CODESEG .code
.macro .const .macro .const
.section .rdata .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 title strcat - concatenate (append) one string to another
;*** ;***
;strcat.asm - contains strcat() and strcpy() routines ;strcat.asm - contains strcat() and strcpy() routines
@ -73,11 +77,12 @@ include ksamd64.inc
; ;
;Exceptions: ;Exceptions:
;******************************************************************************* ;*******************************************************************************
#endif
public ___entry_from_strcat_in_strcpy 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 mov r11, rcx
test cl, 7 test cl, 7
@ -94,12 +99,12 @@ strcat_copy_head_loop_begin:
strcat_loop_begin: strcat_loop_begin:
mov rax, [rcx] mov rax, [rcx]
mov r10, rax mov r10, rax
mov r9, 7efefefefefefeffh mov r9, HEX(7efefefefefefeff)
add r9, r10 add r9, r10
xor r10, -1 xor r10, -1
xor r10, r9 xor r10, r9
add rcx, 8 add rcx, 8
mov r9, 8101010101010100h mov r9, HEX(8101010101010100)
test r10, r9 test r10, r9
je strcat_loop_begin je strcat_loop_begin
sub rcx, 8 sub rcx, 8
@ -136,16 +141,16 @@ strcat_loop_end:
LEAF_END strcat, _TEXT 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 mov r11, rcx
strcat_copy: strcat_copy:
___entry_from_strcat_in_strcpy=strcat_copy ___entry_from_strcat_in_strcpy=strcat_copy
; align the SOURCE so we never page fault // align the SOURCE so we never page fault
; dest pointer alignment not important // dest pointer alignment not important
sub rcx, rdx ; combine pointers sub rcx, rdx // combine pointers
test dl, 7 test dl, 7
jz qword_loop_entrance jz qword_loop_entrance
@ -168,12 +173,12 @@ qword_loop_begin:
add rdx, 8 add rdx, 8
qword_loop_entrance: qword_loop_entrance:
mov rax, [rdx] mov rax, [rdx]
mov r9, 7efefefefefefeffh mov r9, HEX(7efefefefefefeff)
add r9, rax add r9, rax
mov r10, rax mov r10, rax
xor r10, -1 xor r10, -1
xor r10, r9 xor r10, r9
mov r9, 8101010101010100h mov r9, HEX(8101010101010100)
test r10, r9 test r10, r9
jz qword_loop_begin jz qword_loop_begin

View file

@ -1,3 +1,7 @@
#include <asm.inc>
#include <ksamd64.inc>
.code64
#if 0
page ,132 page ,132
title strcmp.asm - compare two strings title strcmp.asm - compare two strings
;*** ;***
@ -54,25 +58,26 @@ include ksamd64.inc
;Exceptions: ;Exceptions:
; ;
;******************************************************************************* ;*******************************************************************************
#endif
CHAR_TYPE EQU BYTE #define CHAR_TYPE BYTE
CHAR_PTR EQU BYTE PTR #define CHAR_PTR BYTE PTR
CHAR_SIZE = sizeof CHAR_TYPE #define CHAR_SIZE 1 /* = sizeof CHAR_TYPE */
BLK_TYPE EQU QWORD #define BLK_TYPE QWORD
BLK_PTR EQU QWORD PTR #define BLK_PTR QWORD PTR
BLK_SIZE = sizeof BLK_TYPE #define BLK_SIZE 8 /* = sizeof BLK_TYPE */
;PAGE_SIZE = 1000h //PAGE_SIZE = 1000h
PAGE_MASK = PAGE_SIZE - 1 ; mask for offset in MM page 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_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 // rcx = src
; rdx = dst // rdx = dst
sub rdx, rcx sub rdx, rcx
test cl, (BLK_SIZE - 1) test cl, (BLK_SIZE - 1)
@ -93,8 +98,8 @@ comp_head_loop_begin:
qword_loop_enter: qword_loop_enter:
mov r11, 8080808080808080h mov r11, HEX(8080808080808080)
mov r10, 0fefefefefefefeffh mov r10, HEX(0fefefefefefefeff)
qword_loop_begin: qword_loop_begin:
lea eax, [edx+ecx] lea eax, [edx+ecx]
@ -105,24 +110,24 @@ qword_loop_begin:
mov rax, BLK_PTR[rcx] mov rax, BLK_PTR[rcx]
cmp rax, BLK_PTR[rdx+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 jne comp_head_loop_begin
; look for null terminator // look for null terminator
lea r9, [rax + r10] lea r9, [rax + r10]
not rax not rax
add rcx, BLK_SIZE add rcx, BLK_SIZE
and rax, r9 and rax, r9
test rax, r11 ; r11=8080808080808080h test rax, r11 // r11=8080808080808080h
jz qword_loop_begin jz qword_loop_begin
return_equal: return_equal:
xor eax, eax ; gets all 64 bits xor eax, eax // gets all 64 bits
ret ret
return_not_equal: 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 or rax, 1
ret ret

View file

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

View file

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

View file

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

View file

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

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132 page ,132
title memicmp - compare blocks of memory, ignore case title memicmp - compare blocks of memory, ignore case
;*** ;***
@ -54,77 +56,90 @@ page
;Exceptions: ;Exceptions:
; ;
;******************************************************************************* ;*******************************************************************************
#endif
CODESEG .code
public __ascii_memicmp public ___ascii_memicmp
__ascii_memicmp proc \ .PROC ___ascii_memicmp
uses edi esi ebx, \
first:ptr byte, \
last:ptr byte, \
count:IWORD
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 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 esi,[first] // si = first
mov edi,[last] ; di = last mov edi,[last] // di = last
; C locale // C locale
mov bh,'A' mov bh,'A'
mov bl,'Z' 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 align 4
lupe: lupe:
mov ah,[esi] ; ah = *first mov ah,[esi] // ah = *first
add esi,1 ; first++ add esi,1 // first++
mov al,[edi] ; al = *last mov al,[edi] // al = *last
add edi,1 ; 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 je short dolupe
cmp ah,bh ; ah < 'A' ?? cmp ah,bh // ah < 'A' ??
jb short skip1 jb short skip1
cmp ah,bl ; ah > 'Z' ?? cmp ah,bl // ah > 'Z' ??
ja short skip1 ja short skip1
add ah,dh ; make lower case add ah,dh // make lower case
skip1: skip1:
cmp al,bh ; al < 'A' ?? cmp al,bh // al < 'A' ??
jb short skip2 jb short skip2
cmp al,bl ; al > 'Z' ?? cmp al,bl // al > 'Z' ??
ja short skip2 ja short skip2
add al,dh ; make lower case add al,dh // make lower case
skip2: skip2:
cmp ah,al ; *first == *last ?? cmp ah,al // *first == *last ??
jne short differ ; nope, found mismatched chars jne short differ // nope, found mismatched chars
dolupe: dolupe:
sub ecx,1 sub ecx,1
jnz short lupe jnz short lupe
jmp short toend ; cx = 0, return 0 jmp short toend // cx = 0, return 0
differ: differ:
mov ecx,-1 ; assume last is bigger mov ecx,-1 // assume last is bigger
; *** can't use "or ecx,-1" due to flags *** // *** can't use "or ecx,-1" due to flags ***
jb short toend ; last is, in fact, bigger (return -1) jb short toend // last is, in fact, bigger (return -1)
neg ecx ; first is bigger (return 1) neg ecx // first is bigger (return 1)
toend: 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 end

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,3 +1,5 @@
#include <asm.inc>
#if 0
page ,132 page ,132
title strspn - search for init substring of chars from control str title strspn - search for init substring of chars from control str
;*** ;***
@ -165,54 +167,58 @@ page
;Exceptions: ;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 #define SSTRSPN 1
_STRSPN_ equ <strspn> #define _STRSPN_ _strspn
endif ; SSTRCSPN #endif // SSTRCSPN
% public _STRSPN_ public _STRSPN_
CODESEG .code
_STRSPN_ proc \ .PROC _STRSPN_
uses esi, \ // Prolog. Original sources used ML's extended PROC feature to autogenerate this.
string:ptr byte, \ push ebp
control:ptr byte 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 xor eax,eax
push eax ; 32 push eax // 32
push eax push eax
push eax push eax
push eax ; 128 push eax // 128
push eax push eax
push eax 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 align 4 // @WordSize
lab listnext ; init char bit map listnext: // init char bit map
mov al,[edx] mov al,[edx]
or al,al or al,al
jz short listdone jz short listdone
@ -220,18 +226,22 @@ lab listnext ; init char bit map
bts map,eax bts map,eax
jmp short listnext 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 align 4 // @WordSize
lab dstnext dstnext:
_ifnd SSTRPBRK, <add ecx,1> #ifndef SSTRPBRK
add ecx,1
#endif
mov al,[esi] mov al,[esi]
or al,al or al,al
@ -239,24 +249,30 @@ _ifnd SSTRPBRK, <add ecx,1>
add esi,1 add esi,1
bt map, eax bt map, eax
ifdef SSTRSPN #ifdef SSTRSPN
jc short dstnext ; strspn: found char, continue jc short dstnext // strspn: found char, continue
elseifdef SSTRCSPN #elif defined SSTRCSPN
jnc short dstnext ; strcspn: did not find char, continue jnc short dstnext // strcspn: did not find char, continue
elseifdef SSTRPBRK #elif defined SSTRPBRK
jnc short dstnext ; strpbrk: did not find char, continue jnc short dstnext // strpbrk: did not find char, continue
lea eax,[esi - 1] ; found char, return address of it lea eax,[esi - 1] // found char, return address of it
endif ; SSTRSPN #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 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 end