format pe gui 4.0
entry start

include '%fasminc%\win32ax.inc'

; -------------------------------------------------
;
; assembler equivalent of visual basic function:
; mid() left() right()
;
; custom destination buffer versions:
; _lmidx() _lleftx() _lrightx()
;
; fixed destination buffer versions:
; _lmid() _lleft() _lright()
;
; also contains this fast functions:
; _strlen_fog()  - Agner Fog
; _strlen_kun()  - kunt0r
; _memcpy_fast() - bart (tuned by me)
;
; notes:
; - for testing you must uncomment any line below
; - read comments for function you want to test/use
;
; coded by Vasilev Vjacheslav
;
; -------------------------------------------------

section '.rdata' data readable writeable

  szCaption	db "Testing",0
  szRight	db "right_str",0
  szNothing	db "<nothing>",0

section '.data' readable writeable

  szBuffer	rb 512

section '.text' code readable writable executable

  ; -------------------------------------------------
  ;
  ; entry-point
  ;
  ; -------------------------------------------------

  start:
	stdcall _strlen_fog,szNothing
	inc	eax
	stdcall _memcpy_fast,szBuffer,szNothing,eax

	;
	; uncomment line and test
	;
	;stdcall _lrightx,szRight,szBuffer,3
	;stdcall _lleftx,szRight,szBuffer,3
	;stdcall _lmidx,szRight,szBuffer,0,0
	;invoke  MessageBox,NULL,szBuffer,szCaption,MB_OK+MB_ICONINFORMATION
	;
	;stdcall _lright,szRight,3
	;stdcall _lleft,szRight,3
	;stdcall _lmid,szRight,2,2
	;invoke  MessageBox,NULL,szRight,szCaption,MB_OK+MB_ICONINFORMATION

	invoke	ExitProcess,NULL

  ; -------------------------------------------------
  ;
  ; return hcount chars from right of hsrc string and
  ; store result into hdst string
  ;
  ; -------------------------------------------------

  proc	_lrightx uses ebx esi edi, hsrc,hdst,hcount
	mov	esi,[hsrc]
	stdcall _strlen_fog,esi
	cmp	[hcount],eax
	jae	.out
	mov	ecx,[hcount]
	mov	ebx,ecx
	mov	edi,[hdst]
  @@:
	lea	edx,[eax+esi]
	sub	edx,ebx
	mov	dl,[edx]
	mov	[edi],dl
	dec	ebx
	inc	edi
	dec	ecx
	jnz	@B
	xor	al,al
	mov	[edi],al
  .out:
	ret
  endp

  proc	_lright uses ebx esi edi, hsrc,hcount
	mov	esi,[hsrc]
	stdcall _strlen_fog,esi
	cmp	[hcount],eax
	jae	.out
	mov	ecx,[hcount]
	mov	ebx,ecx
	mov	edi,esi
  @@:
	lea	edx,[eax+esi]
	sub	edx,ebx
	mov	dl,[edx]
	mov	[edi],dl
	dec	ebx
	inc	edi
	dec	ecx
	jnz	@B
	xor	al,al
	mov	[edi],al
  .out:
	ret
  endp

  ; -------------------------------------------------
  ;
  ; return hcount chars from left of hsrc string and
  ; store result into hdst string
  ;
  ; -------------------------------------------------

  proc	_lleftx uses ebx esi edi, hsrc,hdst,hcount
	mov	esi,[hsrc]
	stdcall _strlen_fog,esi
	cmp	[hcount],eax
	jae	.out
	mov	ecx,[hcount]
	mov	ebx,ecx
	mov	edi,[hdst]
  @@:
	mov	al,[esi+ecx-1]
	mov	[edi+ecx-1],al
	dec	ecx
	jnz	@B
	xor	al,al
	mov	[edi+ebx],al
  .out:
	ret
  endp

  proc	_lleft uses ebx esi edi, hsrc,hcount
	mov	edi,[hsrc]
	stdcall _strlen_fog,edi
	cmp	[hcount],eax
	jae	.out
	add	edi,[hcount]
	xor	al,al
	mov	[edi],al
  .out:
	ret
  endp

  ; -------------------------------------------------
  ;
  ; copy hcount chars from hstart position of hsrc
  ; string into hdst string
  ;
  ; hstart == 0 && hcount == 0 - copy all chars from
  ;                              hsrc into hdst
  ; hstart == 0 && hcount != 0 - copy hcount chars
  ;                              from start of hsrc
  ;                              into hdst
  ; hstart != 0 && hcount == 0 - copy all chars from
  ;                              hstart position of
  ;                              hsrc into hdst
  ; hstart != 0 && hcount != 0 - copy hcount chars
  ;                              from hstart position
  ;                              of hsrc into hdst
  ;
  ; -------------------------------------------------

  proc	_lmidx uses ebx esi edi, hsrc,hdst,hstart,hcount
	mov	esi,[hsrc]
	mov	edi,[hdst]
	xor	ebx,ebx
	stdcall _strlen_fog,esi
	cmp	[hstart],ebx
	jnz	@F
	cmp	[hcount],ebx
	jnz	@F
	inc	eax
	stdcall _memcpy_fast,edi,esi,eax
	jmp	.out
  @@:
	cmp	[hstart],ebx
	jnz	.a
	cmp	[hcount],eax
	jae	.a
	mov	ecx,[hcount]
  @@:
	mov	al,[esi]
	mov	[edi],al
	inc	esi
	inc	edi
	dec	ecx
	jnz	@B
	jmp	.out_xor
  .a:
	cmp	[hcount],ebx
	jnz	.b
	cmp	[hstart],eax
	jae	.b
	sub	eax,[hstart]
	add	esi,[hstart]
  @@:
	mov	cl,[esi]
	mov	[edi],cl
	inc	esi
	inc	edi
	dec	eax
	jnz	@B
	jmp	.out_xor
  .b:
	cmp	[hstart],eax
	jae	.out
	cmp	[hcount],eax
	jae	.out
	mov	ecx,eax
	sub	ecx,[hstart]
	cmp	[hcount],ecx
	ja	.out
	mov	eax,[hcount]
	add	esi,[hstart]
  @@:
	mov	cl,[esi]
	mov	[edi],cl
	inc	esi
	inc	edi
	dec	eax
	jnz	@B
  .out_xor:
	xor	al,al
	mov	[edi],al
  .out:
	ret
  endp

  proc	_lmid uses ebx esi edi, hsrc,hstart,hcount
	mov	esi,[hsrc]
	mov	edi,esi
	xor	ebx,ebx
	stdcall _strlen_fog,esi
	cmp	[hstart],ebx
	jnz	@F
	cmp	[hcount],ebx
	jz	.out
  @@:
	cmp	[hstart],ebx
	jnz	.a
	cmp	[hcount],eax
	jae	.a
	add	edi,[hcount]
	jmp	.out_xor
  .a:
	cmp	[hcount],ebx
	jnz	.b
	cmp	[hstart],eax
	jae	.b
	sub	eax,[hstart]
	add	esi,[hstart]
  @@:
	mov	cl,[esi]
	mov	[edi],cl
	inc	esi
	inc	edi
	dec	eax
	jnz	@B
	jmp	.out_xor
  .b:
	cmp	[hstart],eax
	jae	.out
	cmp	[hcount],eax
	jae	.out
	mov	ecx,eax
	sub	ecx,[hstart]
	cmp	[hcount],ecx
	ja	.out
	mov	eax,[hcount]
	add	esi,[hstart]
  @@:
	mov	cl,[esi]
	mov	[edi],cl
	inc	esi
	inc	edi
	dec	eax
	jnz	@B
  .out_xor:
	xor	al,al
	mov	[edi],al
  .out:
	ret
  endp

  ; -------------------------------------------------
  ;
  ; return length of hstr string in eax (Agner Fog)
  ; pretty fast algorithm
  ;
  ; -------------------------------------------------

  proc	_strlen_fog uses ebx esi edi, hstr
	mov	eax,[hstr]
	lea	edx,[eax+3]
  @@:
	mov	ebx,[eax]
	add	eax,4
	lea	ecx,[ebx-01010101h]
	not	ebx
	and	ecx,ebx
	and	ecx,80808080h
	jz	@B
	test	ecx,00008080h
	jnz	@F
	shr	ecx,16
	add	eax,2
  @@:
	shl	cl,1
	sbb	eax,edx
	ret
  endp

  ; -------------------------------------------------
  ;
  ; return length of hstr string in eax (kunt0r)
  ; another pretty fast algorithm
  ;
  ; -------------------------------------------------

  proc	_strlen_kun uses ebx esi edi, hstr
	mov	eax,[hstr]
  .d1:
	mov	edx,[eax]
	mov	ecx,edx
	add	eax,4
	sub	edx,16843009
	and	edx,2155905152
	jz	.d1
	not	ecx
	and	edx, ecx
	jz	.d1
	test	dl,dl
	jnz	.d2
	test	dh,dh
	jnz	.d3
	test	edx,16711680
	jnz	.d4
	jmp	.d5
  .d2:
	dec eax
  .d3:
	dec eax
  .d4:
	dec eax
  .d5:
	dec	eax
	sub	eax,[hstr]
	ret
  endp

  ; -------------------------------------------------
  ;
  ; fast memory copying algorithm (tuned asmpack ver)
  ; qword -> dword -> byte
  ;
  ; -------------------------------------------------

  proc	_memcpy_fast uses esi edi, hdst,hsrc,hsize
	mov	eax,[hsize]
	mov	edi,[hdst]
	mov	esi,[hsrc]
	mov	ecx,eax
	shr	ecx,3
	jz	.next1
  @@:
	movq	mm0,qword [esi]
	movq	qword [edi],mm0
	add	esi,8
	add	edi,8
	dec	ecx
	jnz	@B
  .next1:
	mov	ecx,eax
	and	ecx,7
	shr	ecx,2
	jz	.next2
  @@:
	mov	edx,[esi]
	mov	[edi],edx
	add	esi,4
	add	edi,4
	dec	ecx
	jnz	@B
  .next2:
	and	eax,3
	jz	.out
  @@:
	mov	dl,byte [esi]
	mov	byte [edi],dl
	inc	esi
	inc	edi
	dec	eax
	jnz	@B
  .out:
	sub	edi,[hsize]
	mov	eax,edi
	ret
  endp

section '.idata' import data readable writeable

  library	kernel32,'kernel32.dll',\
		user32,'user32.dll',\
		gdi32,'gdi32.dll',\
		comdlg32,'comdlg32.dll',\
		advapi32,'advapi32.dll'

  include	'%fasminc%\api\kernel32.inc'
  include	'%fasminc%\api\user32.inc'
  include	'%fasminc%\api\gdi32.inc'
  include	'%fasminc%\api\comdlg32.inc'
  include	'%fasminc%\api\advapi32.inc'

; eof