forked from KolibriOS/kolibrios
dll.obj: Added error handling with detailed inform user which error occurred through @notyfy
git-svn-id: svn://kolibrios.org@9669 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
254d30c075
commit
803d2a454e
@ -2,26 +2,28 @@
|
|||||||
---
|
---
|
||||||
History
|
History
|
||||||
|
|
||||||
0.1 + First realised, kernel load dll.obj at runtime as starting point berfore app startup
|
0.1 + First realised, kernel load dll.obj at runtime as starting point berfore app startup
|
||||||
dll.obj process app import table, but not depended librarys, after that app gots control in his starting point
|
dll.obj process app import table, but not depended librarys, after that app gots control in his starting point
|
||||||
|
|
||||||
|
0.2 + Introduced new KX header as extension for current format (see decription below)
|
||||||
|
+ Add KX header processing
|
||||||
|
+ Improved import table test logic, no reason to kill app for import absence - skip import processing (tnx ProMiNick)
|
||||||
|
+ Added ReadMe.txt (this doc)
|
||||||
|
|
||||||
|
0.2.1 + Branch from dll.inc, now this file is not external. Improved error handling. Now dll.Load return 0 in success only
|
||||||
|
Added corrsponding error codes if one of library or entry not found
|
||||||
|
+ Added error handling with detailed inform user which error occurred through @notyfy.
|
||||||
|
Now application is not crashed if bad format, can't load library or no found entry
|
||||||
|
|
||||||
0.2 + Introduced new KX header as extension for current format (see decription below)
|
|
||||||
+ Add KX header processing
|
|
||||||
+ Improved import table test logic, no reason to kill app for import absence - skip import processing (tnx ProMiNick)
|
|
||||||
|
|
||||||
---
|
|
||||||
Purpose
|
Purpose
|
||||||
|
|
||||||
Automatically libraries loads and linking imports.
|
Automatically libraries loads and linking imports.
|
||||||
|
|
||||||
---
|
---
|
||||||
Limitations
|
TODO
|
||||||
|
|
||||||
|
1) The library format needs to be improved, see intorduction of KX header extension bellow
|
||||||
1) No error messages are issued if the library or symbol in the library is not found or somthing went wrong
|
|
||||||
|
|
||||||
|
|
||||||
2) There is no autoloading of dependent libraries (the library format needs to be improved, see intorduction of KX header extension bellow)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
How to use
|
How to use
|
||||||
@ -30,7 +32,7 @@ How to use
|
|||||||
1) In the version field of a header, (after MENUET0x) you must specify the number 2
|
1) In the version field of a header, (after MENUET0x) you must specify the number 2
|
||||||
2) After existing header add KX header extension as descriprion bellow
|
2) After existing header add KX header extension as descriprion bellow
|
||||||
3) Specify imported libraries. Currentry format of import table same as in case of using dll.Load
|
3) Specify imported libraries. Currentry format of import table same as in case of using dll.Load
|
||||||
4) Add code, without connecting dll.inc and, accordingly, without calling dll.Load. The heap initialization function (f. 68.11) does not need to be called either.
|
4) Add code, without connecting dll.inc and, accordingly, without calling dll.Load. The heap initialization function (f. 68.11) does not need to be called either.
|
||||||
|
|
||||||
5) Compile the app and run. If everything is done correctly, then on startup the debug board will display the message "App header version 2"
|
5) Compile the app and run. If everything is done correctly, then on startup the debug board will display the message "App header version 2"
|
||||||
If the DLL.OBJ library is missing, a message will be displayed, incl. via @NOTIFY. If you get a page error make sure you have completed steps 2 and 3
|
If the DLL.OBJ library is missing, a message will be displayed, incl. via @NOTIFY. If you get a page error make sure you have completed steps 2 and 3
|
||||||
@ -55,7 +57,7 @@ Fields between offset 8 and at end of KX header may be added later.
|
|||||||
|
|
||||||
0 2 SigMagic Module identifier with the value "KX"
|
0 2 SigMagic Module identifier with the value "KX"
|
||||||
|
|
||||||
2 1 SigRevision This field should be 0.
|
2 1 SigRevision This field should be 0.
|
||||||
In the future, it can take on the revision value
|
In the future, it can take on the revision value
|
||||||
(but can't take values higher than 64)
|
(but can't take values higher than 64)
|
||||||
|
|
||||||
|
@ -1,25 +1,35 @@
|
|||||||
;
|
;
|
||||||
; KolibriOS Dll load support
|
; Support for Dll auto load & linking
|
||||||
;
|
;
|
||||||
; (C) 2020-2021 Coldy
|
; (C) 2020-2022 Coldy
|
||||||
; Thank's you for use this code and software based on it!
|
; Thank's you for use this code and software based on it!
|
||||||
; I will glad if it's will be helpful.
|
; I will glad if it's will be helpful.
|
||||||
;
|
;
|
||||||
; Distributed under terms of GPL
|
; Distributed under terms of GPL
|
||||||
;
|
;
|
||||||
|
|
||||||
format MS COFF
|
format MS COFF
|
||||||
public @EXPORT as 'EXPORTS'
|
public @EXPORT as 'EXPORTS'
|
||||||
|
|
||||||
include '../../../proc32.inc'
|
|
||||||
include '../../../macros.inc'
|
|
||||||
|
|
||||||
section '.flat' code readable align 16
|
section '.flat' code readable align 16
|
||||||
|
|
||||||
|
include 'external.inc'
|
||||||
|
include 'dll.inc'
|
||||||
|
|
||||||
|
; This need for @notyfy pre/postformat
|
||||||
|
STR_BUILD_OFFSET = 1
|
||||||
|
STR_BUILD_EXTRA = 5
|
||||||
|
|
||||||
|
mem_alloc = mem.Alloc
|
||||||
|
|
||||||
|
include 'strhlp.inc'
|
||||||
|
|
||||||
app_version equ word[8]
|
app_version equ word[8]
|
||||||
i_table_min_size = 1
|
i_table_min_size = 1
|
||||||
|
|
||||||
sizeof.kx_header = 8
|
sizeof.kx_header = 8
|
||||||
|
|
||||||
|
ERROR_BAD_IMAGE = 0x010
|
||||||
|
|
||||||
APP_STARTUP_THUNK:
|
APP_STARTUP_THUNK:
|
||||||
; First make shure that app
|
; First make shure that app
|
||||||
; have header version 2.0 or more
|
; have header version 2.0 or more
|
||||||
@ -41,10 +51,10 @@ APP_STARTUP_THUNK:
|
|||||||
mov esi,0x24
|
mov esi,0x24
|
||||||
lodsw
|
lodsw
|
||||||
cmp ax, 'KX'
|
cmp ax, 'KX'
|
||||||
jne @f ; Not KX
|
jne .image_error ; Not KX
|
||||||
lodsw
|
lodsw
|
||||||
cmp ax, 0
|
cmp ax, 0
|
||||||
jne @f ; Bad magic
|
jne .image_error ; Bad magic
|
||||||
lodsw
|
lodsw
|
||||||
|
|
||||||
bt ax, 6 ; Have import?
|
bt ax, 6 ; Have import?
|
||||||
@ -54,22 +64,22 @@ APP_STARTUP_THUNK:
|
|||||||
; Test import table (use legacy style)
|
; Test import table (use legacy style)
|
||||||
mov eax, [sizeof.kx_header + 0x24] ; i_table_ptr
|
mov eax, [sizeof.kx_header + 0x24] ; i_table_ptr
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .app_start ; i_table_ptr = 0 ?
|
jz .image_error;.import_error;.app_start ; i_table_ptr = 0 ? => Bad image
|
||||||
;js .error
|
;js .error
|
||||||
mov esi, [0x10]
|
mov esi, [0x10]
|
||||||
cmp esi, eax
|
cmp esi, eax
|
||||||
jbe @f ; i_table_ptr >= img_size ?
|
jbe .image_error;@f ; i_table_ptr >= img_size ?
|
||||||
mov ebx, eax
|
mov ebx, eax
|
||||||
add ebx, i_table_min_size
|
add ebx, i_table_min_size
|
||||||
cmp esi, ebx
|
cmp esi, ebx
|
||||||
jb @f ; i_table_ptr + i_table_min_size > img_size ?
|
jb .image_error;@f ; i_table_ptr + i_table_min_size > img_size ?
|
||||||
|
|
||||||
; Link app/dependent libs import tables with libs export table
|
; Link app/dependent libs import tables with libs export table
|
||||||
; TODO: need revision of the exists lib format and dll.Load (for libs import binds)
|
; TODO: need revision of the exists lib format and dll.Load (for libs import binds)
|
||||||
|
|
||||||
stdcall dll.Load,eax
|
stdcall dll.Load,eax
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .import_error
|
jnz .link_error;.import_error
|
||||||
.app_start:
|
.app_start:
|
||||||
; Start of app code
|
; Start of app code
|
||||||
mov eax, [0x0C]
|
mov eax, [0x0C]
|
||||||
@ -78,9 +88,11 @@ APP_STARTUP_THUNK:
|
|||||||
@@:
|
@@:
|
||||||
mov eax, -1
|
mov eax, -1
|
||||||
int 0x40
|
int 0x40
|
||||||
.import_error:
|
.image_error:
|
||||||
; Run @NOTIFY and tell user then error occured
|
mov eax, ERROR_BAD_IMAGE
|
||||||
; BOARD will contaits details
|
.link_error:
|
||||||
|
; Run @NOTIFY and tell user then error occurred
|
||||||
|
call show_error
|
||||||
jmp @b
|
jmp @b
|
||||||
.denied:
|
.denied:
|
||||||
; Kolibri has no ability kill app if this enter from no from main thread
|
; Kolibri has no ability kill app if this enter from no from main thread
|
||||||
@ -90,13 +102,98 @@ APP_STARTUP_THUNK:
|
|||||||
; } APP_STARTUP_THUNK
|
; } APP_STARTUP_THUNK
|
||||||
|
|
||||||
|
|
||||||
; WARNING! This code must be after app initialization thunk!
|
; eax = error code (see ERROR_xxx above in this and dll.inc files)
|
||||||
include '../../../dll.inc'
|
|
||||||
|
show_error:
|
||||||
|
|
||||||
|
; Store error code
|
||||||
|
mov edx, eax
|
||||||
|
|
||||||
|
; Get app name
|
||||||
|
sub esp,1024
|
||||||
|
mov eax, 9
|
||||||
|
mov ebx, esp
|
||||||
|
mov ecx, -1
|
||||||
|
int 0x40
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
mov esi, esp
|
||||||
|
add esi, 10 ; esi = app name
|
||||||
|
|
||||||
|
|
||||||
|
cmp edx, ERROR_ENTRY_NOT_FOUND
|
||||||
|
je .entry_not_found
|
||||||
|
|
||||||
|
; Init heap not needed
|
||||||
|
; (kernel already initialized heap implicitly when load dll.obj)
|
||||||
|
|
||||||
|
cmp edx, ERROR_LIBRARY_NOT_LOAD
|
||||||
|
je .library_not_loaded
|
||||||
|
|
||||||
|
ccall str_build, szWrongFormat, esi, szBanner
|
||||||
|
jmp @f
|
||||||
|
|
||||||
|
.library_not_loaded:
|
||||||
|
ccall str_build, szLibraryNotLoaded, esi, szBanner, s_libdir.fname
|
||||||
|
jmp @f
|
||||||
|
|
||||||
|
.entry_not_found:
|
||||||
|
mov eax, [szEntryName]
|
||||||
|
ccall str_build, szEntryNotFound, esi, szBanner, eax, s_libdir.fname
|
||||||
|
|
||||||
|
@@:
|
||||||
|
add esp, 1024
|
||||||
|
|
||||||
|
mov byte[eax],'"'
|
||||||
|
mov byte[edi],'"'
|
||||||
|
mov dword[edi+1],"-tdE" ; with title, disable autoclose, error icon
|
||||||
|
|
||||||
|
mov esi, eax
|
||||||
|
|
||||||
|
; Display error
|
||||||
|
mov [pNotify.params], eax
|
||||||
|
mov ebx, pNotify
|
||||||
|
mov eax, 70
|
||||||
|
int 0x40
|
||||||
|
|
||||||
|
stdcall mem.Free, esi
|
||||||
|
|
||||||
|
.exit:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
;dd 0xdeadbeef
|
;dd 0xdeadbeef
|
||||||
dd APP_STARTUP_THUNK
|
dd APP_STARTUP_THUNK
|
||||||
@EXPORT:
|
@EXPORT:
|
||||||
export \
|
export \
|
||||||
dll.Load, 'dll_load', \
|
dll.Load, 'dll_load', \
|
||||||
dll.Link, 'dll_link', \
|
dll.Link, 'dll_link', \
|
||||||
dll.GetProcAddress, 'dll_sym' ;
|
dll.GetProcAddress, 'dll_sym'
|
||||||
|
|
||||||
|
|
||||||
|
pNotify:
|
||||||
|
dd 7, 0
|
||||||
|
.params dd 0
|
||||||
|
dd 0, 0
|
||||||
|
db "/sys/@notify", 0
|
||||||
|
|
||||||
|
; { Strings
|
||||||
|
if defined LANG_RUS
|
||||||
|
include 'strings.rus'
|
||||||
|
;elseif defined LANG_xxx
|
||||||
|
; TODO: Add another supported languges here
|
||||||
|
; - Copy 'elseif defined LANG_xxx', change xxx here and below to the
|
||||||
|
; corresponded constat of you languge
|
||||||
|
; - Create strings.xxx in the root of this project and do translate,
|
||||||
|
; follow the format message below.
|
||||||
|
; - add include 'strings.xxx'
|
||||||
|
else ; Default languge (English)
|
||||||
|
szBanner db "Error!\n",0
|
||||||
|
szWrongFormat db "$ - $Application has wrong format!",0
|
||||||
|
szLibraryNotLoaded db "$ - $Can't load library $", 0
|
||||||
|
szEntryNotFound db "$ - $Entry $\nin library $\nnot found!",0
|
||||||
|
|
||||||
|
end if
|
||||||
|
; } Strings
|
192
programs/develop/libraries/dll/dll.inc
Normal file
192
programs/develop/libraries/dll/dll.inc
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
;
|
||||||
|
; (C) KolibriOS team (original dll.inc)
|
||||||
|
; (C) 2022, Edited by Coldy
|
||||||
|
;
|
||||||
|
; This module based on original dll.inc.
|
||||||
|
;
|
||||||
|
; - Improved error handling. Now dll.Load return 0 is success guarantie
|
||||||
|
; Also added corrsponding error codes if one of library or entry not found
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
ERROR_LIBRARY_NOT_LOAD = 0x100
|
||||||
|
ERROR_ENTRY_NOT_FOUND = 0x101
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; load one or more DLL file in COFF format and try to import functions by our list
|
||||||
|
; if first function in import list begins with 'lib_', call it as DLL initialization
|
||||||
|
; return eax = 1 as fail, if anyone of .obj file not found in /sys/lib
|
||||||
|
; return 0 if all fine or error code LIBRARY_NOT_LOAD or ENTRY_NOT_FOUND
|
||||||
|
; dirties all registers! eax, ebx, ecx, edx, esi, edi
|
||||||
|
proc dll.Load, import_table:dword
|
||||||
|
mov esi, [import_table]
|
||||||
|
.next_lib:
|
||||||
|
mov edx, [esi]
|
||||||
|
or edx, edx
|
||||||
|
jz .exit
|
||||||
|
push esi
|
||||||
|
mov esi, [esi + 4]
|
||||||
|
mov edi, s_libdir.fname
|
||||||
|
@@:
|
||||||
|
lodsb
|
||||||
|
stosb
|
||||||
|
or al, al
|
||||||
|
jnz @b
|
||||||
|
mcall 68, 19, s_libdir
|
||||||
|
or eax, eax
|
||||||
|
jz .fail_load
|
||||||
|
push eax
|
||||||
|
stdcall dll.Link, eax, edx
|
||||||
|
test eax, eax
|
||||||
|
jnz .fail_link
|
||||||
|
;push eax
|
||||||
|
mov eax, [esp]
|
||||||
|
mov eax, [eax]
|
||||||
|
cmp dword[eax], 'lib_'
|
||||||
|
pop eax
|
||||||
|
jnz @f
|
||||||
|
stdcall dll.Init, [eax + 4]
|
||||||
|
@@:
|
||||||
|
pop esi
|
||||||
|
add esi, 8
|
||||||
|
jmp .next_lib
|
||||||
|
.exit:
|
||||||
|
xor eax, eax
|
||||||
|
ret
|
||||||
|
.fail_load:
|
||||||
|
add esp, 4
|
||||||
|
;xor eax, eax
|
||||||
|
;inc eax
|
||||||
|
mov eax, ERROR_LIBRARY_NOT_LOAD
|
||||||
|
ret
|
||||||
|
.fail_link:
|
||||||
|
add esp, 4
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; scans dll export table for a functions we want to import
|
||||||
|
; break scan on first unresolved import
|
||||||
|
; return value: 0 - success or ENTRY_NOT_FOUND
|
||||||
|
proc dll.Link, exp:dword, imp:dword
|
||||||
|
;push eax
|
||||||
|
mov esi, [imp]
|
||||||
|
; Import table alreary checked in APP_STARTUP_THUNK
|
||||||
|
;test esi, esi
|
||||||
|
;jz .fail1;.done
|
||||||
|
.next:
|
||||||
|
lodsd
|
||||||
|
test eax, eax
|
||||||
|
jz .done
|
||||||
|
mov ebx, eax
|
||||||
|
stdcall dll.GetProcAddress, [exp], eax
|
||||||
|
or eax, eax
|
||||||
|
jz .fail ;.done
|
||||||
|
mov [esi - 4], eax
|
||||||
|
jmp .next
|
||||||
|
; @@:
|
||||||
|
;mov dword[esp], 0
|
||||||
|
;.fail1:
|
||||||
|
; No imports
|
||||||
|
;mov eax, BAD_IMAGE
|
||||||
|
;jmp .done
|
||||||
|
.fail:
|
||||||
|
mov [szEntryName],ebx
|
||||||
|
mov eax, ERROR_ENTRY_NOT_FOUND
|
||||||
|
.done:
|
||||||
|
;pop eax
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; calls lib_init with predefined parameters
|
||||||
|
; no return value
|
||||||
|
proc dll.Init, dllentry:dword
|
||||||
|
pushad
|
||||||
|
mov eax, mem.Alloc
|
||||||
|
mov ebx, mem.Free
|
||||||
|
mov ecx, mem.ReAlloc
|
||||||
|
mov edx, dll.Load
|
||||||
|
stdcall [dllentry]
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; scans export table for a sz_name function
|
||||||
|
; returns in eax function address or 0 if not found
|
||||||
|
proc dll.GetProcAddress, exp:dword, sz_name:dword
|
||||||
|
mov edx, [exp]
|
||||||
|
xor eax, eax
|
||||||
|
.next:
|
||||||
|
or edx, edx
|
||||||
|
jz .end
|
||||||
|
cmp dword[edx], 0
|
||||||
|
jz .end
|
||||||
|
stdcall strcmp, [edx], [sz_name]
|
||||||
|
test eax, eax
|
||||||
|
jz .ok
|
||||||
|
add edx, 8
|
||||||
|
jmp .next
|
||||||
|
.ok:
|
||||||
|
mov eax, [edx + 4]
|
||||||
|
.end:
|
||||||
|
cmp eax, -1
|
||||||
|
jnz @f
|
||||||
|
xor eax, eax
|
||||||
|
@@:
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; compares strings
|
||||||
|
; returns eax = 0 if equal, -1 otherwise
|
||||||
|
proc strcmp, str1:dword, str2:dword
|
||||||
|
push esi edi
|
||||||
|
mov esi, [str1]
|
||||||
|
mov edi, [str2]
|
||||||
|
xor eax, eax
|
||||||
|
@@:
|
||||||
|
lodsb
|
||||||
|
scasb
|
||||||
|
jne .fail
|
||||||
|
or al, al
|
||||||
|
jnz @b
|
||||||
|
jmp .ok
|
||||||
|
.fail:
|
||||||
|
or eax, -1
|
||||||
|
.ok:
|
||||||
|
pop edi esi
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
s_libdir:
|
||||||
|
db '/sys/lib/'
|
||||||
|
.fname rb 32
|
||||||
|
|
||||||
|
szEntryName dd 0
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
proc mem.Alloc, size
|
||||||
|
push ebx ecx
|
||||||
|
mov ecx, [size]
|
||||||
|
mcall 68, 12
|
||||||
|
pop ecx ebx
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
proc mem.ReAlloc, mptr, size
|
||||||
|
push ebx ecx edx
|
||||||
|
mov ecx, [size]
|
||||||
|
mov edx, [mptr]
|
||||||
|
mcall 68, 20
|
||||||
|
pop edx ecx ebx
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
proc mem.Free, mptr
|
||||||
|
push ebx ecx
|
||||||
|
mov ecx,[mptr]
|
||||||
|
mcall 68, 13
|
||||||
|
pop ecx ebx
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
;-----------------------------------------------------------------------------
|
7
programs/develop/libraries/dll/external.inc
Normal file
7
programs/develop/libraries/dll/external.inc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
;
|
||||||
|
; This file is used for external includes
|
||||||
|
; If server and locale relative paths is different
|
||||||
|
; then need a corresponding copy on each side
|
||||||
|
|
||||||
|
include '../../../proc32.inc'
|
||||||
|
include '../../../macros.inc'
|
303
programs/develop/libraries/dll/strhlp.inc
Normal file
303
programs/develop/libraries/dll/strhlp.inc
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
;
|
||||||
|
; String helpers
|
||||||
|
;
|
||||||
|
; (C) KolibriOS team (parts from another project)
|
||||||
|
; (C) 2022 Coldy (str_buld function)
|
||||||
|
; Thank's you for use this code and software based on it!
|
||||||
|
; I will glad if it's will be helpful.
|
||||||
|
;
|
||||||
|
; Distributed under terms of GPL
|
||||||
|
;
|
||||||
|
|
||||||
|
;****************************************
|
||||||
|
;* input: esi = pointer to string *
|
||||||
|
;* output: ecx = length of the string *
|
||||||
|
;****************************************
|
||||||
|
strlen:
|
||||||
|
push eax esi
|
||||||
|
xor ecx, ecx
|
||||||
|
@@:
|
||||||
|
lodsb
|
||||||
|
or al, al
|
||||||
|
jz @f
|
||||||
|
inc ecx
|
||||||
|
jmp @b
|
||||||
|
@@:
|
||||||
|
pop esi eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* input: esi = pointer to the src string *
|
||||||
|
;* edi = pointer to the dest string *
|
||||||
|
;* ecx = number of bytes to copy *
|
||||||
|
;*************************************************
|
||||||
|
strncpy:
|
||||||
|
push eax ecx esi edi
|
||||||
|
@@:
|
||||||
|
lodsb
|
||||||
|
stosb
|
||||||
|
or al, al
|
||||||
|
jz @f
|
||||||
|
dec ecx
|
||||||
|
jz @f
|
||||||
|
jmp @b
|
||||||
|
@@:
|
||||||
|
pop edi esi ecx eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
if 0 ; { Not used
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* input: esi = pointer to the src string *
|
||||||
|
;* edi = pointer to the dest string *
|
||||||
|
;*************************************************
|
||||||
|
strcpy:
|
||||||
|
push esi edi
|
||||||
|
; ecx = ???
|
||||||
|
; ZF = 0
|
||||||
|
rep movsb
|
||||||
|
pop edi esi
|
||||||
|
ret
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* input: esi = pointer to the src string *
|
||||||
|
;* edi = pointer to the dest string *
|
||||||
|
;* ecx = number of bytes to copy *
|
||||||
|
;*************************************************
|
||||||
|
strncat:
|
||||||
|
push edi
|
||||||
|
push ecx esi
|
||||||
|
mov esi, edi
|
||||||
|
call strlen
|
||||||
|
add edi, ecx
|
||||||
|
pop esi ecx
|
||||||
|
call strncpy
|
||||||
|
pop edi
|
||||||
|
ret
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* (c) Coldy 2022 *
|
||||||
|
;* input: edi = pointer to the dest string *
|
||||||
|
;* ecx = number of bytes to zero *
|
||||||
|
;*************************************************
|
||||||
|
;memnz:
|
||||||
|
; push eax ecx edi
|
||||||
|
; xor eax, eax
|
||||||
|
; rep stosb
|
||||||
|
; pop edi ecx eax
|
||||||
|
; ret
|
||||||
|
|
||||||
|
end if ; }
|
||||||
|
|
||||||
|
;
|
||||||
|
; str_build
|
||||||
|
;
|
||||||
|
; Purose: Build output string by template. Allocate necessary output
|
||||||
|
; buffer, copy parts from template and insert strings instead
|
||||||
|
; of $ wildcard.
|
||||||
|
;
|
||||||
|
; SPECIAL CASE:
|
||||||
|
; For use dollar sing ($) in text, just mark this plase(s) in
|
||||||
|
; template and provide pointer(s) on string with this sign in args)
|
||||||
|
;
|
||||||
|
; PRECAUTION:
|
||||||
|
; 1. Not safe, caller must provide args count >= $ wildcard count
|
||||||
|
; 2. If used dynamic memory allocator then caller must free output
|
||||||
|
; buffer
|
||||||
|
; 3. Looks like cdecl, but she is not. For cdecl need compat wrapper
|
||||||
|
; 4. Dirties all registers, incl. ebp
|
||||||
|
;
|
||||||
|
; Input:
|
||||||
|
; esp+4 = pointer to template string
|
||||||
|
; esp+8 = wildcard strings pointers in reverse order
|
||||||
|
;
|
||||||
|
; Options:
|
||||||
|
if ~STR_BUILD_OFFSET
|
||||||
|
STR_BUILD_OFFSET = 0
|
||||||
|
; Optional, specify STR_BUILD_OFFSET value for offset from start
|
||||||
|
; of output buffer (this useful for postinsert initial characters
|
||||||
|
; before output sting). By default - no offset (0)
|
||||||
|
end if
|
||||||
|
if ~STR_BUILD_EXTRA
|
||||||
|
STR_BUILD_EXTRA = 0
|
||||||
|
; Optional, specify STR_BUILD_EXTRA value for extra length of
|
||||||
|
; output bufer (this useful for postadding characters after
|
||||||
|
; output string). By default - no extra length (0)
|
||||||
|
end if
|
||||||
|
|
||||||
|
;
|
||||||
|
; { STR_BUILD_NO_DOLLAR_SIGN - should be removed, see cpecial case above }
|
||||||
|
|
||||||
|
;
|
||||||
|
; Next two options below can reduse total code size by exclude
|
||||||
|
; corresponding parts if they are not used
|
||||||
|
;
|
||||||
|
if ~STR_BUILD_NO_STARTING_TEXT
|
||||||
|
STR_BUILD_NO_STARTING_TEXT = 0
|
||||||
|
; Specify STR_BUILD_NO_STARTING_TEXT if you do not used templates
|
||||||
|
; starting with text, e.g."Some text first $, $"
|
||||||
|
; By default is disabled (0)
|
||||||
|
end if
|
||||||
|
;
|
||||||
|
if ~STR_BUILD_NO_DOUBLE_WILDCARD
|
||||||
|
STR_BUILD_NO_DOUBLE_WILDCARD = 0
|
||||||
|
; Specify STR_BUILD_NO_DOUBLE_WILDCARD if you not used templates
|
||||||
|
; with double wildcards, e.g. "$$ some text" or "Some text $$"
|
||||||
|
; By default is disabled (0)
|
||||||
|
end if
|
||||||
|
;
|
||||||
|
; mem_alloc(size)
|
||||||
|
; external memory allocator, stdcall. Must return pointer (in eax)
|
||||||
|
; to base of memory block by size length. By defauld used internal
|
||||||
|
;
|
||||||
|
; Output:
|
||||||
|
; eax = Pointer to output string (see PRECAUTION #2) or 0 if error
|
||||||
|
; edi = Cursor of output string. No mean inf if eax = 0
|
||||||
|
;
|
||||||
|
; Stack struct
|
||||||
|
; ------
|
||||||
|
; | ArgN |
|
||||||
|
; -------
|
||||||
|
; | ... |
|
||||||
|
; -------
|
||||||
|
; ebp+4 | Arg1 |
|
||||||
|
; ------ -------
|
||||||
|
; ebp | TplS | Template string
|
||||||
|
; ------ -------
|
||||||
|
; | ret | Caller return address (not used), esp when entry
|
||||||
|
; -------
|
||||||
|
; | $off1 | 1st offset in template string
|
||||||
|
; -------
|
||||||
|
; | ... |
|
||||||
|
; -------
|
||||||
|
; | $offN | N-offset in template string
|
||||||
|
; -------
|
||||||
|
; | EOTpl | End of template string, esp after phase 1.1
|
||||||
|
; -------
|
||||||
|
; | Len1 | Length of 1st wildcard string
|
||||||
|
; -------
|
||||||
|
; | ... |
|
||||||
|
; -------
|
||||||
|
; | LenN | Length of N wildcard string, esp after phase 1.2
|
||||||
|
; -------
|
||||||
|
;
|
||||||
|
str_build:
|
||||||
|
mov ebp, esp ; Store caller esp...
|
||||||
|
add ebp, 8 ; ... and shift return address and tamplate string
|
||||||
|
mov esi, [ebp-4]
|
||||||
|
xor edx, edx ; Offsets, length...
|
||||||
|
xor edi, edi ; Found count...
|
||||||
|
|
||||||
|
; Phase 1.1. Scan to find positions $ and store to stack offsets $+1
|
||||||
|
; and end of template string. Break scan if zero byte appear
|
||||||
|
.scan:
|
||||||
|
lodsb
|
||||||
|
inc edx
|
||||||
|
or al, al
|
||||||
|
jz .end_scan
|
||||||
|
cmp al, '$'
|
||||||
|
je .found
|
||||||
|
jmp .scan
|
||||||
|
.found:
|
||||||
|
push edx ; Store offset
|
||||||
|
inc edi
|
||||||
|
jmp .scan
|
||||||
|
.end_scan:
|
||||||
|
or edi, edi
|
||||||
|
jz .error ; Not found
|
||||||
|
push edx ; Store last offset (end of template string)
|
||||||
|
sub edx, edi
|
||||||
|
dec edx ; Total length + zero string
|
||||||
|
|
||||||
|
; Phase 1.2. Store to stack lengths of wildcard strings
|
||||||
|
mov eax, edi
|
||||||
|
@@:
|
||||||
|
mov esi,[ebp+4*(eax-1)]
|
||||||
|
call strlen
|
||||||
|
add edx, ecx
|
||||||
|
push ecx
|
||||||
|
dec eax
|
||||||
|
inc edi ; once edi*2 instead
|
||||||
|
test eax,eax
|
||||||
|
jnz @b
|
||||||
|
|
||||||
|
add edx, STR_BUILD_OFFSET + STR_BUILD_EXTRA
|
||||||
|
|
||||||
|
; Phase 1.3. Allocate buffer for output string
|
||||||
|
if defined mem_alloc
|
||||||
|
stdcall mem_alloc, edx
|
||||||
|
else
|
||||||
|
mov eax, 68
|
||||||
|
mov ebx, 12
|
||||||
|
mov ecx, edx
|
||||||
|
int 0x40
|
||||||
|
end if
|
||||||
|
test eax,eax
|
||||||
|
jz .exit
|
||||||
|
|
||||||
|
mov byte[eax+edx],0 ; Mark end of output string
|
||||||
|
|
||||||
|
; Phase 2. Build output string
|
||||||
|
|
||||||
|
; eax = base of output string
|
||||||
|
xor ebx, ebx ; ebx = index of args data
|
||||||
|
; ecx = free, but used below
|
||||||
|
mov edx, edi ; edx = index of stored data
|
||||||
|
; esi = free, but used below
|
||||||
|
mov edi, eax ; edi = cursor of output string
|
||||||
|
|
||||||
|
add edi, STR_BUILD_OFFSET
|
||||||
|
if ~STR_BUILD_NO_STARTING_TEXT ; {
|
||||||
|
mov ecx, [esp+4*edx] ; Offset
|
||||||
|
cmp ecx,1 ; Wildcard first?
|
||||||
|
je .build
|
||||||
|
|
||||||
|
mov esi, -2 ; One or double wildcard at the end
|
||||||
|
neg ecx
|
||||||
|
add ecx, [esp+4*edx-4] ; Next offset
|
||||||
|
cmp ecx, 1 ; More one wildcard at the end?
|
||||||
|
je @f
|
||||||
|
dec esi
|
||||||
|
|
||||||
|
@@:
|
||||||
|
mov ecx,esi
|
||||||
|
add ecx,[esp+4*edx-4] ; Next offset
|
||||||
|
mov esi,[ebp-4] ; Template string
|
||||||
|
call strncpy
|
||||||
|
add edi, ecx ; Advance cursor
|
||||||
|
end if; } STR_BUILD_NO_STARTING_TEXT
|
||||||
|
.build:
|
||||||
|
mov esi, [ebp+4*ebx] ; Wildcard string
|
||||||
|
mov ecx,[esp+4*ebx] ; Length
|
||||||
|
call strncpy
|
||||||
|
add edi, ecx ; Advance cursor
|
||||||
|
mov ecx, [esp+4*edx] ; Offset
|
||||||
|
|
||||||
|
mov esi,[ebp-4] ; Template string
|
||||||
|
add esi, ecx
|
||||||
|
cmp byte [esi], 0 ; End of string?
|
||||||
|
je .exit
|
||||||
|
if ~STR_BUILD_NO_DOUBLE_WILDCARD ; {
|
||||||
|
cmp byte [esi], '$'
|
||||||
|
je @f
|
||||||
|
end if; } STR_BUILD_NO_DOUBLE_WILDCARD
|
||||||
|
neg ecx
|
||||||
|
add ecx,[esp+4*edx-4] ; Next offset
|
||||||
|
dec ecx
|
||||||
|
call strncpy
|
||||||
|
add edi, ecx ; Advance cursor
|
||||||
|
@@: ; { STR_BUILD_NO_DOUBLE_WILDCARD }
|
||||||
|
inc ebx
|
||||||
|
dec edx
|
||||||
|
cmp ebx, edx
|
||||||
|
jne .build
|
||||||
|
.exit:
|
||||||
|
; Restore stack
|
||||||
|
sub ebp, 8
|
||||||
|
mov esp,ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.error:
|
||||||
|
xor eax, eax
|
||||||
|
ret
|
||||||
|
|
5
programs/develop/libraries/dll/strings.rus
Normal file
5
programs/develop/libraries/dll/strings.rus
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
szBanner db "舘芋<E88898>!\n",0
|
||||||
|
szWrongFormat db "$ - $摚能𨯂走鴙諰 銈酮罱 能走恩平剁!",0
|
||||||
|
szLibraryNotLoaded db "$ - $摚╳妞恩陋 <20>␡膇兩<E88687> ”‵車漭芥 $", 0
|
||||||
|
szEntryNotFound db "$ - $<24>恕 $\n<> ”‵車漭炙 $\n郊 <20>岸平!",0
|
Loading…
Reference in New Issue
Block a user