; Aufgabe Nr.: Speichermodul fuer uP- Praktikum II
; Autor: Joerg Vollandt
; erstellt am : 21.05.1994
; letzte Aenderung am : 02.08.1994
; Bemerkung : Routinen fuer die Speicherverwaltung
;
; Dateiname : mem1.asm
;
;=====================================================================
; Definitionen der Funktionen des Seichermoduls
;INIT_MEM Initialisieren des Speichermoduls
;DEINIT_MEM Deinitialisieren des Speichermoduls
;CLEAR_MEM Speicher loeschen
;RESET_MEM Speicher zum lesen zuruecksetzen
;PUT_ELEMENT_MEM Element anf naechste freie Position schreiben
;GET_ELEMENT_MEM Element von akt. Position lesen
;WR_MEM_PC Speicher auf dem PC speichern.
;RD_MEM_PC Speicher vom PC laden.
;------------------------------------------------------------------------------
;Messagedefinitionen
;1.Dateityp (Bit 0 und Bit 1)
Msg_PC_To_Net equ 00b ;direkte Eingabe von Hex-Messages fБr das Netz
Msg_Frs_Datei equ 01b ;FrДstischdatei
Msg_Rob_Teach_Datei equ 10b ;Roboter-Teach-In-Datei
Msg_Frs_Teach_Datei equ 11b ;FrДstisch-Teach-In-Datei
;2.Aktion (Bit 2 und Bit 3)
Msg_PC_Get equ 0000b ;Rekordanfrage an PC
Msg_PC_Put equ 0100b ;Rekordspeichern Slave=>PC, Rekordausgabe PC=>Slave
Msg_PC_Reset equ 1000b ;PC Datei Фffnen zum Lesen
Msg_PC_Rewrite equ 1100b ;PC Datei Фffnen zum Schreiben
;3.Slaveadresse Slave=>PC ; Msg_From_PC PC=>Slave
Msg_From_PC equ 00000000b ;Antwort auf Anfrage
EOF_Record equ 0ffffh ;
PC_Slave_Adr equ 0eh ;
;------------------------------------------------------------------------------
; Speicherdefinitionen
SEGMENT DATA
CHECKSUMME DW ?
SEGMENT XDATA
POINTER DW ? ; fuer Test
NEXT_FREE DW ?
RD_POINTER DW ?
BLOCKNR DW ?
MEM_ANF DB 1000 DUP (?) ; Speichergroesse in Bytes
MEM_ENDE
;---------------------------------------------------------------------
SEGMENT CODE
;---------------------------------------------------------------------
; Funktion : Initialisieren des Speichermoduls
; Aufrufparameter : -
; Ruechgabeparameter : -
; Veraenderte Register : -
; Stackbedarf :
; Zeitbedarf :
;
INIT_MEM:
PUSH PSW
PUSH_DPTR
MOV DPTR,#MEM_ANF
SET_16 NEXT_FREE
SET_16 RD_POINTER
MOV CHECKSUMME,#0
MOV CHECKSUMME+1,#0
CLR READY
CLR CRC
POP_DPTR
POP PSW
RET
;---------------------------------------------------------------------
; Funktion : Deinitialisieren des Speichermoduls
; Aufrufparameter : -
; Ruechgabeparameter : -
; Veraenderte Register : -
; Stackbedarf :
; Zeitbedarf :
;
DEINIT_MEM:
RET
;---------------------------------------------------------------------
; Funktion : Speicher loeschen
; Aufrufparameter : -
; Ruechgabeparameter : -
; Veraenderte Register : -
; Stackbedarf :
; Zeitbedarf :
;
CLEAR_MEM:
PUSH PSW
PUSH_DPTR
MOV DPTR,#MEM_ANF
SET_16 NEXT_FREE
SET_16 RD_POINTER
MOV CHECKSUMME,#0
MOV CHECKSUMME+1,#0
CLR READY
CLR CRC
POP_DPTR
POP PSW
RET
;---------------------------------------------------------------------
; Funktion : Speicher zum lesen zuruecksetzen
; Aufrufparameter : -
; Ruechgabeparameter : -
; Veraenderte Register : -
; Stackbedarf :
; Zeitbedarf :
;
RESET_MEM:
PUSH_DPTR
MOV DPTR,#MEM_ANF
SET_16 RD_POINTER
POP_DPTR
RET
;---------------------------------------------------------------------
; Funktion : Speicher von MEM_ANF bis NEXT_FREE auf dem PC speichern.
; Aufrufparameter : -
; Ruechgabeparameter : -
; Veraenderte Register : -
; Stackbedarf :
; Zeitbedarf :
;
WR_MEM_PC:
PUSH_ALL
; MOV A,#MSG_PC_REWRITE+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_REWRITE
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr ; Datei oeffnen
MOV B,#8
SEND_NET
; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_PUT
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr ; Header zusammenstellen
MOV B,#8
MOV DPTR,#0
SET_16 BLOCKNR ; Blocknr.=0 setzen
MOV R1,DPL ; Blocknr.
MOV R2,DPH
GET_16 NEXT_FREE
SUBB_DPTR MEM_ANF
MOV R3,DPL ; Anzahl Bytes
MOV R4,DPH
LCALL CHECK_SUM
MOV R5,CHECKSUMME ; Pruefsumme
MOV R6,CHECKSUMME+1
SEND_NET ; Header senden
MOV DPTR,#MEM_ANF
SET_16 POINTER ; Zeiger auf MEM_ANF setzen
WR_MEM_MSG:
LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
JNC WR_MEM_MSG1
LJMP WR_MEM_CLOSE ; keine Bytes mehr -> close datei
WR_MEM_MSG1:
LCALL ACC_RD_MEM ; Byte aus MEM lesen
MOV R3,A ; Message aufbauen
LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
JNC WR_MEM_MSG2
LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben
WR_MEM_MSG2:
LCALL ACC_RD_MEM ; Byte aus MEM lesen
MOV R4,A ; Message aufbauen
LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
JNC WR_MEM_MSG3
LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben
WR_MEM_MSG3:
LCALL ACC_RD_MEM ; Byte aus MEM lesen
MOV R5,A ; Message aufbauen
LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
JNC WR_MEM_MSG4
LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben
WR_MEM_MSG4:
LCALL ACC_RD_MEM ; Byte aus MEM lesen
MOV R6,A ; Message aufbauen
LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
JNC WR_MEM_MSG5
LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben
WR_MEM_MSG5:
LCALL ACC_RD_MEM ; Byte aus MEM lesen
MOV R7,A ; Message aufbauen
PUSH_DPTR
GET_16 BLOCKNR
INC DPTR
SET_16 BLOCKNR ; Blocknr.=+1 setzen
MOV R1,DPL ; Blocknr.
MOV R2,DPH
POP_DPTR
; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_PUT
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr
MOV B,#8
SEND_NET ; Message senden
LJMP WR_MEM_MSG ; naechste Message
WR_MEM_REST:
PUSH_DPTR ; nicht volle MSG schreiben
GET_16 BLOCKNR
INC DPTR
SET_16 BLOCKNR ; Blocknr.=+1 setzen
MOV R1,DPL ; Blocknr.
MOV R2,DPH
POP_DPTR
; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_PUT
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr
MOV B,#8
SEND_NET ; Message senden
WR_MEM_CLOSE:
; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_PUT
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr ; Datei schlieсen
MOV B,#8
MOV R1,#(EOF_RECORD#256)
MOV R2,#(EOF_RECORD/256)
SEND_NET
POP_ALL
RET
;---------------------------------------------------------------------
; Funktion : Speicher vom PC laden.
; Aufrufparameter : -
; Ruechgabeparameter : -
; Veraenderte Register : -
; Stackbedarf :
; Zeitbedarf :
;
RD_MEM_PC:
PUSH_ALL
; MOV A,#MSG_PC_RESET+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_RESET
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr ; Datei oeffnen
MOV B,#8
SEND_NET
; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_GET
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr ; Header laden
MOV B,#8
MOV DPTR,#0
SET_16 BLOCKNR ; Blocknr.=0 setzen
MOV R1,DPL ; Blocknr.
MOV R2,DPH
SEND_NET ; Header anfordern
POP_ALL
RET
GET_FROM_PC:
PUSH_ALL
CJNE R1,#0,GET_NO_HEADER1 ; wenn Blocknr.=0, dann
CJNE R2,#0,GET_NO_HEADER1 ; Header
LJMP GET_HEADER
GET_NO_HEADER1:
LJMP GET_NO_HEADER
GET_HEADER:
CJNE R3,#0,GET_NOT_EMPTY_JMP ; testen ob 0 Bytes in Datei
CJNE R4,#0,GET_NOT_EMPTY_JMP
LJMP GET_EMPTY
GET_NOT_EMPTY_JMP:
LJMP GET_NOT_EMPTY
GET_EMPTY: ; Datei leer
LCALL INIT_MEM ; Speicherreset
; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_PUT
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr ; und Datei schlieсen
MOV B,#8
MOV R1,#(EOF_RECORD#256)
MOV R2,#(EOF_RECORD/256)
SEND_NET
POP_ALL
SETB READY
LCD 40H,"Teachin- Datei leer. "
RET
GET_NOT_EMPTY: ; Datei nicht leer
MOV DPL,R3 ; Groesse nach DPTR
MOV DPH,R4
ADD_DPTR MEM_ANF
SET_16 NEXT_FREE ; neues Speicherende setzen
MOV CHECKSUMME,R5 ; neue Checksumme laden
MOV CHECKSUMME+1,R6
PUSH_DPTR
GET_16 BLOCKNR
INC DPTR
SET_16 BLOCKNR ; Blocknr.=+1 setzen
MOV R1,DPL ; Blocknr.
MOV R2,DPH
POP_DPTR
; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_GET
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr
MOV B,#8
SEND_NET ; 1. Block anfordern
MOV DPTR,#MEM_ANF
SET_16 POINTER ; Zeiger auf MEM_ANF setzen
POP_ALL
RET
GET_NO_HEADER:
GET_16 POINTER ; Schreibzeiger laden
MOV A,R3
LCALL ACC_WR_MEM ; in den Speicher schreiben
LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
JNC GET_MORE2
LJMP GET_CLOSE ; wenn nicht Datei schliessen
GET_MORE2:
MOV A,R4
LCALL ACC_WR_MEM ; in den Speicher schreiben
LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
JNC GET_MORE3
LJMP GET_CLOSE ; wenn nicht Datei schliessen
GET_MORE3:
MOV A,R5
LCALL ACC_WR_MEM ; in den Speicher schreiben
LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
JNC GET_MORE4
LJMP GET_CLOSE ; wenn nicht Datei schliessen
GET_MORE4:
MOV A,R6
LCALL ACC_WR_MEM ; in den Speicher schreiben
LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
JNC GET_MORE5
LJMP GET_CLOSE ; wenn nicht Datei schliessen
GET_MORE5:
MOV A,R7
LCALL ACC_WR_MEM ; in den Speicher schreiben
LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei
JNC GET_MORE6
LJMP GET_CLOSE ; wenn nicht Datei schliessen
GET_MORE6:
SET_16 POINTER
GET_16 BLOCKNR
INC DPTR
SET_16 BLOCKNR ; Blocknr.=+1 setzen
MOV R1,DPL ; Blocknr.
MOV R2,DPH
; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_GET
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr
MOV B,#8
SEND_NET ; naechsten Block anfordern
POP_ALL
RET
GET_CLOSE:
; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16
MOV A,MY_SLAVE_ADR
SWAP A ; *16
ADD A,#MSG_PC_PUT
MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese
SETB ACC.1
MOV R0,A
MOV A,#PC_Slave_Adr ; und Datei schlieсen
MOV B,#8
MOV R1,#(EOF_RECORD#256)
MOV R2,#(EOF_RECORD/256)
SEND_NET
MOV R0,CHECKSUMME
MOV A,CHECKSUMME+1
LCALL CHECK_SUM
CJNE A,CHECKSUMME+1,GET_CRC_ERROR
MOV A,R0
CJNE A,CHECKSUMME,GET_CRC_ERROR
POP_ALL
CLR CRC
SETB READY
LCD 40H,"Teachin- Datei fehlerfrei geladen. "
RET
GET_CRC_ERROR:
POP_ALL
SETB CRC
SETB READY
LCD 40H,"FEHLER bei Laden der Teachin- Datei. "
RET
;---------------------------------------------------------------------
; Funktion : Testen ob DPTR zum LESEN auf belegten Speicher zeigt.
; C=0 ==> MEM_ANF <= DPTR < NEXT_FREE
; C=1 ==> sonst
; Aufrufparameter : DPTR = Pointer
; Ruechgabeparameter : -
; Veraenderte Register : PSW
; Stackbedarf :
; Zeitbedarf :
;
CHECK_RD_POINTER:
PUSH PSW
PUSH ACC
MOV A,#((MEM_ANF-1)/256)
CJNE A,DPH,CH_RD1 ; Test ob Pointer >= MEM_ANF
CH_RD1: JC CH_RD_OK1
CJNE A,DPH,CH_RD_ERROR ;
MOV A,#((MEM_ANF-1)#256)
CJNE A,DPL,CH_RD2
CH_RD2: JC CH_RD_OK1
LJMP CH_RD_ERROR ;
CH_RD_OK1:
PUSH_DPTR
MOV DPTR,#(NEXT_FREE+1)
MOVX A,@DPTR
POP_DPTR
CJNE A,DPH,CH_RD3 ; Test ob Pointer < NEXT_FREE
CH_RD3: JC CH_RD_ERROR
CJNE A,DPH,CH_RD_OK2 ;
PUSH_DPTR
MOV DPTR,#NEXT_FREE
MOVX A,@DPTR
POP_DPTR
CJNE A,DPL,CH_RD4
CH_RD4: JC CH_RD_ERROR
CJNE A,DPL,CH_RD_OK2
LJMP CH_RD_ERROR ;
CH_RD_OK2:
POP ACC
POP PSW
CLR C ; o.k.
RET
CH_RD_ERROR:
POP ACC
POP PSW
SETB C ; Fehler
RET
;---------------------------------------------------------------------
; Funktion : Testen ob DPTR zum SCHREIBEN auf belegten Speicher zeigt.
; C=0 ==> MEM_ANF <= DPTR <= NEXT_FREE
; C=1 ==> sonst
; Aufrufparameter : DPTR = Pointer
; Ruechgabeparameter : -
; Veraenderte Register : PSW
; Stackbedarf :
; Zeitbedarf :
;
CHECK_WR_POINTER:
PUSH PSW
PUSH ACC
MOV A,#((MEM_ANF-1)/256)
CJNE A,DPH,CH_WR1 ; Test ob Pointer >= MEM_ANF
CH_WR1: JC CH_WR_OK1
CJNE A,DPH,CH_WR_ERROR ;
MOV A,#((MEM_ANF-1)#256)
CJNE A,DPL,CH_WR2
CH_WR2: JC CH_WR_OK1
LJMP CH_WR_ERROR ;
CH_WR_OK1:
PUSH_DPTR
MOV DPTR,#(NEXT_FREE+1)
MOVX A,@DPTR
POP_DPTR
CJNE A,DPH,CH_WR3 ; Test ob Pointer <= NEXT_FREE
CH_WR3: JC CH_WR_ERROR
CJNE A,DPH,CH_WR_OK2 ;
PUSH_DPTR
MOV DPTR,#NEXT_FREE
MOVX A,@DPTR
POP_DPTR
CJNE A,DPL,CH_WR4
CH_WR4: JNC CH_WR_OK2
LJMP CH_WR_ERROR ;
CH_WR_OK2:
POP ACC
POP PSW
CLR C ; o.k.
RET
CH_WR_ERROR:
POP ACC
POP PSW
SETB C ; Fehler
RET
;---------------------------------------------------------------------
; Funktion : Testen ob DPTR < MEM_ENDE.
; C=0 ==> DPTR < MEM_ENDE
; C=1 ==> sonst
; Aufrufparameter : DPTR = Pointer
; Ruechgabeparameter : -
; Veraenderte Register : PSW
; Stackbedarf :
; Zeitbedarf :
;
CHECK_EOM_POINTER:
PUSH PSW
PUSH ACC
MOV A,#(MEM_ENDE/256)
CJNE A,DPH,CH_EOM3 ; Test ob Pointer < MEM_ENDE
CH_EOM3: JC CH_EOM_ERROR
CJNE A,DPH,CH_EOM_OK2 ;
MOV A,#(MEM_ENDE#256)
CJNE A,DPL,CH_EOM4
CH_EOM4: JC CH_EOM_ERROR
CJNE A,DPL,CH_EOM_OK2
LJMP CH_EOM_ERROR ;
CH_EOM_OK2:
POP ACC
POP PSW
CLR C ; o.k.
RET
CH_EOM_ERROR:
POP ACC
POP PSW
SETB C ; Fehler
RET
;---------------------------------------------------------------------
; Funktion : ACC in den Speicher schreiben, DPTR increminieren.
; Aufrufparameter : ACC = Wert, DPTR = Pointer
; Ruechgabeparameter : -
; Veraenderte Register : DPTR
; Stackbedarf :
; Zeitbedarf :
;
ACC_WR_MEM:
MOVX @DPTR,A
INC DPTR
RET
;---------------------------------------------------------------------
; Funktion : ACC aus dem Speicher lesen, DPTR increminieren.
; Aufrufparameter : DPTR = Pointer
; Ruechgabeparameter : ACC = Wert
; Veraenderte Register : ACC, DPTR
; Stackbedarf :
; Zeitbedarf :
;
ACC_RD_MEM:
MOVX A,@DPTR
INC DPTR
RET
;---------------------------------------------------------------------
; Funktion : Pruefsumme ueber den Speicher bilden.
; Aufrufparameter : -
; Ruechgabeparameter : -
; Veraenderte Register : -
; Stackbedarf :
; Zeitbedarf :
;
CHECK_SUM:
PUSH PSW
PUSH ACC
PUSH_DPTR
MOV CHECKSUMME,#0
MOV CHECKSUMME+1,#0
MOV DPTR,#MEM_ANF ; Pointer auf MEM_ANF setzen
CHECK_SUM1:
LCALL CHECK_RD_POINTER ; Pointer in DPTR!!!
JC CHECK_SUM_ENDE
LCALL ACC_RD_MEM ; Byte aus MEM lesen
ADD A,CHECKSUMME
MOV CHECKSUMME,A
MOV A,#0
ADDC A,CHECKSUMME+1
MOV CHECKSUMME+1,A
LJMP CHECK_SUM1
CHECK_SUM_ENDE:
POP_DPTR
POP ACC
POP PSW
RET
;---------------------------------------------------------------------
; Funktion : Element in den Speicher auf die naechste frei Position schreiben.
; Aufrufparameter : ACC = Wert
; Ruechgabeparameter : C=0 ==> o.k., C=1 ==> Speicherueberlauf
; Veraenderte Register : -
; Stackbedarf :
; Zeitbedarf :
;
PUT_ELEMENT_MEM:
PUSH PSW
GET_16 NEXT_FREE
LCALL CHECK_EOM_POINTER ; testen ob DPTR < MEM_ENDE
JC GET_ELEMENT_ERROR ; wenn nicht Fehler
LCALL CHECK_WR_POINTER ; testen ob MEM_ANF <= DPTR <= NEXT_FREE
JC PUT_ELEMENT_ERROR ; wenn nicht Fehler
LCALL ACC_WR_MEM ; Byte aus MEM lesen
SET_16 NEXT_FREE
PUT_EL_OK1:
POP PSW
CLR C
RET
PUT_ELEMENT_ERROR:
POP PSW
SETB C
RET
RET
;---------------------------------------------------------------------
; Funktion : Element von der akt. Position aus dem Speicher lesen.
; Aufrufparameter : -
; Ruechgabeparameter : ACC = Wert
; C=0 ==> o.k., C=1 ==> Schreib- gleich Lesezeiger
; oder Lesezeiger ausserhalb des gueltigen Bereiches
; Veraenderte Register : ACC, PSW
; Stackbedarf :
; Zeitbedarf :
;
GET_ELEMENT_MEM:
PUSH PSW
GET_16 RD_POINTER
LCALL CHECK_EOM_POINTER ; testen ob DPTR < MEM_ENDE
JC GET_ELEMENT_ERROR ; wenn nicht Fehler
LCALL CHECK_RD_POINTER ; testen ob MEM_ANF <= DPTR < NEXT_FREE
JC GET_ELEMENT_ERROR ; wenn nicht Fehler
LCALL ACC_RD_MEM ; Byte aus MEM lesen
SET_16 RD_POINTER
GET_EL_OK1:
POP PSW
CLR C
RET
GET_ELEMENT_ERROR:
POP PSW
SETB C
RET
;=====================================================================
; END
;---------------------------------------------------------------------