📄 text.asm
字号:
;*** TEXT.ASM - Low level routines for Text Manager
;*
;* GLOBAL
;* SegAddr Linear address -> segmented address
;* CbFindLine Find a line in the source buffer
;* BigMoveUp Move large blocks of memory up (overlapping)
;* BigMoveDown Move large blocks of memory down (overlapping)
;* LinearAddr Convert from segmented to linear (32-bit) address
;*
;* LOCAL
;* $LinearAddr Convert from segmented to linear (32-bit) address
;* $SegAddr Convert from linear (32-bit) to segmented address
;*
;* DESCRIPTION
;* Low level routines for dealing with large blocks of data.
;*
;------------------------------------------------------------
PAGE 66,132
TITLE TEXT.ASM - Low level routines for Text Manager
.XLIST
include version.inc
.LIST
;------------------------------------------------------------
; DATA segment definitions
;------------------------------------------------------------
assumes DS, DATA
assumes SS, DATA
;------------------------------------------------------------
; CODE segment definitions
;------------------------------------------------------------
sBegin UI
assumes CS,UI
;*** SegAddr - Convert from linear to segmented address
;*
;* SYNOPSIS
;* lp = SegAddr(addr32)
;*
;* ENTRY
;* addr32 32-bit (linear) address
;*
;* RETURNS
;* Far pointer (segmented address)
;*
;* DESCRIPTION
;* Calls internal routine $SegAddr to do the work
;------------------------------------------------------------
cProc SegAddr, <NEAR, PUBLIC>
parmD addr32
cBegin
mov dx, word ptr [addr32 + 2]
mov ax, word ptr [addr32]
call $SegAddr
cEnd
;*** LinearAddr - Convert from segmented to linear (32-bit) address
;*
;* SYNOPSIS
;* addr32 = LinearAddr(lp)
;*
;* ENTRY
;* lp Far pointer
;*
;* RETURNS
;* 32-bit address of converted far pointer
;*
;* DESCRIPTION
;* Calls local routine $LinearAddr
;------------------------------------------------------------
cProc LinearAddr, <NEAR, PUBLIC>
parmD lp
cBegin
mov ax, word ptr [lp]
mov dx, word ptr [lp + 2]
call $LinearAddr
cEnd
;*** CbFindLine - Find a line in the source buffer
;*
;* SYNOPSIS
;* cb = CbFindLine(pAddr32, oln)
;*
;* ENTRY
;* pAddr32 POINTER TO 32-bit address of source buffer
;* oln Line number to find
;*
;* RETURNS
;* Number of bytes in line found
;* Also stores 32-bit linear address of line found in pAddr32
;*
;* DESCRIPTION
;* On entry, *pAddr32 "points to" the word count preceding a line of
;* text. Simply moves through the source buffer, using the word
;* count preceding each line to skip to the next line. On exit,
;* *pAddr32 "points to" the line found (actual text, NOT the preceding
;* word count).
;------------------------------------------------------------
cProc CbFindLine, <NEAR, PUBLIC>, <DI, SI>
parmDP pAddr32
parmW oln
cBegin
mov bx, pAddr32
mov ax, [bx]
mov dx, [bx+2]
call $SegAddr ; Returns DX:AX as far pointer
mov es, dx
mov di, ax
mov cx, oln
inc cx ; Filename is always "line 0"
xor si, si
NextLine:
add di, si
; Normalize es:di
mov ax, di
shr ax, 1
shr ax, 1
shr ax, 1
shr ax, 1
mov bx, es
add ax, bx
mov es, ax
and di, 000Fh
mov si, es:[di]
inc di ; Skip...
inc di ; ...word count
loop NextLine
; Convert back to 32-bit address
mov ax, di
mov dx, es
call $LinearAddr
; Store 32-bit address
mov bx, pAddr32
mov [bx], ax
mov [bx+2], dx
mov ax, si ; Number of bytes in line
cEnd
;*** BigMoveUp - Moves large blocks of overlapping memory up
;*
;* SYNOPSIS
;* BigMoveUp(addr32Dst, addr32Src, cb)
;*
;* ENTRY
;* addr32Dst 32-bit address "pointer" to dest. buffer
;* addr32Src 32-bit address "pointer" to source buffer
;* cb Number of bytes to move
;*
;* RETURNS
;* None
;*
;* DESCRIPTION
;* The algorithm moves the data in chunks of FFF0 bytes.
;*
;* Before starting to do the move, the number of FFF0 length chunks
;* is calculated, along with the number of bytes that are left over.
;* (Find i, j such that cb = i*FFF0 + j where j < FFF0).
;*
;* So i blocks of size FFF0 and one block of size j must be moved.
;* The i blocks of size FFF0 are moved first, followed by the one
;* block of size j.
;*
;* In order to move FFF0 bytes, each of the source, and the destination
;* addresses must have an offset portion less than 000F (because
;* we are moving from bottom to top). Before each chunk is moved,
;* both addresses are normalized to this form.
;*
;* CAVEAT
;* This routine will not work for blocks which start anywhere in the
;* last 64K of physical memory.
;*
;* This routine makes implicit use of the relationship between segment
;* number, and physical address that exists in the iApx 86 architecture.
;* This routing assumes that cb >= 2
;------------------------------------------------------------
cProc BigMoveUp, <NEAR, PUBLIC>, <DS, SI, DI>
parmD addr32Dst
parmD addr32Src
parmD cb
cBegin
cCall SegAddr,<addr32Dst> ; Convert from linear to segmented address
mov es, dx
mov di, ax
cCall SegAddr,<addr32Src> ; Convert from linear to segmented address
mov ds, dx
mov si, ax
; Calulate the number of FFF0-byte chunks to move.
; (Save the remainder for later).
mov ax, word ptr [cb]
mov dx, word ptr [cb + 2]
mov bx, 0FFF0h
div bx ; AX == # of chunks, DX == # of bytes
xchg dx, ax
push ax
NextChunkUp:
mov cl, 4 ; Normalize DS:SI to form SSSS:000y
mov ax, si
shr ax, cl
mov bx, ds
add ax, bx
mov ds, ax
and si, 000fH
mov ax, di ; Normalize ES:DI to form SSSS:000y
shr ax, cl
mov bx, es
add ax, bx
mov es, ax
and di, 000fH
or dx,dx ; See if done moving big blocks
je MoveBytesUp ; Yes, move last partial block
dec dx ; Moving next big block
mov cx, 0FFF0h / 2
rep movsw ; Moving words is faster than bytes
jmp Short NextChunkUp
; At this point DS:SI and ES:DI are normalized, so we can move the
; remaining bytes in one chunk.
MoveBytesUp:
pop cx ; Get back # of bytes
shr cx, 1
jnc MoveWordsUp
movsb ; Move odd byte
MoveWordsUp:
rep movsw ; Move last chunk of words
cEnd
;*** BigMoveDown - Moves large blocks of overlapping memory down
;*
;* SYNOPSIS
;* BigMoveDown(addr32Dst, addr32Src, cb)
;*
;* ENTRY
;* addr32Dst 32-bit address "pointer" to source buffer
;* addr32Src 32-bit address "pointer" to dest. buffer
;* cb Number of bytes to move
;*
;* RETURNS
;* None
;*
;* DESCRIPTION
;* Similar in operation to BigMoveUp().
;------------------------------------------------------------
cProc BigMoveDown, <NEAR, PUBLIC>, <DS, SI, DI>
parmD addr32Dst
parmD addr32Src
parmD cb
cBegin
mov ax, word ptr [addr32Dst] ; Point to end of Target string
mov dx, word ptr [addr32Dst + 2]
add ax, word ptr [cb]
adc dx, word ptr [cb + 2]
sub ax, 1 ; Address must be zero based
sbb dx, 0
call $SegAddr ; Convert linear to segmented addr
mov di, ax ; ES:DI == end of target string
mov es, dx
mov ax, word ptr [addr32Src] ;Point to end of Source string
mov dx, word ptr [addr32Src + 2]
add ax, word ptr [cb]
adc dx, word ptr [cb + 2]
sub ax, 1 ; Address is zero based
sbb dx, 0
call $SegAddr ; Convert linear to segmented addr
mov si, ax ; DS:SI == end of source string
mov ds, dx
; Calulate the number of FFF0-byte chunks to move.
; (Save the remainder for later).
mov ax, word ptr [cb]
mov dx, word ptr [cb + 2]
mov bx, 0FFF0h
div bx ; AX == # of chunks, DX == # of bytes
xchg dx, ax
push ax ; Save final chunk size in bytes
std ; Performing a reverse move operation
NextChunkDown:
mov cl, 4 ; Normalize DS:SI to form SSSS:FFFy
mov ax, si
shr ax, cl
mov bx, 0FFFh
sub bx, ax
mov ax, ds
sub ax, bx
mov ds, ax
or si, 0FFF0h
mov cl, 4 ; Normalize ES:DI to form SSSS:FFFy
mov ax, di
shr ax, cl
mov bx, 0FFFh
sub bx, ax
mov ax, es
sub ax, bx
mov es, ax
or di, 0FFF0h
or dx,dx ; See if done moving big blocks
je MoveBytesDown ; Yes, move last partial block and quit
dec dx ; Keep track of big blocks moved
movsb ; Can't do a movsw if either SI or...
movsb ; ...DI is 0FFFFh so do two movsb's...
; ...to make sure they are not
dec si ; Point at the low byte of the words to be moved
dec di ; (We are moving words at a time now)
mov cx, 0FFF0h / 2 - 1 ; Number of words - 1
rep movsw
inc si ; Repz goes one byte too far
inc di
jmp Short NextChunkDown
; At this point DS:SI and ES:DI are normalized, so we can move the
; remaining bytes in one chunk.
MoveBytesDown:
pop cx ; Get back # of remaining bytes
shr cx, 1 ; Convert to words
jnc MoveWordsDown ; See if odd byte exists
movsb ; Move odd byte
MoveWordsDown:
jcxz MoveDownDone ; No moves on zero length left
movsb ; Problem with moving last word of block
movsb
dec cx ; Count the Word move
dec si ; Point at the low byte of the words to be moved
dec di ; (We are moving words at a time now)
rep movsw
MoveDownDone:
cld ; Always restore UP condition flag
cEnd
;------------------------------------------------------------
; LOCAL routines
;------------------------------------------------------------
;*** $LinearAddr - Convert far pointer to linear (32-bit) address
;*
;* ENTRY
;* DX Segment of far pointer
;* AX Offset of far pointer
;*
;* RETURNS
;* DX High word of 32-bit address
;* AX Low word of 32-bit address
;*
;* USES
;* BX
;* CL
;*
;* DESCRIPTION
;* Addr32 = (Segment << 4) + Offset
;------------------------------------------------------------
$LinearAddr proc near
mov bx, ax
mov cl, 4
rol dx, cl
mov ax, dx
and dx, 000Fh
and ax, 0FFF0h
add ax, bx
adc dx, 0
ret
$LinearAddr endp
;*** $SegAddr - Convert from linear (32-bit) address to far pointer
;*
;* ENTRY
;* DX High word of 32-bit address
;* AX Low word of 32-bit address
;*
;* RETURNS
;* DX Segment of far pointer
;* AX Offset of far pointer
;*
;* USES
;* BX
;* CL
;*
;* DESCRIPTION
;* Addr32 = (Segment << 4) + Offset
;------------------------------------------------------------
$SegAddr proc near
and dx, 000Fh
mov bx, ax
and ax, 0FFF0h
or dx, ax
mov cl, 4
ror dx, cl
mov ax, bx
and ax, 000Fh
ret
$SegAddr endp
sEnd UI
;------------------------------------------------------------
; Memory Support routines
;------------------------------------------------------------
sBegin RT
assumes CS,RT
extrn B$IFHAlloc:near
extrn B$FHRealloc:near
extrn B$FHDealloc:near
;*** FhdAlloc - Allocate a fhd
;*
;* SYNOPSIS
;* success = FhdAlloc(pFhd, cb)
;*
;* ENTRY
;* pFhd pointer to fhd to allocate
;* cb Initial size of fhd
;*
;* RETURNS
;* FALSE if allocation failed
;*
;* DESCRIPTION
;* Allocates the fhd by calling the runtime entrypoint for
;* far heap allocs.
;------------------------------------------------------------
cProc FhdAlloc,<PUBLIC,FAR>
parmW pFhd
parmD cb
cBegin
mov bx,pFhd
mov dx,WORD PTR cb+2
mov ax,WORD PTR cb
call B$IFHAlloc
cEnd
;*** FhdReAlloc - Realloc a fhd
;*
;* SYNOPSIS
;* success = FhdReAlloc(pFhd, cb)
;*
;* ENTRY
;* pFhd pointer to fhd to reallocate
;* cb new size of fhd
;*
;* RETURNS
;* FALSE if reallocation failed
;*
;* DESCRIPTION
;* Reallocates the fhd by calling the runtime entrypoint for
;* far heap reallocation.
;------------------------------------------------------------
cProc FhdRealloc,<PUBLIC,FAR>
parmW pFhd
parmD cb
cBegin
mov bx,pFhd
mov dx,WORD PTR cb+2
mov ax,WORD PTR cb
call B$FHRealloc
cEnd
;*** FhdDealloc - Deallcates a fhd
;*
;* SYNOPSIS
;* FhdDealloc(pFhd)
;*
;* ENTRY
;* pFhd pointer to fhd to deallocate
;*
;* RETURNS
;* Nothing
;*
;* DESCRIPTION
;------------------------------------------------------------
cProc FhdDealloc,<PUBLIC,FAR>
parmW pFhd
cBegin
mov bx,pFhd
call B$FHDealloc
cEnd
sEnd RT
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -