home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
asm_kit
/
macro1.asm
< prev
next >
Wrap
Assembly Source File
|
1985-05-11
|
19KB
|
566 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; ASSEMBLE.MAC ;;
;; ;;
;; SAMPLE MACRO LIBRARY FOR THE IBM PC MACRO ASSEMBLER ;;
;; ;;
;; (C) COPYRIGHT 1983 ;;
;; BY ;;
;; JERRY D. STUCKLE ;;
;; ;;
;; RELEASED TO PUBLIC DOMAIN ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CLEAR MACRO R1,R2,R3,R4,R5,R6,R7,R8
;;***************************************************************************;;
;; ;;
;; MACRO: CLEAR ;;
;; ;;
;; DESCRIPTION: CLEAR REGISTERS ;;
;; ;;
;; PARAMATERS: UP TO 8 REGISTERS TO BE CLEARED ;;
;; ;;
;; INPUT: N/A ;;
;; ;;
;; OUTPUT: REQUESTED REGISTERS SET TO BINARY 0'S ;;
;; ;;
;; REGISTERS USED: NONE ;;
;; ;;
;;***************************************************************************;;
IRP RX,<R1,R2,R3,R4,R5,R6,R7,R8> ;REGISTER LIST
IFNB <RX> ;FOR EACH REGISTER IN LIST
XOR RX,RX ;CLEAR THE REGISTER
ENDIF ;END OF IFIDN
ENDM ;END OF IRP
ENDM ;MACRO END
CLS MACRO
LOCAL CLS1,CLSD
;;***************************************************************************;;
;; ;;
;; MACRO: CLS ;;
;; ;;
;; DESCRIPTION: CLEAR THE DISPLAY SCREEN ;;
;; ;;
;; PARAMATERS: NONE ;;
;; ;;
;; INPUT: NONE ;;
;; ;;
;; OUTPUT: NONE ;;
;; ;;
;; REGISTERS USED: AX,DX ;;
;; ;;
;;***************************************************************************;;
DISPLAY CLSD ;DISPLAY THE DOS2 STRING
JMP SHORT CLS1 ;GO AROUND THE STRING DATA
CLSD DB 1BH,'[2J$' ;DATA FOR DOS CALL
CLS1 LABEL NEAR
ENDM
COLOR MACRO FOREGROUND,BACKGROUND
LOCAL COLD,COL1
;;***************************************************************************;;
;; ;;
;; MACRO: COLOR ;;
;; ;;
;; DESCRIPTION: SETS DISPLAY COLOR ;;
;; ;;
;; PARAMATERS: FOREGROUND COLOR, BACKGROUND COLOR ;;
;; ;;
;; INPUT: NONE ;;
;; ;;
;; OUTPUT: NONE ;;
;; ;;
;; REGISTERS USED: AX,DX ;;
;; ;;
;;***************************************************************************;;
DISPLAY COLD ;DISPLAY THE COLOR STRING
JMP SHORT COL1 ;GO AROUND THE STRING
COLD DB 1BH,'[' ;START OF STRING
IFIDN <FOREGROUND>,<NORMAL> ;IF NORMAL REQUEST
DB '0' ;NORMAL FOREGROUND
ELSE
IFIDN <FOREGROUND>,<BOLD> ;IF BOLD REQUEST
DB '1' ;BOLD FOREGROUND
ELSE
IFIDN <FOREGROUND>,<UNDERSCORE> ;IF UNDERSCORED
DB '4' ;UNDERSCORE FOREGROUND
ELSE
IFIDN <FOREGROUND>,<BLINK> ;IF BLINK REQUEST
DB '5' ;BLINK FOREGROUND
ELSE
IFIDN <FOREGROUND>,<REVERSE> ;IF REVERSE REQUEST
DB '7' ;REVERSE VIDEO
ELSE
IFIDN <FOREGROUND>,<INVISIBLE> ;IF INVISABLE REQUEST
DB '8' ;INVISABLE (NO-SHOW)
ELSE
IFIDN <FOREGROUND>,<BLACK> ;IF BLACK REQUEST
DB '30' ;BLACK FOREGROUND
ELSE
IFIDN <FOREGROUND>,<RED> ;IF RED REQUEST
DB '31' ;RED FOREGROUND
ELSE
IFIDN <FOREGROUND>,<GREEN> ;IF GREEN REQUEST
DB '32' ;GREEN FOREGROUND
ELSE
IFIDN <FOREGROUND>,<YELLOW> ;IF YELLOW REQUEST
DB '33' ;YELLOW FOREGROUND
ELSE
IFIDN <FOREGROUND>,<BLUE> ;IF BLUE REQUEST
DB '34' ;BLUE FOREGROUND
ELSE
IFIDN <FOREGROUND>,<MAGENTA> ;IF MAGENTA REQUEST
DB '35' ;MAGENTA FOREGROUND
ELSE
IFIDN <FOREGROUND>,<CYAN> ;IF CYAN REQUEST
DB '36' ;CYAN FOREGROUND
ELSE
IFIDN <FOREGROUND>,<WHITE> ;IF WHITE REQUEST
DB '37' ;WHITE FOREGROUND
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IFNB <FOREGROUND> ;IF WE HAVE FOREGROUND...
IFNB <BACKGROUND> ;AND BACKGROUND COLORS
DB ';' ;PUT IN A SEPERATOR
ENDIF
ENDIF
IFIDN <BACKGROUND>,<BLACK> ;IF BLACK REQUEST
DB '40' ;BLACK BACKGROUND
ELSE
IFIDN <BACKGROUND>,<RED> ;IF RED REQUEST
DB '41' ;RED BACKGROUND
ELSE
IFIDN <BACKGROUND>,<GREEN> ;IF GREEN REQUEST
DB '42' ;GREEN BACKGROUND
ELSE
IFIDN <BACKGROUND>,<YELLOW> ;IF YELLOW REQUEST
DB '43' ;YELLOW BACKGROUND
ELSE
IFIDN <BACKGROUND>,<BLUE> ;IF BLUE REQUEST
DB '44' ;BLUE BACKGROUND
ELSE
IFIDN <BACKGROUND>,<MAGENTA> ;IF MAGENTA REQUEST
DB '45' ;MAGENTA BACKGROUND
ELSE
IFIDN <BACKGROUND>,<CYAN> ;IF CYAN REQUEST
DB '46' ;CYAN BACKGROUND
ELSE
IFIDN <BACKGROUND>,<WHITE> ;IF WHITE REQUEST
DB '47' ;WHITE BACKGROUND
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
COL1 LABEL NEAR ;SKIP AROUND DATA
ENDM
CURSOR MACRO FUNCTION,AREA
;;***************************************************************************;;
;; ;;
;; MACRO: CURSOR ;;
;; ;;
;; DESCRIPTION: SAVE OR SET CURRENT CURSOR TYPE, BLANK CURSOR ON SCREEN ;;
;; ;;
;; PARAMATERS: FUNCTION (SAVE,SET OR ERASE), DATA OR DATA ADDRESS ;;
;; ;;
;; INPUT: CURSOR START AND END LINES (SET ONLY) ;;
;; ;;
;; OUTPUT: CURSOR START AND END LINES (SAVE ONLY) ;;
;; ;;
;; REGISTERS USED: AX,CX (DS USED AND RESTORED) ;;
;; ;;
;;***************************************************************************;;
IFIDN <FUNCTION>,<ERASE> ;IF CURSOR ERASE REQUESTED
MOV AH,1 ;SET CURSOR MODE
MOV CX,0F0FH ;START AND END ON LINE 15
INT 10H ;GO DO A VIDEO INTERRUPT
ELSE
IFIDN <FUNCTION>,<SAVE> ;IF CURSOR SAVE REQUEST
PUSH DS ;SAVE DS
MOV AX,40H ;GET SEGMENT 40H IN AX
MOV DS,AX ;AND PUT IT IN DS
MOV CX,DS:60H ;GET CURRENT CURSOR MODE
POP DS ;RESTORE DS
MOV AREA,CX ;AND MOVE CURSOR MODE TO AREA
ELSE
IFIDN <FUNCTION>,<SET> ;IF CURSOR SET REQUEST
MOV CX,AREA ;GET CURSOR MODE IN CX
MOV AH,1 ;SET CURSOR MODE
INT 10H ;GO DO VIDEO INTERRUPT
ENDIF
ENDIF
ENDIF
ENDM
CVD MACRO DEST,ORG
LOCAL CVBP,CVDE
;;***************************************************************************;;
;; ;;
;; MACRO: CVD ;;
;; ;;
;; DESCRIPTION: CONVERT BINARY NUMBER TO ASCII DECIMAL NUMBER ;;
;; ;;
;; PARAMATERS: OUTPUT LABEL, INPUT LABEL ;;
;; ;;
;; INPUT: WORD BINARY NUMBER ;;
;; ;;
;; OUTPUT: 4 BYTE DECIMAL NUMBER ;;
;; ;;
;; REGISTERS USED: AX,BX,DX,DI ;;
;; ;;
;;***************************************************************************;;
IFDIF <ORG>,<AX> ;IF BINARY VALUE NOT IN AX
MOV AX,WORD PTR ORG ;MOVE ORIGIN TO AX
ENDIF
LEA DI,DEST ;GET ADDRESS OF DESTINATION
MOV BL,100D ;DIVISOR TO BL
DIV BL ;DIVIDE BY 100
MOV BH,AH ;SAVE REMAINDER IN BH
CALL CVDP ;CONVERT HIGHORDER TO DECIMAL
MOV AL,BH ;GET REMAINDER
CALL CVDP ;CONVERT LOW ORDER TO DECIMAL
JMP SHORT CVDE ;JUMP AROUND PROC
CVDP PROC NEAR
AAM ;CONVERT TO PACKED DECIMAL
OR AX,3030H ;CONVERT TO ASCII
MOV [DI],AH ;STORE HIGH ORDER BYTE
INC DI ;POINT TO NEXT BYTE
MOV [DI],AL ;STORE LOW ORDER BYTE
INC DI ;POINT TO NEXT BYTE
RET ;RETURN TO CALLER
CVDP ENDP
CVDE LABEL NEAR
ENDM
DISPLAY MACRO STRING
;;***************************************************************************;;
;; ;;
;; MACRO: DISPLAY ;;
;; ;;
;; DESCRIPTION: PRINT AN ASCII STRING ON THE SCREEN ;;
;; ;;
;; PARAMATERS: LABEL OF STRING TO BE PRINTED ;;
;; ;;
;; INPUT: ASCII STRING, ENDING WITH A $ ;;
;; ;;
;; OUTPUT: NONE ;;
;; ;;
;; REGISTERS USED: AX,DX ;;
;; ;;
;;***************************************************************************;;
LEA DX,STRING ;ADDRESS OF STRING TO DISPLAY
DOSCALL 9 ;DOS PRINT STRING FUNCTION
ENDM
DOSCALL MACRO FUNCTION
;;***************************************************************************;;
;; ;;
;; MACRO: DOSCALL ;;
;; ;;
;; DESCRIPTION: SET UP AND EXECUTE REQUESTED DOS FUNCTION CALL ;;
;; ;;
;; PARAMATERS: FUNCTION TO BE CALLED ;;
;; ;;
;; INPUT: NONE ;;
;; ;;
;; OUTPUT: NONE ;;
;; ;;
;; REGISTERS USED: AX ;;
;; ;;
;;***************************************************************************;;
MOV AH,FUNCTION ;GET FUNCTION IN AH
INT 21H ;DOS CALL
ENDM
GETDATE MACRO DEST,TYPE
LOCAL GDTE,GTDP
;;***************************************************************************;;
;; ;;
;; MACRO: GETDATE ;;
;; ;;
;; DESCRIPTION: GETS CURRENT DATE INTO DESTINATION ;;
;; ;;
;; PARAMATERS: DESTINATION, TYPE OF DATE (CHAR OR BIN) ;;
;; ;;
;; INPUT: NONE ;;
;; ;;
;; OUTPUT: MM/DD/YY (CHAR) OR MDYY (BIN) ;;
;; ;;
;; REGISTERS USED: AX,BX,CX,DX,DI ;;
;; ;;
;;***************************************************************************;;
IFIDN <TYPE>,<CHAR> ;IF CHARACTER REQUEST
DOSCALL 2AH ;GET DATE FUNCTION CALL
LEA DI,DEST ;GET ADDRESS OF DESTINATION
MOV AL,DH ;GET MONTH IN AL
CALL GDTP ;CONVERT BYTE TO ASCII
MOV WORD PTR [DI],'/' ;MOVE IN /
INC DI ;POINT TO NEXT BYTE
MOV AL,DL ;GET DAY IN AL
CALL GDTP ;CONVERT BYTE TO ASCII
MOV WORD PTR [DI],'/' ;MOVE IN /
INC DI ;POINT TO NEXT BYTE
MOV AX,CX ;GET YEAR IN AL
MOV BL,100D ;MOVE IN DIVISOR
DIV BL ;DIVIDE BY 100
MOV AL,AH ;REMAINDER TO AL
CALL GDTP ;CONVERT BYTE TO ASCII
JMP SHORT GDTE ;JUMP AROUND PROC
GDTP PROC NEAR
AAM ;CONVERT TO PACKED DECIMAL
ADD AX,3030H ;CONVERT TO ASCII
MOV BYTE PTR [DI],AH ;STORE HIGH ORDER BYTE
INC DI ;POINT TO NEXT BYTE
MOV BYTE PTR [DI],AL ;STORE LOW ORDER BYTE
INC DI ;POINT TO NEXT BYTE
RET ;RETURN TO CALLER
GDTP ENDP
GDTE LABEL NEAR
ELSE
IFIDN <TYPE>,<BIN> ;IF BINARY REQUEST
DOSCALL 2AH ;GET CURRENT DATE
MOV BYTE PTR DEST,DH ;MOVE MONTH TO DESTINATION
MOV BYTE PTR [DEST+1],DL ;MOVE DAT TO DESTINATION
MOV WORD PTR [DEST+2],CX ;MOVE YEAR TO DESTINATION
ENDIF
ENDIF
ENDM
GETTIME MACRO DEST,TYPE
LOCAL GTMP,GTME
;;***************************************************************************;;
;; ;;
;; MACRO: GETTIME ;;
;; ;;
;; DESCRIPTION: GET CURRENT TIME INTO DESTINATION ;;
;; ;;
;; PARAMATERS: DESTINATION, TYPE (CHAR OR BIN) ;;
;; ;;
;; INPUT: NONE ;;
;; ;;
;; OUTPUT: HH:MM:SS:HH (CHAR) OR HMSH (BIN) ;;
;; ;;
;; REGISTERS USED: AX,BX,CX,DX,DI ;;
;; ;;
;;***************************************************************************;;
IFIDN <TYPE>,<CHAR> ;IF CHARACTER REQUEST
DOSCALL 2CH ;GET CURRENT TIME
LEA DI,DEST ;GET DESTINATION ADDRESS
MOV AL,CH ;MOVE HOURS TO AL
CALL GTMP ;AND CONVERT TO ASCII
MOV WORD PTR [DI],':' ;PUT IN :
INC DI ;POINT TO NEXT BYTE
MOV AL,CL ;MOVE MINUTES TO AL
CALL GTMP ;AND CONVERT TO ASCII
MOV WORD PTR [DI],':' ;PUT IN :
INC DI ;POINT TO NEXT BYTE
MOV AL,DH ;MOVE SECONDS TO AL
CALL GTMP ;AND CONVERT TO ASCII
MOV WORD PTR [DI],':' ;PUT IN :
INC DI ;POINT TO NEXT BYTE
MOV AL,DL ;MOVE HUNDRETHS TO AL
CALL GTMP ;AND CONVERT TO ASCII
JMP SHORT GTME ;JUMP AROUND PROC
GTMP PROC NEAR
AAM ;CONVERT TO PACKED DECIMAL
ADD AX,3030H ;CONVERT TO ASCII
MOV BYTE PTR [DI],AH ;STORE HIGH ORDER BYTE
INC DI ;POINT TO NEXT BYTE
MOV BYTE PTR [DI],AL ;STORE LOW ORDER BYTE
INC DI ;POINT TO NEXT BYTE
RET ;RETURN TO CALLER
GTMP ENDP
GTME LABEL NEAR
ELSE
IFIDN <TYPE>,<BIN> ;IF REQUEST FOR BINARY TIME
DOSCALL 2CH ;GET CURRENT TIME
MOV BYTE PTR DEST,CH ;MOVE HOURS TO DESTINATION
MOV BYTE PTR DEST+1,CL ;MOVE MINUTES TO DESTINATION
MOV BYTE PTR DEST+2,DH ;MOVE SECONDS TO DESTINATION
MOV BYTE PTR DEST+3,DL ;MOVE HUNDRETHS TO DESTINATION
ENDIF
ENDIF
ENDM
LOCATE MACRO ROW,COLUMN
LOCAL LOC1,LOCD
;;***************************************************************************;;
;; ;;
;; MACRO: LOCATE ;;
;; ;;
;; DESCRIPTION: POSITION CURSOR ON SCREEN ;;
;; ;;
;; PARAMATERS: ROW, COLUMN ;;
;; ;;
;; INPUT: BINARY ROW AND COLUMN LOCATION, IF NOT IN MACRO CALL ;;
;; ;;
;; OUTPUT: NONE ;;
;; ;;
;; REGISTERS USED: AX,DX ;;
;; ;;
;;***************************************************************************;;
MOV AL,ROW ;GET BINARY ROW
AAM ;CONVERT TO PACKED DECIMAL
ADD AX,3030H ;CONVERT TO ASCII
MOV BYTE PTR [LOCD+2],AH ;HIGH ORDER ROW TO STRING
MOV BYTE PTR [LOCD+3],AL ;LOW ORDER ROW TO STRING
CLEAR AH ;CLEAR AH AGAIN
MOV AL,COLUMN ;GET COLUMN IN AL
AAM ;CONVERT TO PACKED DECIMAL
ADD AX,3030H ;CONVERT TO ASCII
MOV BYTE PTR [LOCD+5],AH ;HIGH ORDER COLUMN TO STRING
MOV BYTE PTR [LOCD+6],AL ;LOW ORDER COLUMN TI STRING
DISPLAY LOCD ;POSITION THE CURSOR
JMP SHORT LOC1 ;JUMP AROUND STRING
LOCD DB 1BH,'[ ; H$' ;POSITION CURSOR STRING
LOC1 LABEL NEAR
ENDM
MOVE MACRO TO,FROM,LNGTH
LOCAL MOVELP
;;***************************************************************************;;
;; ;;
;; MACRO: MOVE ;;
;; ;;
;; DESCRIPTION: MULTIPLE BYTE MOVE ;;
;; ;;
;; PARAMATERS: TO LOCATION, FROM LOCATION, LENGTH (OPT.) ;;
;; ;;
;; INPUT: SOURCE STRING ;;
;; ;;
;; OUTPUT: DESTINATION STRING ;;
;; ;;
;; REGISTERS USED: CX,SI,DI (ES ASSUMED POINTING TO DESTINATION SEGMENT) ;;
;; ;;
;;***************************************************************************;;
CLEAR CH ;CLEAR LENGTH REG
IFB <LENGTH> ;IF NO LENGTH REQUESTED
MOV CX,LENGTH TO ;USE LENGTH OF TO STRING
ELSE ;IF LENGTH REQUESTED
MOV CX,LNGTH ;USE LENGTH IN MACRO
ENDIF
IFDIF <TO>,<DI> ;IF DI NOT SPECIFIED FOR TO
LEA DI,TO ;LOAD TO ADDRESS INTO DI
ENDIF
IFDIF <FROM>,<SI> ;IF SI NOT SPECIFIED FOR FROM
LEA SI,FROM ;LOAD FROM ADDRESS INTO SI
ENDIF
CLD ;CLEAR DIRECTION FLAG
REP MOVSB ;MOVE THE DATA
ENDM
RESTORE MACRO R1,R2,R3,R4,R5,R6,R7,R8,R9,R10
;;***************************************************************************;;
;; ;;
;; MACRO: RESTORE ;;
;; ;;
;; DESCRIPTION: RESTORE REGISTERS FROM STACK ;;
;; ;;
;; PARAMATERS: REGISTERS TO BE RESTORED (IN REVERSE ORDER) ;;
;; ;;
;; INPUT: NONE ;;
;; ;;
;; OUTPUT: RESTORED REGISTERS ;;
;; ;;
;; REGISTERS USED: NONE ;;
;; ;;
;;***************************************************************************;;
IRP RX,<R10,R9,R8,R7,R6,R5,R4,R3,R2,R1> ;REPEAT FOR EACH PARM
IFNB <RX> ;IF THIS PARM NOT BLANK
POP RX ;POP THE REGISTER
ENDIF ;END IFNB
ENDM ;END IRP
ENDM
SAVE MACRO R1,R2,R3,R4,R5,R6,R7,R8,R9,R10
;;***************************************************************************;;
;; ;;
;; MACRO: SAVE ;;
;; ;;
;; DESCRIPTION: SAVE REGISTERS ON THE STACK ;;
;; ;;
;; PARAMATERS: REGISTERS TO BE SAVED ;;
;; ;;
;; INPUT: NONE ;;
;; ;;
;; OUTPUT: REGISTERS SAVED ON STACK ;;
;; ;;
;; REGISTERS USED: NONE ;;
;; ;;
;;***************************************************************************;;
IRP RX,<R1,R2,R3,R4,R5,R6,R7,R8,R9,R10> ;REPEAT FOR EACH PARM
IFNB <RX> ;IF THIS PARM NOT BLANK
PUSH RX ;SAVE THE REGISTER
ENDIF ;END IFNB
ENDM ;END IRP
ENDM
SETINT MACRO INTERRUPT,ROUTINE
;;***************************************************************************;;
;; ;;
;; MACRO: SETINT ;;
;; ;;
;; DESCRIPTION: SET INTERRUPT VECTOR ;;
;; ;;
;; PARAMATERS: INTERRUPT VECTOR, INTERRUPT ROUTINE ADDRESS ;;
;; ;;
;; INPUT: NONE ;;
;; ;;
;; OUTPUT: NONE ;;
;; ;;
;; REGISTERS USED: AX,DX ;;
;; ;;
;;***************************************************************************;;
MOV AL,INTERRUPT ;GET INTERRUPT TO BE SET
LEA DX,ROUTINE ;GET ADDRESS OF ROUTINE
DOSCALL 25H ;CALL DOS
ENDM
SETTIME MACRO HOURS,MINUTES,SECONDS,HUNDRETHS
;;***************************************************************************;;
;; ;;
;; MACRO: SETTIME ;;
;; ;;
;; DESCRIPTION: SET CURRENT TIME ;;
;; ;;
;; PARAMATERS: HOURS, MINUTES, SECONDS,HUNDRETHS ;;
;; ;;
;; INPUT: TIME TO BE SET ;;
;; ;;
;; OUTPUT: NONE ;;
;; ;;
;; REGISTERS USED: AX,CX,DX ;;
;; ;;
;;***************************************************************************;;
IFNB <HOURS> ;IF HOURS SPECIFIED
MOV CH,HOURS ;MOVE HOURS TO CH
ELSE ;IF HOURS NOT SPECIFIED
CLEAR CH ;CLEAR CH
ENDIF
IFNB <MINUTES> ;IF MINUTES SPECIFIED
MOV CL,MINUTES ;MOVE MINUTES TO CL
ELSE ;IF MINUTES NOT SPECIFIED
CLEAR CL ;CLEAR CL
ENDIF
IFNB <SECONDS> ;IF SECONDS SPECIFIED
MOV DH,SECONDS ;MOVE SECONDS TO DH
ELSE ;IF SECONDS NOT SPECIFIED
CLEAR DH ;CLEAR DH
ENDIF
IFNB <HUNDRETHS> ;IF HUNDRETHS SPECIFIED
MOV DL,HUNDRETHS ;MOVE HUNDRETHS TO DL
ELSE ;IF HNDRETHS NOT SPECIFIED
CLEAR DL ;CLEAR DL
ENDIF
DOSCALL 2DH ;CALL DOS TO SET TIME
ENDM