152 lines
6.0 KiB
NASM
152 lines
6.0 KiB
NASM
|
; Turbo Pascal 5.5 object-oriented example
|
|||
|
; Assembler code for TCALC example
|
|||
|
; Copyright (c) 1989 by Borland International, Inc.
|
|||
|
|
|||
|
MODEL TPASCAL
|
|||
|
|
|||
|
LOCALS
|
|||
|
|
|||
|
DATASEG
|
|||
|
|
|||
|
EXTRN CheckSnow : BYTE
|
|||
|
|
|||
|
CODESEG
|
|||
|
|
|||
|
PUBLIC MoveToScreen, MoveFromScreen
|
|||
|
|
|||
|
; procedure MoveToScreen(var Source, Dest; Len : Word);
|
|||
|
;
|
|||
|
; Moves memory from normal RAM to screen memory, making sure that the video
|
|||
|
; interference that can occur when you do this on certain CGA's is
|
|||
|
; prevented.
|
|||
|
;
|
|||
|
; Variables:
|
|||
|
;
|
|||
|
; Source : Far pointer to the location of the memory to be moved.
|
|||
|
; Dest : Far pointer to the destination of the memory to be moved.
|
|||
|
; Len : The amount in bytes of the memory to be moved.
|
|||
|
|
|||
|
Proc MoveToScreen Source : DWord, Dest : DWord, Len : Word
|
|||
|
push ds ; Save DS
|
|||
|
mov bh,[CheckSnow] ; Load CheckSnow value
|
|||
|
lds si,[Source] ; Source pointer into DS:SI
|
|||
|
les di,[Dest] ; Dest pointer into ES:DI
|
|||
|
mov cx,[Len] ; Len value into CX
|
|||
|
jcxz @@0 ; Quit if Len = 0
|
|||
|
cmp si,di ; Find out if source comes before destination
|
|||
|
; in memory
|
|||
|
jle @@1 ; If it does, copy from end of memory area
|
|||
|
cld ; Set direction to forward
|
|||
|
jmp short @@2
|
|||
|
@@1:
|
|||
|
add si,cx ; Move SI and DI to the ends of the memory
|
|||
|
sub si,2 ; areas
|
|||
|
add di,cx
|
|||
|
sub di,2
|
|||
|
std ; Set direction to backward
|
|||
|
@@2:
|
|||
|
cmp bh,0 ; If CheckSnow is false, use fast screen I/O
|
|||
|
je @@7
|
|||
|
@@3:
|
|||
|
shr cx,1 ; Change bytes to words
|
|||
|
mov dx,3DAh ; Point DX to CGA status port
|
|||
|
mov bl,9 ; Move horiz. + vertical retrace mask to bl
|
|||
|
@@4:
|
|||
|
lodsw ; Grab a video word
|
|||
|
mov bp,ax ; Save it in BP
|
|||
|
@@5:
|
|||
|
in al,dx ; Get 6845 status
|
|||
|
rcr al,1 ; Check horizontal retrace
|
|||
|
jb @@5 ; Loop if in horizontal retrace: this prevents
|
|||
|
; starting in mid-retrace, since there is
|
|||
|
; exactly enough time for 1 and only 1 STOSW
|
|||
|
; during horizontal retrace
|
|||
|
cli ; No ints during critical section
|
|||
|
@@6:
|
|||
|
in al,dx ; Get 6845 status
|
|||
|
and al,bl ; Check for both kinds of retrace: IF the
|
|||
|
; video board does not report horizontal
|
|||
|
; retrace while in vertical retrace, this
|
|||
|
; will allow several characters to be
|
|||
|
; stuffed in during vertical retrace
|
|||
|
jz @@6 ; Loop if equal to zero
|
|||
|
mov ax,bp ; Get the video word
|
|||
|
stosw ; Store the video word
|
|||
|
sti ; Allow interrupts
|
|||
|
loop @@4 ; Go do next word
|
|||
|
jmp short @@0
|
|||
|
@@7:
|
|||
|
shr cx,1 ; Change bytes to words
|
|||
|
rep movsw
|
|||
|
@@0:
|
|||
|
pop ds ; Restore DS
|
|||
|
ret
|
|||
|
ENDP
|
|||
|
|
|||
|
; procedure MoveFromScreen(var Source, Dest; Len : Word);
|
|||
|
;
|
|||
|
; Moves memory to normal RAM from screen memory, making sure that the video
|
|||
|
; interference that can occur when you do this on certain CGA's is
|
|||
|
; prevented.
|
|||
|
;
|
|||
|
; Variables:
|
|||
|
;
|
|||
|
; Source : Far pointer to the location of the memory to be moved.
|
|||
|
; Dest : Far pointer to the destination of the memory to be moved.
|
|||
|
; Len : The amount in bytes of the memory to be moved.
|
|||
|
|
|||
|
Proc MoveFromScreen Source : DWord, Dest : DWord, Len : Word
|
|||
|
push ds ; Save DS
|
|||
|
mov bh,[CheckSnow] ; Load CheckSnow value
|
|||
|
lds si,[Source] ; Source pointer into DS:SI
|
|||
|
les di,[Dest] ; Dest pointer into ES:DI
|
|||
|
mov cx,[Len] ; Len value into CX
|
|||
|
jcxz @@0 ; Quit if Len = 0
|
|||
|
cmp si,di ; Find out if source comes before destination
|
|||
|
; in memory
|
|||
|
jle @@1
|
|||
|
cld ; Set direction to forward
|
|||
|
jmp short @@2
|
|||
|
@@1:
|
|||
|
add si,cx ; Move SI and DI to the ends of the memory
|
|||
|
sub si,2 ; areas
|
|||
|
add di,cx
|
|||
|
sub di,2
|
|||
|
std ; Set direction to backward
|
|||
|
@@2:
|
|||
|
cmp bh,0 ; If CheckSnow is false, use fast screen I/O
|
|||
|
je @@6
|
|||
|
@@3:
|
|||
|
shr cx,1 ; Change bytes to words
|
|||
|
mov dx,3DAh ; Point DX to CGA status port
|
|||
|
@@4:
|
|||
|
in al,dx ; Get 6845 status
|
|||
|
rcr al,1 ; Check horizontal retrace
|
|||
|
jb @@4 ; Loop if in horizontal retrace: this prevents
|
|||
|
; starting in mid-retrace, since there is
|
|||
|
; exactly enough time for 1 and only 1 LODSW
|
|||
|
; during horizontal retrace
|
|||
|
cli ; No ints during critical section
|
|||
|
@@5:
|
|||
|
in al,dx ; Get 6845 status
|
|||
|
rcr al,1 ; Check for horizontal retrace: LODSW is 1
|
|||
|
; clock cycle slower than STOSW; because of
|
|||
|
; this, the vertical retrace trick can't be
|
|||
|
; used because it causes flicker! (RCR AL,1
|
|||
|
; is 1 cycle faster than AND AL,AH)
|
|||
|
jnb @@5 ; Loop if not in retrace
|
|||
|
lodsw ; Load the video word
|
|||
|
sti ; Allow interrupts
|
|||
|
stosw ; Store the video word
|
|||
|
loop @@4 ; Go do next word
|
|||
|
jmp short @@0
|
|||
|
@@6:
|
|||
|
shr cx,1 ; Change bytes to words
|
|||
|
rep movsw
|
|||
|
@@0:
|
|||
|
pop ds ; Restore DS
|
|||
|
ret
|
|||
|
ENDP
|
|||
|
|
|||
|
END
|
|||
|
|