
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³                                                                   ³
;³               RUTINAS EN ENSAMBLADOR PARA 765DEBUG                ³
;³                                                                   ³
;³          Incluir en un fichero de proyecto con 765DEBUG.C         ³
;³         El modelo de memoria debe ser necesariamente LARGE        ³
;³                                                                   ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

               PUBLIC    _MoveMem      ; copiar una zona de memoria a otra
               PUBLIC    _rnd          ; obtener n£mero aleatorio
               PUBLIC    _semilla      ; para n£meros aleatorios
               PUBLIC    _EsperaDma0   ; esperar cuenta 0xFFFF del DMA
               PUBLIC    _es386        ; detectar 386+
               PUBLIC    _NuevaInt0E   ; nueva interrupci¢n de disquete


_TEXT          SEGMENT WORD PUBLIC 'CODE'
               ASSUME  CS:_TEXT, DS:_DATA

; ------------ Copiar un bloque de memoria a otro sitio. El compilador
;              tiene media docena de funciones o mas pero ni una sola
;              que funcione bien. Requiere punteros huge.
;
;              Declaraci¢n:
;                 void MoveMem (char huge *fuente, char huge *destino,
;                               unsigned numbytes);

fuente         EQU   [BP+6]            ; para modelo LARGE
destino        EQU   [BP+10]
numbytes       EQU   [BP+14]

_MoveMem       PROC  FAR
               PUSH  BP
               MOV   BP,SP
               PUSH  SI
               PUSH  DI
               PUSH  DS
               PUSH  ES
               LDS   SI,fuente
               LES   DI,destino
               MOV   CX,numbytes
               SHR   CX,1
               CLD
               PUSHF
               REP   MOVSW
               POPF
               JNC   fin_mv
               MOVSB
fin_mv:        POP   ES
               POP   DS
               POP   DI
               POP   SI
               POP   BP
               RET
_MoveMem       ENDP


; ------------ Obtener n£mero aleatorio r pido.
;              Declaraci¢n: unsigned rnd (int unsigned);

rango          EQU   [BP+6]            ; para modelo LARGE

_rnd           PROC  FAR
               PUSH  BP
               MOV   BP,SP
               CMP   _semilla,0
               JNE   dev_rnd
               PUSH  DS
               MOV   AX,40h
               MOV   DS,AX
               MOV   AX,DS:[6Ch]       ; contador hora BIOS
               POP   DS                ; como semilla
               MOV   _semilla,AX
dev_rnd:       MOV   AX,_semilla
               MOV   BX,AX
               MOV   CL,7
               SHR   AX,CL
               XOR   AX,BX
               AND   AX,1
               ROR   AX,1
               SHR   BX,1
               OR    AX,BX
               MOV   _semilla,AX
               MUL   WORD PTR rango
               MOV   AX,DX
               POP   BP
               RET
_rnd           ENDP


; ------------ Esperar que el contador del DMA alcance el final y
;              resetear la controladora de disquetes.

unidad         EQU   BYTE PTR [BP+6]   ; para modelo LARGE

_EsperaDma0    PROC  FAR
               CLI                     ; *
               PUSH  AX
               PUSH  BX
               PUSH  CX
               PUSH  DX

               IN    AL,61h
               AND   AL,11111100b
               OR    AL,1
               JMP   SHORT $+2
               OUT   61h,AL            ; cnt2 en marcha
               MOV   AL,10010110b
               JMP   SHORT $+2
               OUT   43h,AL            ; 8254: cnt2 byte bajo
               MOV   AL,0
               JMP   SHORT $+2
               OUT   42h,AL
               MOV   AL,10100110b
               JMP   SHORT $+2
               OUT   43h,AL            ; 8254: cnt2 byte alto
               MOV   AL,0
               JMP   SHORT $+2
               OUT   42h,AL

               JMP   SHORT $+2
               IN    AL,42h
               MOV   BL,AL             ; estado de la cuenta alta
               MOV   DX,3F4h
               MOV   CX,9321           ; cte. para dos segundos

wait_dma:      IN    AL,DX             ; transferencia con DMA
               XOR   AL,11000000b
               TEST  AL,11000000b
               JZ    dma_fin           ; hay resultados del FDC
               IN    AL,5
               MOV   AH,AL
               IN    AL,5              ; contador del canal 2
               CMP   AX,-1
               JE    dma_fin           ; fin de la cuenta del DMA
               IN    AL,42h
               CMP   AL,BL
               JE    wait_dma          ; no han pasado 256/1193180 seg
               MOV   BL,AL
               LOOP  wait_dma

dma_fin:       MOV   CL,unidad
               ADD   CL,4
               MOV   AL,1
               SHL   AL,CL             ; bits motor en nibble alto
               OR    AL,unidad         ; seleccionar unidad
               OR    AL,00001000b      ; interrupciones+DMA y reset
               MOV   DX,3F2h           ; registro de salida digital
               OUT   DX,AL             ; se¤al de reset
               STI                     ; *
               XOR   CX,CX
pp486:         JMP   SHORT $+2
               LOOP  pp486
               OR    AL,00000100b
               OUT   DX,AL             ; fin de se¤al de reset
               POP   DX
               POP   CX
               POP   BX
               POP   AX
               RET
_EsperaDma0    ENDP


; ------------ Comprobar si es 386 o superior.
;              Declaraci¢n: int es386 (void);

_es386         PROC  FAR
               PUSHF
               POP   AX
               OR    AH,70h        ; intentar activar bit 12, 13 ¢ 14
               PUSH  AX            ; del registro de estado
               POPF
               PUSHF
               POP   AX
               AND   AH,0F0h
               CMP   AH,0F0h
               MOV   AL,0
               JE    fin_test_CPU  ; es 8086 o similar
               AND   AH,70h        ; 286 pone bits 12, 13 y 14 a cero
               JZ    fin_test_CPU  ; es 286
               MOV   AL,1          ; 386 o superior
fin_test_CPU:  MOV   AH,0
               RET
_es386         ENDP


; ------------ Rutina de interrupci¢n de disquete sin chorradas.

_NuevaInt0E    PROC
               STI
               PUSH  AX
               PUSH  DS
               MOV   AX,40h
               MOV   DS,AX
               OR    BYTE PTR DS:[3Eh],80h
               MOV   AL,66h
               OUT   20h,AL
               POP   DS
               POP   AX
               IRET
_NuevaInt0E    ENDP

_TEXT          ENDS

_DATA          SEGMENT WORD PUBLIC 'DATA'

_semilla       DW    0                 ; para n£meros aleatorios

_DATA          ENDS

               END
