Obsah / Utility / TEXT / TextMid
Zdrojový kód:
INCLUDE\UTIL\TEXT.INC, UTIL\TEXT.ASM
TextMid - Střední
část textu
Funkce TextMid navrátí
střední část textu, tedy část textu od dané pozice a o
dané délce.
; -----------------------------------------------------------------------------
; Get middle part of text
; -----------------------------------------------------------------------------
; INPUT: EAX = pointer to source TEXT
; EBX = pointer to destination TEXT
; ECX = length of part of text (it may be out of range)
; EDX = start position of part of text (it may be out of range)
; OUTPUT: CY = memory error, destination TEXT becomes empty
; NOTES: It limits length and position to a valid range.
; Source and destination may be identical.
; -----------------------------------------------------------------------------
|
Na vstupu funkce obsahuje registr EAX
ukazatel na zdrojovou textovou proměnnou, EBX ukazatel na
cílovou textovou proměnnou, ECX délku části textu (v
bajtech) a registr EDX pozici (offset) počátku části text.
Délka i pozice textu mohou být mimo platný rozsah. V
případě chyby paměti funkce navrátí příznak chyby CY a
cílový text se nastaví jako prázdný. Zdrojová a cílová
proměnná mohou být identické.
; ------------- Check if source and destination is identical
TextMid: cmp eax,ebx ; is source and destination identical?
je TextMid9 ; source is identical with destination
...................
; ------------- Identical source and destination variable (here is EAX == EBX)
TextMid9: push eax ; create temporary variable in stack
mov ebx,esp ; EBX <- temporary variable
push eax ; push EAX (destination variable)
mov eax,[eax] ; EAX <- TEXTDATA buffer
call TextAttach ; attach text to temporary variable
xchg eax,ebx ; EAX <- temporary variable
pop ebx ; EBX <- destination variable
call TextMid1 ; get middle part of text
pushf ; push flags
xchg eax,ebx ; EBX <- temporary, EAX <- destination
call TextDetach ; detach temporary variable
popf ; pop flags
pop ebx ; delete temporary variable
mov ebx,eax ; EBX <- destination variable
ret
|
Na začátku funkce se porovnáním
ukazatelů ověří, zda cílová a zdrojová textová proměnná
nejsou identické. Pokud ano, provede se kopie textu zvláštní
obsluhou a to tak, že se v zásobníku vytvoří přechodná
textová proměnná, vstupní proměnná se k ní připojí, do
cílové proměnné se z ní zkopíruj požadovaná střední
část textu a přechodná proměnná se opět zruší.
; ------------- Push registers
TextMid1: push eax ; push EAX
push ecx ; push ECX
push edx ; push EDX
push esi ; push ESI
push edi ; push EDI
; ------------- Empty destination text variable
call TextEmpty ; empty text
|
Po úschově registrů je cílový text
vyprázdněn pro případ návratu s chybou.
; ------------- Limit minimal start position
or edx,edx ; check minimal start position
js TextMid7 ; limit minimal start position
...................
; ------------- Limit minimal start position
TextMid7: add ecx,edx ; ECX <- correct text length
xor edx,edx ; EDX <- 0, limit start position
jmp short TextMid2
|
Testem registru EDX se ověří minimální
pozice části textu. Pokud leží pozice před začátkem textu,
opraví se délka textu a pozice se omezí na nulu.
; ------------- Check minimal text length
TextMid2: or ecx,ecx ; check text length
jle TextMid6 ; no text to copy (here is NC)
|
Pokud není délka textu kladné číslo,
není žádný text ke kopírování a funkce se ukončí.
; ------------- Check maximal start position (rest of text -> EAX)
mov esi,[eax] ; EDI <- data buffer
mov eax,[esi+TEXT_Length] ; EAX <- text length
sub eax,edx ; EAX <- remaining characters
jle TextMid5 ; no data to copy
|
Do registru ESI je připraven ukazatel na
buffer zdrojového textu a do registru EAX délka zdrojového
textu. Do registru EAX se připraví délka zbývající části
textu od dané pozice. Pokud nezbyl žádný text, funkce se
ukončí a bude navrácen prázdný text.
; ------------- Limit maximal text length
cmp eax,ecx ; EAX <- rest of text
jl TextMid8 ; length is too big
...................
; ------------- Limit maximal text length
TextMid8: xchg eax,ecx ; ECX <- limit maximal text length
jmp short TextMid4
|
Délka zbylého textu v registru EAX se
porovná s délkou požadovaného textu ECX a pokud je menší,
omezí se dékla požadovaného textu na skutečnou zbývající
délku textu.
; ------------- Create destination buffer (it need not be detached)
TextMid4: jecxz TextMid5 ; text is empty
mov eax,ecx ; EAX <- text length
call TextNew ; create data buffer
jc TextMid6 ; memory error
|
Registr ECX nyní obsahuje požadovanou
délku textu. Je-li požadovaná délka nula, funkce se může
ihned ukončit, cílový text je již vyprázdněný. Jinak se
vytvoří pomocí funkce TextNew nový textový buffer pro
požadovanou délku textu. Adresa bufferu se uloží do cílové
proměnné EBX. Původní obsah proměnné EBX není potřeba
odpojovat, protože se jednalo o prázdný konstantní text,
který nevyžaduje manipulaci s čítačem referencí.
; ------------- Prepare buffer address
lea esi,[esi+TEXT_Text+edx] ; EDI <- start of text
mov edi,[ebx] ; EDI <- destination buffer
add edi,byte TEXT_Text ; EDI <- destination text
; ------------- Copy text
shr ecx,2 ; ECX <- length of text in DWORDs
rep movsd ; shift text in DWORDs
and eax,byte 3 ; EAX <- rest in last DWORD
xchg eax,ecx ; ECX <- rest in last DWORD
rep movsb ; copy rest of text
; ------------- Pop registers
TextMid5: clc ; clear error flag
TextMid6: pop edi ; pop EDI
pop esi ; pop ESI
pop edx ; pop EDX
pop ecx ; pop ECX
pop eax ; pop EAX
ret
|
Registr ESI se posune na začátek
zdrojového textu. Do registru EDI se připraví začátek
bufferu cílového textu. Text se zkopíruje ze zdrojového do
cílového bufferu - nejdříve po celých dvojslovech a pak
zbylá data v posledním dvojslovu.
Obsah / Utility / TEXT / TextMid