Electronics
Btrieve
Motorcycling
Software

CHAPTER 9

Assembly Language Linkage

9.1 OVERVIEW

NOTE: This section assumes that the designer has an understanding of the architecture and assembly language of the MCS-51 Microcontroller family!!!

MCS BASIC-52 contains a complete library of routines that can easily be accessed with assembly language CALL instructions. The advantage of using assembly language is that it offers a significant improvement in execution speed relative to interpreted BASIC. In order to successfully interface MCS BASIC-52 with an assembly language program, the software designer must be aware of a few simple facts.

READ THIS CAREFULLY!!!

1. MCS BASIC-52 uses REGISTER BANKS 0, 1, and 2 (RB0, RB1, and RB2). REGISTER BANK 3 (RB3) is never used except during a PGM statement. RB3 is designated the USER REGISTER BANK and the users can do whatever they want to with REGISTER BANK 3 (RB3) and MCS BASIC-52 will never alter the contents of this REGISTER BANK except during the execution of a PGM statement. The contents of REGISTER BANK 3 (RB3) can be changed by executing a DBY ([expr]) = [0 to 255] statement. Where the [expr] evaluates to a number between 24 (18H) and 31 (1FH) inclusive. In addition, INTERNAL MEMORY LOCATIONS 32 (20H) and 33 (21 H) are also NEVER used by MCS BASIC-52. These two BIT and/or BYTE addressable locations are specifically reserved for assembly language programs.

2. MCS BASIC-52 uses REGISTER BANK 0 (RB0) as the WORKING REGISTER FILE. Whenever assembly language is used to access MCS BASlC-52's routines, the WORKING REGISTER FILE, REGISTER BANK 0 (RB0) MUST BE SELECTED!!! This means that the USER MUST MAKE SURE THAT REGISTER BANK 0 (RB0) IS SELECTED BEFORE CALLING ANY OF MCS BASlC-52's ROUTINES. This is done simply by setting BITS 3 and 4 in the PSW equal to ZERO. If this is not done, MCS BASIC-52 will "KICK OUT" the USER and NO operation will be performed. When an ASSEMBLY LANGUAGE program is accessed by using the MCS BASlC-52's CALL instruction, REGISTER BANK 0 (RB0) will always be selected. So unless the user selects REGlSTER BANK 3 (RB3) in assembly language, it is NOT NECESSARY to change the designated REGISTER BANK.

3. ALWAYS ASSUME THAT MCS BASIC-52 DESTROYS THE CONTENTS OF THE WORKING REGISTER FILE AND THE DPTR, UNLESS OTHERWISE STATED IN FOLLOWING DOCU- MENTATION.

4. Certain routines in MCS BASIC-52 require that REGISTERS be initialized BEFORE the user CALLS that specific ROUTINE. These registers are ALWAYS in the WORKING REGISTER FILE, REGISTER BANK 0 (RB0).

5. Certain routines in MCS BASIC-52 return the result of an operation in a register or registers. The result registers are ALWAYS in the WORKING REGISTER FILE, REGISTER BANK 0, (RB0).

6. MCS BASIC-52 loads the INTERNAL STACK POINTER (SPECIAL FUNCTION REGISTER- SP) with the value that is in INTERNAL MEMORY LOCATION 62 (3EH). MCS BASIC-52 initializes INTERNAL MEMORY LOCATION 62 (3EH) by writing a 77 (4DH) to this location after a hardware RESET. MCS BASIC-52 does NOT use any memory beyond 77 (4DH) for anything EXCEPT STACK SPACE. If the user wants to ALLOCATE some additional intemal memory for their application, this is done by changing the contents of INTERNAL MEMORY LOCATION 62 (3EH) to a value that is GREATER than 77 (4DH). This will allocate the INTERNAL MEMORY LOCATIONS from 77 (4DH) to the value that is placed in INTERNAL MEMORY LOCATION 62 (3EH) to the user. As a guideline, it is a good idea to allow at least 48 (30H) bytes of stack space for MCS BASIC-52. The bad news about reducing the stack space is that it will reduce the amount of nested parentheses that MCS BASIC-52 can evaluate in an expression [expr]. This will either cause a I-STACK ERROR or will cause a fatal CPU "crash." Use caution and DON'T allocate more memory than you need.

EXAMPLE OF THE EFFECTS OF ALTERING THE STACK ALLOCATION:

COMMENTS >PRINT DBY(62) AFTER RESET INTERNAL MEMORY LOCATION 6 77 CONTAINS A 77 >PRINT (1*(2*(3))) BASIC HAS NO PROBLEM EVALUATING 3 LEVELS 6 OF NESTED PARENRHESIS >DBY(62)=230 NOW ALLOCATE 255-230 = 25 BYTES OF STACK SPACE TO BASIC, REMEMBER, THE STACK ON >PRINT (1*(2*(3))) THE 80S2AH GROWS "UP" ERROR: I-STACK BASIC CANNOT EVALUATE THIS EXPRESSION READY BECAUSE IT DOES NOT HAVE ENOUGH STACK >DBY(62)=210 NOW ALLOCATE 255-210 = 45 BYTES OF STACK SPACE TO BASIC >PRINT (1*(2*(3))) THE I-STACK ERROR GOES AWAY 6

7. Throughout this section a 16-BIT REGISTER PAIR is designated-Rx:Ry, where Rx is the most sig- nificant byte and Ry is the least significant byte.

EXAMPLE:

R3:R1 - R3=MOST SIGNIFICANT BYTE. R1=LEAST SIGNIFICANT BYTE

9.2 GENERAL PURPOSE ROUTINES

Accessing MCS BASIC-52 routines with assembly language is easy. The user just loads the ACCUMU- LATOR with a specific value and CALLS LOCATION 48 (30H). The value placed in the ACCUMULATOR determines what operation will be performed. Unless otherwise stated, the CONTENTS of the DPTR and REGISTER BANK 0 (RB0) will ALWAYS be altered when calling these routines. The generalized form for accessing MCS BASlC-52's routines is as follows:

ANL PSW,#11100111B ;make sure RB0 is selected MOV A,#OPBYTE ;load the instruction CALL 30H ;execute the instruction

The value of OPBYTE determines what operation will be performed. The following operations can be performed:

OPBYTE = 0 (00H) RETURN TO COMMAND MODE

This instruction causes MCS BASIC-52 to enter the COMMAND MODE. Control of the CPU is handed back to the MCS BASIC-52 interpreter and BASIC will respond by outputting a READY and a PROMPT character (>).

OPBYTE = 1 (01H) POP ARGUMENT STACK AND PUT VALUE IN R3:R1

This instruction converts the value that is on the ARGUMENT STACK to a 16 BIT BINARY INTEGER and returns the BINARY INTEGER in registers R3 (high byte) and R1 (low byte) of REGISTER BANK 0 (RB0). The ARGUMENT STACK gets popped after this instruction is executed. If the value on the ARGUMENT STACK cannot be represented by a 16-BIT BINARY NUMBER (i.e. it is NOT between 0 and 65535 (0FFFFH) inclusive), BASIC WILL TRAP THE ERROR and print a BAD ARGUMENT ERROR MESSAGE. The BINARY VALUE returned is TRUNCATED, NOT ROUNDED.

EXAMPLE:

BASIC PROGRAM - 10 PUSH 20 20 CALL 5000H ASSEMBLY LANGUAGE PROGRAM - ORG 5000H MOV A.#01H ;load opbyte CALL 30H ;RB0 still selected ; ; at this point R3 (of RB0) = 01H ; and R1 (of RB0) = 04H ; so, R3:R1 = 260, which was the value ; that was placed on the ARGUGENT STACK

COMMENTS ON THE NEXT TWO INSTRUCTIONS:

The next two instructions permit the user to transfer floating point numbers between an assembly language program and MCS BASIC-52. The user provides the address where a floating point number is stored or will be stored in a 16-bit REGISTER PAIR. Depending on the operation requested, the floating point numbers are either PUSHED ON or POPPED OFF MCS BASlC-52's ARGUMENT STACK. This in- struction permits the user to keep track of variables in assembly language and bypass the relatively slow procedure BASIC must follow.

As mentioned earlier, when a floating point number is PUSHED onto the ARGUMENT STACK, the ARGUMENT STACK POINTER is decremented by a count of 6. This is because a floating point number requires 6 bytes of RAM storage. Although it may seem confusing to the novice, the LAST value placed on the ARGUMENT STACK is referred to as the value on the TOP of the ARGUMENT STACK, even though it is on the BOTTOM of the STACK relative to the sequential numbering of memory addresses. No one knows why this is so.

The ARGUMENT STACK resides in EXTERNAL RAM MEMORY LOCATIONS 301 (12DH) through 510 (1FEH). The lower BYTE of the ARGUMENT STACK POINTER resides in INTERNAL MEMORY LOCATION 9 (09H). MCS BASIC-52 always assumes that the upper BYTE (higher order address) of the ARGUMENT STACK POINTER is 1 (01H). The software designer can use this information, along with the next two instructions to perform operations like copying the stack.

OPBYTE = 2 (02H) PUSH THE FLOATING POINT NUMBER ADDRESSED BY REGISTER
PAIR R2:R0 ONTO THE ARGUMENT STACK.

R2 and R0 (in REGISTER BANK 0, RB0) contain the ADDRESS (R2 = high byte, R0 = low byte) of the location where the floating point number is stored. After this instruction is executed the floating point number that the REGISTER PAIR R2:R0 points to is PUSHED onto the TOP of the ARGUMENT STACK. The ARGUMENT STACK POINTER automatically gets DECREMENTED, by a count of 6, when the value is placed on the stack. A floating point number in MCS BASIC-52 requires 6 BYTES of RAM storage. The register Pair R2:R0 points to the MOST SIGNIFICANT BYTE of the floating point number and is DECREMENTED BY 6 after the CALL instruction is executed. So, if R2:R0 = 7F18H before this instruction was executed, it would equal 7F12H after this instruction was executed.

OPBYTE = 3 (03H) POP THE ARGUMENT STACK AND SAVE THE FLOATING POINT
NUMBER IN THE LOCATION ADDRESSED BY R3:R1.

The TOP of the ARGUMENT STACK is moved to the location pointed to by the REGISTER PAIR R3:R1(R3 = high byte, R1 = low byte, in REGISTER BANK 0, RB0). The ARGUMENT STACK POINTER is automatically INCREMENTED BY 6. Just as in the previous PUSH instruction, the REG- ISTER PAIR R3:R1 points to the MOST SIGNIFICANT BYTE of the floating point number and is DECREMENTED BY 6 after the CALL instruction is executed.

EXAMPLE OF USER PUSH AND POP:

BASIC PROGRAM: >5 REM PUT 100 AND 200 ON THE ARGUMENT STACK >10 PUSH 100,200 >15 REM CALL THE USER ROUTINE TO SAVE NUMBERS >20 CALL 5000H >25 REM CLEAR THE STACK >30 CLEARS >35 REM USE ASM TO PUT NUMBERS BACK ON STACK >40 CALL 5010H >50 POP A,B >60 PRINT A,B >RUN 100 200 READY ASM PROGRAM: ORG 5000H MOV R3,#HIGH USER SAVE ; LOAD POINTERS TO WHERE MOV R1.#LOW USER_SAVE ; NUMBERS WILL BE SAVED. MOV A,#03H ; LOAD OPBYTE CALL 30H ; SAVE ONE NUMBER MOV A,#03H ; LOAD OPBYTE AGAIN CALL 30H ; SAVE ANOTHER NUMBER RET ; BACK TO BASIC ; ORG 5010H MOV R2,#HIGH USER_SAVE ;LOAD ADDRESS WHERE MOV R0,#LOW USER_SAVE ;NUMBERS ARE STORED MOV A,#02H ;LOAD OPBYTE CALL 30H ;PUT ONE NUMBER ON STACK MOV A,#02H ;LOAD OPBYTE CALL 30H ;NEXT NUMBER ON STACK RET ;BACK TO BASIC

OPBYTE = 4 (04H) PROGRAM A PROM USING R3:R1 AS THE SOURCE ADDRESS
POINTER, R2:R0 AS THE DESTINATION (PROM) ADDRESS POINTER, AND R7:R6 AS THE
BYTE COUNTER.

This instruction assumes that the DATA to be programmed into a PROM is stored in external memory and that the REGISTER PAIR R3:R1 (in RB0) contains the address of this external memory. REGISTER PAIR R7:R6 contains the total number of bytes that are to be programmed. The PROM is programmed sequentially and everytime a byte is programmed the REGISTER PAIR R7:R6 is decremented and the REGISTER PAIRS R3:R1 and R2:R0 are incremented. Programming continues until R7:R6 equals ZERO. The REGISTER PAIR R2:R0 must be initialized with the desired ADDRESS of the EPROM to be programmed MINUS 1. This may sound strange, but that is the way it works. So, if you wanted to program an EPROM starting at address 9000H, with the data stored in address 0D00H and you wanted to program 500 BYTES, then the registers would be set up as follows: R2:R0 = 8FFFH, R3:R1 = 0D00H, and R7:R6 = 01F4H (500 decimal). You would then put a 4 (04H) in the ACC and CALL location 30H.

NOTE: In Version 1.0, if an ERROR OCCURS DURING PROGRAMMING, MCS BASIC-52 WILL TRAP THE ERROR AND ENTER THE COMMAND MODE. The user cannot handle errors that occur during the EPROM programming operation!!!!

In Version 1.1, programming errors will only be trapped if the MCS BASIC-52 device is in the COMMAND MODE. If the MCS BASIC-52 device is in the run mode, control will be passed back to the user. The user must then examine registers R6 and R7. If R6 = R7 = 0, then the programming operation was successfully completed, if these registers do not equal zero then registers R2:R0 contain the address of the EPROM location that failed to program. This feature in Version 1.1 permits the user to program EPROMS in embedded applications and manage errors, should they occur in the programming process, without trapping to the command mode.

In addition to setting up the pointers previously described, the user must also initialize the INTERNAL MEMORY locations that control the width of the programming pulse. This gives the user complete control over this critical prom programming parameter. The internal memory locations that must be initialized with this information are 64 (40H) and 65 (41H). These locations are treated as a 16 bit register pair with location 64 (40H) designated as the most significant byte and location 65 (41H) as the least significant byte. Locations 64 (40H) and 65 (41H) are loaded into TH1 (TIMER1 high byte) and TL1 (TIMER1 low byte) respectively. The width of the programming pulse, in microseconds is determined by the following equation:

WIDTH = (65536-256*DBY(64)+DBY(65))*12/XTAL microseconds

conversely;

DBY(64):DBY(65) = 65536-WIDTH*XTAL/12

The proper values for the "normal" 50 millisecond programming algorithm and the 1 millisecond "INTELligent" algorithm are calculated and stored by MCS BASIC-52 in external memory locations 296:297 ( 128H: 129H) and 298:299 ( 12AH: 12BH) respectively. If the user wants to use the pre-calculated values the statements DBY(64) = XBY(296) and DBY(65) = XBY(297) may be used to initialize the prom programming width for the normal algorithm and the statements DBY(64) = XBY(298) and DBY(65) = XBY(299) can be used to initialize for the INTELligent algorithm.

To select the "INTELLIGENT" EPROM PROGRAMMING algorithm the directly addressable BIT 51 (33H) MUST be set to 1 before the EPROM PROGRAMMING routine is called. The "STANDARD" 50 ms EPROM PROGRAMMING algorithm is selected by CLEARING BIT 51 (33H) (i.e. BIT 51 = 0) before calling the EPROM PROGRAMMING routine. The directly addressable BIT 51 is located in internal memory location 38.3 (26.3H) (BIT 3 of BYTE 38 (26H) in internal memory). This BIT can be SET or CLEARED by the BASIC STATEMENTS DBY(38) = DBY(38).0R.08H to SET and DBY(38)=DBY(38).AND.0F7H to CLEAR. Of course, the user can set or clear this bit in assembly language with a SETB 51 or CLR 51 instruction.

The user must also turn on the EPROM PROGRAMMING voltage BEFORE calling the EPROM PRO- GRAMMING routine. This is done by CLEARING BIT P1.5, the fifth BIT on PORT 1. This too can be done in BASIC with a PORT1 = PORT1.AND.0DFH instruction or in assembly language with a CLR P1.5 instruction. The user must also set this bit when the PROM PROGRAMMING procedure is complete.

This instruction assumes that the hardware surrounding the MCS BASIC-52 device is the same as the suggestions in the EPROM PROGRAMMING chapter of this manual.

OPBYTE = 5 (05H) INPUT A STRING OF CHARACTERS AND STORE IN THE BASIC INPUT BUFFER.

This instruction inputs a line of text from the console device and saves the information in the MCS BASIC- 52's input buffer. MCS BASlC-52's input buffer begins at EXTERNAL MEMORY LOCATION 7 (0007H). All of the line editing features available in MCS BASIC-52 are implemented in this instruction. If a control- C is typed during the input process, MCS BASIC-52 will trap back into the command mode. A carriage return (cr) terminates the input procedure.

OPBYTE = 6 (06H) OUTPUT THE STRING OF CHARACTERS POINTED TO BY THE REGISTER PAIR R3:R1 TO THE CONSOLE DEVICE.

This instruction is used to OUTPUT a string of characters to the console device. R3:R1 contains the initial address of this string. The string can either be stored in PROGRAM MEMORY or EXTERNAL DATA MEMORY. If BIT 52 (34H) (which is BIT 4 of internal RAM location 38 (26H)) is set, the output will be from PROGRAM MEMORY. If BIT 52 is cleared, the output will be from EXTERNAL DATA MEMORY. The DATA stored in MEMORY is sent out to the console device one byte at a time and the memory pointer is incremented. The output is stopped when a termination character is read. The termination character for PROGRAM MEMORY and EXTERNAL DATA MEMORY are different. The termination character for EXTERNAL DATA MEMORY is a (cr) 0DH. The termination character for PROGRAM MEMORY is a " or 22H.

OPBYTE = 7 (07H) OUTPUT A CARRIAGE RETURN-LINE FEED SEQUENCE TO THE CONSOLE DEVICE.

Enough said.

OPBYTE = 128 (80H) OUTPUT THE CHARACTER IN R5 (REGISTER BANK 0) TO THE CONSOLE DEVICE.

This routine takes the character that is in R5 (register bank 0) and directs it to the console device. Any console device may be selected (i.e. U0 or UI or the software serial port).

OPBYTE = 144 (90H) OUTPUT THE NUMBER ON THE TOP OF ARGUMENT STACK TO THE CONSOLE DEVICE.

The floating point number that is on the top of the argument stack is outputted to the console device. The FORMAT is determined by the USING statement. The argument stack is POPPED after the output operation.

OPBYTE = 154 (9AH) THE 16 BIT NUMBER REPRESENTED BY REGISTER PAIR R2:R0 IS PUSHED ON THE ARGUMENT STACK.

This instruction converts the 16 bit register pair R2:R0 to a floating point number and pushes this number onto the argument stack. This instruction is the converse of the OPBYTE = 1 instruction.

9.3 UNARY OPERATORS

The next group of instructions perform an operation on the number that is on the TOP of the ARGUMENT STACK. If the TOP of the ARGUMENT STACK is represented by the symbol [TOS], then the following instructions would take the general form:

[TOS] < OP [TOS]

Where OP is one of the following operators:

OPBYTE = 24 (18H)--ABSOLUTE VALUE

[TOS] < ABS([TOS]). The [TOS] is replaced by the absolute value of [TOS].

OPBYTE = 25 (19H)--INTEGER

[TOS] < INT([TOS]). The [TOS] is replaced by the integer portion of [TOS].

OPBYTE = 26 (1AH)--SIGN

[TOS] < SGN([TOS]). If [TOS] > 0 then [TOS] = 1, if [TOS] = 0 then [TOS] = 0, and if [TOS] < O then [TOS] = -1.

OPBYTE = 27 (1BH)--ONE'S COMPLEMENT

[TOS] < NOT([TOS]). [TOS] must be a valid integer.

OPBYTE = 28 (1CH)--COSINE OPERATOR

[TOS] < COS([TOS]). [TOS] must be between +-200000.

OPBYTE = 29 (1DH)--TANGENT OPERATOR

[TOS] < TAN([TOS]). [TOS] must be between +- 200000 and [TOSl cannot equal PI/2, 3*PI/2, 5*PI/2..... (2*N+1)*PI/2.

OPBYTE = 30 (1EH)--SINE OPERATOR

[TOSl < SIN([TOS]). [TOS] must be between +-200000.

OPBYTE = 31 (1FH)--SQUARE ROOT

[TOS] < SQR ([TOS]). [TOS] must be >= 0.

OPBYTE = 32 (20H)--CBY OPERATOR

[TOS] < CBY ([TOS]). [TOS] must be a valid integer.

OPBYTE = 33 (21H)--E TO THE [TOS] OPERATOR

[TOS] < e(2.7182818)**[TOS]. e is raised to the [TOS] power.

OPBYTE = 34 (22H)--ATN OPERATOR

[TOS] < ATN([TOS]). Arctangent, the value returned is between +- PI/2.

OPBYTE = 35 (23H)--LOG OPERATOR (natural LOG)

[TOS] < LOG([TOS])--[TOS] must be > 0.

OPBYTE = 36 (24H)--DBY OPERATOR

[TOS] < DBY([TOS]). [TOS] must be between 0 and 255 inclusive.

OPBYTE = 37 (25H)--XBY OPERATOR

[TOS] < XBY([TOS]). [TOS] must be a valid integer.

9.4 SPECIAL OPERATORS

The next group of instructions place a value on the stack. The value placed on the stack is as follows:

OPBYTE = 38 (26H)--PI

[TOS] = PI. PI (3.1415926) is placed on the [TOS].

OPBYTE = 39 (27H)--RND

[TOS] = RND. A random number is placed on the [TOS].

OPBYTE = 40 (28H)--GET

[TOS] = GET. The value of the SPECIAL FUNCTION OPERATOR, GET is put on the [TOS].

OPBYTE = 41 (29H)--FREE

[TOS] = FREE. The value of the SYSTEM CONTROL VALUE, FREE is put on the [TOS].

OPBYTE = 42 (2AH)--LEN

[TOS] = LEN. The value of the SYSTEM CONTROL VALUE, LEN is put on the [TOS].

OPBYTE = 43 (2BH)--XTAL

[TOS] = XTAL. The value of the SPECIAL FUNCTION OPERATOR, XTAL is put on the [TOS].

OPBYTE = 44 (2CH)--MTOP

[TOS] = MTOP. The value of the SYSTEM CONTROL VALUE, MTOP is put on the [TOS].

OPBYTE = 45 (2DH)--TIME

[TOS] = TIME. The value of the SPECIAL FUNCTION OPERATOR, TIME is put on the [TOS].

OPBYTE = 46 (2EH)--IE

[TOS] = IE The value of the IE register is put on the [TOS].

OPBYTE = 47 (2FH)--IP

[TOS] = IP. The value of the IP register is put on the [TOS].

OPBYTE = 48 (30H)--TIMER0

[TOS] = TIMER0. The value of TIMER0 (TH0:TL0) is put on the [TOS].

OPBYTE = 49(31H)--TIMER1

[TOS] = TIMERI. The value of TIMERI (TH1:TL1) is put on the [TOS].

OPBYTE = 50 (32H)--TIMER2

[TOS] = TIMER2. The value of TIMER2 (TH2:TL2) is put on the [TOS].

OPBYTE = 51 (33H)--T2CON

[TOS] = T2CON. The value of the T2CON register is put on the [TOS].

OPBYTE = 52 (34H)--TCON

[TOS] = TCON. The value of the TCON register is put on the [TOS].

OPBYTE = 53 (35H)--TMOD

[TOS] = TMOD. The value of the TMOD register is put on the [TOS].

OPBYTE = 54 (36H)--RCAP2

[TOS] = RCAP2. The value of the RCAP2 registers (RCAP2H:RCAP2L) is put on the [TOS].

OPBYTE = 55 (37H)--PORT1

[TOS] = PORT1. The value of the PORT1 (P1) pins is placed on the [TOS].

OPBYTE = 56 (38H)--PCON

[TOS] = PCON. The value of the PCON register is put on the [TOS].

9.5 DUAL OPERAND OPERATORS

The next group of instructions assume that TWO values are on the ARGUMENT STACK. If number on the TOP of the ARGUMENT STACK is represented by the symbol [TOS] and the number NEXT to TOP of the ARGUMENT STACK is represented by the symbol [NxTOS] and the ARGUMENT STACK POINTER is represented by the symbol AGSP, then the following instructions would take the general form:

TEMP1 = [TOS]
TEMP2= [NxTOS]
AGSP < AGSP + 6
RESULT = TEMP2 OP TEMP1
[TOS] = RESULT

Where OP is one of the following operators to be described. NOTE that the group of instructions ALWAYS POP the ARGUMENT STACK by one FLOATING POINT NUMBER SIZE (i.e. 6 BYTES).

ERRORS can be handled in two different ways with the ADD, SUBTRACT, MULTIPLY, and DIVIDE routines. One option is to let MCS BASIC-52 trap ERRORS, should they occur during the operation. With this option MCS BASIC-52 will print the appropriate error message to the console device. The other option passes a STATUS CODE to the user. After the operation the Accumulator contains the status code information. The Status information is as follows:

ACC.0--ARITHMETIC UNDERFLOW ACC.1--ARITHMETIC OVERFLOW ACC.2--RESULT WAS ZERO (not an error, just a condition) ACC.3--DIVIDE BY ZERO ACC.4--NOT USED, ZERO RETURNED ACC.5--NOT USED, ZERO RETURNED ACC.6--NOT USED, ZERO RETURNED ACC.7--NOT USED, ZERO RETURNED

If an ARITH. OVERFLOW or a DIVIDE BY ZERO ERROR occurs and the user is handling the error condition, the floating point processor will retum a result of +- 99999999E+ 127 to the argument stack. The user can do what they want to with this result (i.e. use it or waste it). An ARITH. UNDERFLOW ERROR will return to the argument stack a result of 0 (zero).

MCS BASIC-52 can perform the following DUAL OPERAND OPERATIONS:

OPBYTE = 9 (09H) EXPONENTIATION

The [NxTOS] value is raised to the [TOS] power. RESULT= [NxTOS] ** [TOS]. NOTE--[TOS] MUST BE LESS THAN 256.

OPBYTE = 10 (0AH) MULTIPLY

RESULT = [NxTOS] * [TOS]. If an ERROR occurs during this operation (i.e. ARITH. OVERFLOW or UNDERFLOW) MCS BASIC-52 will trap the error and print the error message to the console device.

OPBYTE = 136 (88H) MULTIPLY

RESULT = [NxTOS] * [TOS]. If an error occurs during this operation, the status byte previously discussed will be returned to the user.

OPBYTE = 11 (0BH) ADD

RESULT = [NxTOS] + [TOS]. BASIC handles errors.

OPBYTE = 130 (82H) ADD

RESULT = [NxTOS] + [TOS]. User handles errors.

OPBYTE = 12 (0CH) DIVIDE

RESULT = [NxTOS] / [TOS]. BASIC handles errors.

OPBYTE = 138 (8AH) DIVIDE

RESULT = [NxTOS] / [TOS]. User handles errors.

OPBYTE = 13 (0DH) SUBTRACT

RESULT = [NxTOS] -- [TOS]. BASIC handles errors.

OPBYTE = 132 (84H) SUBTRACT

RESULT = [NxTOS] - [TOS]. User handles errors.

OPBYTE = 14 (0EH) EXCLUSIVE OR

RESULT = [NxTOS] XOR [TOS], both values must be GREATER THAN OR EQUAL TO ZERO and LESS THAN OR EQUAL TO 65535 (0FFFFH).

OPBYTE = 15 (0FH) LOGICAL AND

RESULT = [NxTOS] and [TOS], both values must be GREATER THAN OR EQUAL TO ZERO and LESS THAN OR EQUAL TO 65535 (0FFFFH).

OPBYTE = 16 (10H) LOGICAL OR

RESULT = [NxTOS] OR [TOS], both values must be GREATER THAN OR EQUAL TO ZERO and LESS THAN OR EQUAL TO 65535 (0FFFFH).

OPBYTE = 18 (12H) TEST FOR EQUALITY

IF [NxTOS] = [TOS] then, RESULT = 65535 (0FFFFH), else RESULT = 0.

OPBYTE = 19 (13H) TEST FOR GREATER THAN OR EOUAL

IF [NxTOS] > = [TOS] then, RESULT = 65535 (0FFFFH), else RESULT = 0.

OPBYTE = 20 (14H) TEST FOR LESS THAN OR EQUAL

IF [NxTOS] < = [TOS] then, RESULT = 65535 (0FFFFH), else RESULT = 0.

OPBYTE = 21(15H) TEST FOR NOT EQUAL

IF [NxTOS] <> [TOS] then, RESULT = 65535 (0FFFFH), else RESULT = 0.

OPBYTE = 22(16H) TEST FOR LESS THAN

IF [NxTOS] < [TOS] then, RESULT = 65535 (0FFFFH), else RESULT = 0.

OPBYTE = 23(17H) TEST FOR GREATER THAN

IF [NxTOS] > [TOS] then, RESULT = 65535 (0FFFFH), else RESULT = 0.

9.6 ADDED LINK ROUTINES TO VERSION 1.1

Version 1.1 of MCS BASIC-52 contains a number of useful assembly language link routines that were not available in Version 1.0. Most of these routines were designed to be used in conjunction with the new Command/Statement extensions that are described in Chapter 11 of this manual. The added link routines are as follows:

OPBYTE = 57 (39H) EVALUATE AN EXPRESSION WITHIN THE BASIC TEXT STRING AND PLACE THE RESULT ON THE ARGUMENT STACK

This routine permits the user to evaluate a BASIC expression [expr] containing variables, operators and constants. The result of the evaluated expression is placed on the floating point argument stack. This lets the user evaluate expressions in "customized" statements and commands. An example of use of this OPBYTE is given at the end of this section.

OPBYTE = 58 (3AH) PERFORM CRYSTAL DEPENDENT CALCULATIONS WITH THE VALUE THAT IS ON THE ARGUMENT STACK

This routine is provided mainly to let the user write an assembly language RESET routine and perform all of the crystal dependent calculations that are required by MCS BASIC-52. An example of a customized RESET routine that uses this OPBYTE is presented in Chapter 11 of this manual.

OPBYTE = 63 (3FH) GET A CHARACTER OUT OF THE BASIC TEXT STRING

This routine permits the user to "pick" a character out of the BASIC program. For instance, in BASIC the user could have the following:

10 CALL 1000H A

If the user executed the following in assembly language at 1000H:

MOV A, #63 LCALL 30H

The character A would be returned in the accumulator. The Basic text pointer is located in location 8 (8H) (low byte) and 10 (0AH) (high byte) of the internal ram on the MCS BASIC-52 device. If the user were to implement the above function, the basic text pointer must be advanced to the carriage return at the end of the statement before retuming back to Basic. Failure to do this will cause a BAD SYNTAX ERROR when the user retums back to Basic. The following OPBYTE can be used to advance the Basic Text pointer.

OPBYTE = 64 (40H) GET CHARACTER, THEN INCREMENT TEXT POINTER

This OPBYTE does the same thing as the previous one described, except that the BASIC text pointer is INCREMENTED AFTER the character is read. An example of this OPBYTE is presented at the end of this section.

OPBYTE = 65 (41H) INPUT A CHARACTER FROM THE CONSOLE DEVICE, PUT IT IN THE ACCUMULATOR, THEN RETURN

This OPBYTE permits the user to input characters from MCS BASlC-52's console input routine. The character is placed in the accumulator upon return.

OPBYTE = 66 (42H) ENTER THE RUN MODE

This OPBYTE permits the user to start the execution of an MCS BASIC-52 program from assembly language. The user need only insure that locations 19 (13H) and 20 (14H) of internal data memory contain the start address (high byte, low byte respectively) of the BASIC program.

OPBYTE = 129 (81H) INPUT AN ASCII FLOATING POINT NUMBER AND PLACE IT ON THE ARGUMENT STACK. THE DPTR POINTS TO THE EXTERNAL RAM LOCATION, WHERE THE ASCII TEXT STRING IS STORED

This routine assumes that the user has placed an ASCII text string somewhere in memory and that this ASCII text string represents a valid floating point number. The user then puts the DPTR to the starting address of this text string. After this OPBYTE is executed the text string will be converted to a valid MCS BASIC-52 floating point number and placed on the argument stack and the DPTR will be advanced to the end of the floating point number. If the DPTR does not point to a text string that contains a valid floating point number, the accumulator will contain an 0FFH upon return.

OPBYTE = 152 (98) OUTPUT, IN HEX, TO THE CONSOLE OUTPUT DRIVER, THE CONTENTS OF R3:R1

This routine is used to display HEX numbers, assuming that they are in registers R3:R1. If R3 = 0, leading zeros can be supressed by setting BIT 54 (36H) before calling this routine. If BIT 54 (36H) is cleared when this routine is called, the driver will always output four hex digits followed by the character H. This routine always outputs a space character (20H) to the console device, before any hex digits are output. BIT 54 (36H) is bit 6 of internal RAM location 38.

MCS-S1 MACRO ASSEMBLER ISIS-II MCS-51 MACRO ASSEMBLER V1.0 OBJECT MODULE PLACED IN:F4:DEMO HEX ASSEMBLER INVOKED BY: ASM51 :F4:DEMO LOC OBJ LINE SOURCE 1 ; ********************************************************************* 2 ; 3 ; The following is an example of a program that uses the new OPPYTES 4 ; available in version 1.1 of MCS BASIC-52. This code is by no means 5 ; optimized but it is meant to demonstrate how the user can define 6 ; "customized" commands and statements in version 1.1 of MCS BASIC-52. 7 ; 8 ; The new command defined here is DISPLAY. What it does is display a 9 ; region of external data memory to the console device. The syntax 1O ; for this statement is: 11 ; 12 ; DISPLAY [expr], [expr] 13 ; 14 ; Where the first expression is the starting address and the last 15 ; expression is the ending address. In this example the DISPLAY is 16 ; treated like a command which means that it cannot be executed in 17 ; RUN mode. 18 ; 19 ; The output for the DlSPLAY command is as follows: 20 ; 21 ; ADDRESS then 16 Bytes of Characters i. e. 22 ; 23 ; 1000H 00H 22H 33H 27H . . . . . . . . 24 ; 25 ; Now on to the program. 26 ;**********************************************************************

27 2002 28 ORG 2002H 29 2002 5A 30 DB 5AH ; Tell basic that expanslon option is 31 ; present 2048 32 ORG 2048H 33 2048 D22D 34 SETB 45 ; Set the bit that sags so 204A 22 35 RET 36 2070 37 ORG 2070H ; Set up DPTR to Jump table 38 2070 90207C 39 MOV DPTR,#VECTOR_TABLE 2073 22 40 RET 41 2078 42 ORG 2078H ; Set up DPTR to expansion table 43 2078 90207E 44 MOV DPTR,#USER_TABLE 2078 22 45 RET 46 47 VECTOR TABLE: 48 207C 2087 49 DW DO_DISPLAY ; This is the address of DISPLAY 50 51 USER TABLE: 52 207E 10 53 DB 10H ; Token for Display 207F 44495350 54 DB 'DISPLAY' ; ASCII for display 2083 4C4159 2086 FF 55 DB 0FFH ; End of table (short table) 56 57 58 59 DO DISPLAY: 60 2087 302F63 61 JNP 47,DUMMY ; make sure that MCS BASIC-52 is in 62 ; the command mode. Bit 47 is set 63 ; if it is. 64 208A 7439 65 MOV A,#57 ; Evaluate the first expression after 208C 120030 66 LCALL 30H ; the keyword dlsplay, MCS BASIC-52 67 ; will handle any errors. The value 68 ; of the expression will be on the 69 ; Argument Stack. 70

208F 7440 71 MOV A,#64 ; Get the character after the expression 2091 120030 72 LCALL 30H ; and bump the BASIC text pointer 73 2094 B42C6A 74 CJNE A,#',',C_ERROR ; Make sure it is a comma, if not do an 79 ; error 76 2097 7439 77 MOV A,#57 ; Evaluate the next expression (the 2099 120030 78 LCALL 30H ; ending address) and put it on the 79 ; Argument Stack 80 209C 7401 81 MOV A,#1 ; Convert the last expression (the 209E 120030 82 LCALL 30H ; ending address) on the stack to 83 ; an integer and put it in R3:R1 84 20A1 8918 85 MOV 18H,R1 ; Save the endlng address in the user 20A3 8B19 86 MOV 19H,R3 ; reserved locations 18H and 19H. This 87 ; is reserved as register bank 3 88 20A5 7401 89 MOV A,#1 ; Convert the first expression (the 20A7 120030 90 LCALL 30H ; starting address) on the stack to 9l ; an Integer and put it in R3:R1 92 20AA 891A 93 MOV 1AH.R1 ; Save the starting address in the user 20AC 8B1B 94 MOV 1BH.R3 ; reserved locations 1AH and 18H 95 96 ; Now everythlng is set up to loop 97 20AE C3 98 LOOP1: CLR C ; Check to make sure that the starting 20AF E518 99 MOV A,18H ; or current address is <= the ending 20B1 951A 100 SUB8 A,1AH ; address 20B3 E519 101 MOV A,19H 20B5 951B 102 SUBB A,1BH 20B7 5004 103 JNC LOOP2 ; If the carry is set, it's over 20B9 E4 104 CLR A ; Go to the command mode 20BA 020030 105 LJMP 30H ; (if display was a statement instead 106 ; of a command. this routine would 107 ; exit with a RET) 108 20BD 7407 109 LOOP2: MOV A,#7 ; Do a carriage return, line feed 20BF 120030 110 LCALL 30H 111 20C2 A91A 112 MOV R1.1AH ; Output the Starting address 20C4 AB1B 113 MOV R3.18H 114 20C6 C236 115 CLR 36H ; Don't supress leading zeros

20C8 7498 116 MOV A,#98H 20CA 120030 117 LCALL 30H 118 20CD 851A82 119 LOOP3: MOV DPL,1AH ; Now, set up to read 16 bytes 20D0 851B83 120 MOV DPH,1BH ; put address in DPTR 121 20D3 E0 122 MOVX A,@DPTR ; Read the byte in external RAM 20D4 A3 123 INC DPTR ; Bump to the next location 124 20D5 85821A 125 MOV 1AH,DPL ; Save the Address 20D8 85831B 126 MOV 1BH,DPH 127 20DB F9 128 MOV R1,A ; Output the byte 20DC 7B00 l29 MOV R3,#0 ; The high byte is always zero 20DE D236 130 SETB 36H ; Supress leading Zeros 20E0 7498 131 MOV A,#98H 20E2 120030 132 LCALL 30H 133 20E5 E51A 134 MOV A,1AH ; Check to see if on a 16 byte boundry 20E7 540F 135 ANL A,#0FH 20E9 70E2 136 JNZ LOOP3 ; Loop until on a 16 Byte Boundry 20EB 80C1 137 SJMP LOOP1 138 139 DUMMY: 140 20ED 7407 141 MOV A,#7 ; Do a carriage return-line feed 20EF 120030 142 LCALL 30H 143 20F2 7B21 144 MOV R3,#HIGH D_MSG ; Display the error message 20F4 7915 145 MOV R1,#LOW D_MSG 20F6 D234 146 SETB 52 ; Print from ROM 20F8 7406 147 MOV A,#6 20FA 120030 148 LCALL 30H 20FD E4 149 CLR A ; Go back to the command mode 20FE 020030 150 LJMP 30H 151 152 C_ERROR: 153 2101 7407 154 MOV A,#7 ; Do what we did before 2103 120030 155 LCALL 30H 156 2106 7B21 157 MOV R3,#HIGH C_MSG 2108 793B 158 MOV R1,#LOW C_MSG 210A D234 159 SETB 52 210C 7406 160 MOV A,#6 210E 120030 161 LCALL 30H

2111 E4 162 CLR A 2112 020030 163 LJMP 30H 164 2115 44495350 165 D_MSG: DB "DISPLAY IS A COMMAND, NOT A STATEMENT" 2119 4C415920 211D 49532041 2121 20434F4D 2125 4D414E44 2129 2C204E4F 212D 54204120 2131 53544154 2135 454D454E 2139 5422 166 213B 594F5520 167 C_MSG: DB "YOU NEED A COMMA TO MAKE DISPLAY WORK" 213F 4E454544 2143 20412043 2147 4F4D4D41 214B 20544F20 214F 4D414B45 2153 20444953 2157 504C4159 215B 20574F52 215F 4B22 168 169 END ASSEMBLY COMPLETE. NO ERRORS FOUND (that'- all it takes)

9.7 INTERRUPTS

Interrupts can be handled by MCS BASIC-52 in two distinct ways. The first, which has already been discussed, allows statements in an MCS BASIC-52 program to perform the required interrupt routine. The ONTIME and ONEX1 statements enable this particular interrupt mode. Additionally, setting BIT 26.1H permits EXTERNAL INTERRUPT 0 to act as a "fake" DMA input and the details of this feature are in the BELLS, WHISTLES, and ANOMALIES section of this manual. The second method of handling interrupts in MCS BASIC-52 allows the programmer to write assembly language routines to perform the interrupt task. This method yields a much faster interrupt response time, but, the programmer must exercise some caution.

All interrupt vectors on the MCS BASIC-52 device are "mirrored" to external PROGRAM MEMORY LOCATIONS 4003H through 402BH inclusive. The only MCS BASIC-52 STATEMENTS that enable the interrupts on the 8052AH are the CLOCK1 and the ONEX1 STATEMENTS. If interrupts are NOT enabled by these STATEMENTS, BASIC assumes that the USER is providing the interrupt routine in assembly language. The vectors for the various interrupts are as follows:

LOCATION---INTERRUPT 4003H------EXTERNAL INTERRUPT 0 400BH------TIMER 0 OVERFLOW 4013H------EXTERNAL INTERRUPT 1 401BH------TIMER 1 OVERFLOW 4023H------SERIAL PORT 402BH------TIMER 2 OVERFLOW/EXTERNAL INTERRUPT 2

The programmer can enable interrupts in MCS BASIC-52 by using the statement IE = IE.OR.XXH, where XX enables the appropriate interrupts. The bits in the interrupt register (IE) on the 8052AH are defined as follows:

BIT 7 6 5 4 3 2 1 0 EA X ET2 ES ET1 EX1 ET0 EX0 ENABLE UNDE- TIMER2 SERIAL TIMER1 EXT1 TIMER0 EXT 0 ALL FINED PORT

Interrupts are enabled when the appropriate BITS in the IE register are set to a one. Details of the 8052AH interrupt structure are available in the MICROCONTROLLER USERS MANUAL available from INTEL.

============================== IMPORTANT NOTE!! ==============================

Before MCS BASIC-52 vectors to the USER interrupt locations just described, the PROCESSOR STATUS WORD (PSW) is PUSHED onto the STACK. So, the USER does not have to save the PSW in the assembly language interrupt routine!!! HOWEVER, THE USER MUST POP THE PSW BEFORE RETURNING FROM THE INTERRUPT.

============================ VERY IMPORTANT NOTE!!! ===========================

If the user is running some interrupt driven "background" routine while MCS BASIC-52 is running a program, the user MUST NOT CALL any of the assembly language routines available in the MCS BASIC-52 device. The only way the routines in the MCS BASIC-52 device can be accessed is when the CALL statement in MCS BASIC-52 is used to transfer control to the users assembly language program. The reason for this is that the MCS BASIC-52 interpreter must be in a "known" state before the user can call the routines available in the MCS BASIC-52 device and a "random" interrupt does not guarantee that the interpreter is in this known state. The user should use REGISTER BANK 3 to handle interrupt routines in assembly language.

9.8 RESOURCE ALLOCATION

Specific statements in MCS BASIC-52 require the use of certain hardware features on the device. If the user wants to use these hardware features for interrupt driven routines, conflicts between BASIC and the assembly language routine may occur. To avoid these potential conflicts, the programmer needs to know what hardware features are used by MCS BASIC-52. The following is a list of the COMMANDS and/or STATEMENTS that use the hardware features on the 8052AH.

CLOCK1--uses TIMER/COUNTER 0 in the 13 bit 8048 mode.

PWM--uses TIMER/COUNTER 1 in the 16 bit mode

LIST#--uses TIMER/COUNTER 1 to generate baud rate in 16 bit mode

PRINT#--same as LIST#

PROG--uses TIMER/COUNTER 1 for programming pulse

ONEX1--uses EXTERNAL INTERRUPT 1

In addition, TIMER/COUNTER 2 is used to generate the baud rate for the serial port. What the preceding list means is that if CLOCK1, PWM, ONEX1, LIST#, PRINT#, and PROG commands/statements are used by the programmer, the user MAY NOT use the associated TIMER/COUNTER or EXTERNAL INTERRUPT pin for an assembly language routine.

MCS BASIC-52 initializes the TIMER/COUNTER modes by writing a 244 (0F4H), 16 (10H), and 52 (34H) to the TCON, TMOD, and T2CON registers respectively. These registers are initialized only during the RESET initialization sequence, and MCS BASIC-52 assumes that these registers are NEVER changed. So, if the user changes the contents of TCON, TMOD, or T2CON, something funny and/or disastrous is bound to happen if the Statements/Commands listed above are executed. If the user does not execute any of the previously mentioned Statements or Commands, the user is free to use the interrupts in any way suitable to the application.

 

Copyright © Madis Kaal 2000-