Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
XASM 8051 Cross Assembler Users Guide Release 2.5 Revised 05-Jan-96 Copyright 1983-1996 Dave Dunfield All rights reserved XASM Cross Assemblers Page: 1 1. INTRODUCTION This single XASM package includes a cross assembler, and two utility programs: asm51 hexfmt macro - 8051/8052 Assembler (also 803x, 873x, 875x) - HEX file manipulator - Macro pre-processor The XASM "package" (software and documentation) is copyrighted, and may not be re-distributed without my written permission. If you find XASM useful, please help me continue to support and enhance it by ordering the complete package using the order form in the enclosed CATALOG file. XASM is provided on an "as is" basis, with no warranty of any kind. In no event shall the author be liable for any damages arising from its use or distribution. Throughout this document, angle braces ('<>') are used to indicate operands for which a value must be supplied by the user. Square braces ('[]') are used to identify operands which are optional. XASM Cross Assemblers Page: 2 2. ASSEMBLERS All of the cross assemblers read a source file (.ASM), and produce a code file (.HEX) containing either MOTOROLA or INTEL format ASCII-HEX download records. A optional listing file (.LST) may also be produced. 2.1 Using the assemblers Any assembler is invoked by entering its name at the command prompt, in the following format: ASMxx <filename> [options] The <filename> operand is the name of the file to be assembled, it is assumed to have the extension ".ASM" if none is supplied. Unless otherwise specified, the code produced by the assembler is written to a file with the name '<filename>.HEX', and the listing is written to a file with the name '<filename>.LST'. 2.1.1 Command line options The following options may be specified on the command line, following the <filename> operand: -A - [A]bsolute jumps/calls This directive causes the ASM51 to use AJMP/ACALL instructions in place of LJMP/LCALL. -C - [C]ase sensitive Causes the assembler to make a distinction between upper and lower case characters in symbol names. If this option is not used, the assembler will ignore case differences, same. and assume that the symbols are the NOTE: When using this option, you must enter any register names in UPPER case. C=<filename> - Specify [C]ode file This option allows you to specify the file to which the output code is written. If no extension is supplied as part of <filename>, it defaults to ".HEX". -F - Generate [F]ull listing Causes the assembler to output a full source listing to the '.LST' file. By default, only lines containing errors are written to the listing file. -I - Generate [I]ntel format HEX file Causes the assembler to output the code to the '.HEX' file in INTEL hex format. By default the code is written to the file in MOTOROLA hex format. XASM Cross Assemblers Page: 3 L=<filename> - Specify [L]isting file This option allows you to specify the file to which the listing is written. If no extension is supplied as part of <filename>, it defaults to ".LST". P=<length> - Set page length This option specifies the number of lines which will be printed on each page. The default number of lines per page is 60. -Q - [Q]uiet mode Causes the assembler to be quiet, inhibiting the display of the progress messages. -S - Generate [S]ymbol table Causes the assembler to sort and display the symbol table at the end of the listing file. By default, the symbol table is not displayed. -T - Output to [T]erminal Causes the assembler to output the listing to the terminal, (via stdout) instead of the usual '.LST' file. W=<width> - Set page width This option control the number of columns which will be used for the printing of page titles and the symbol table listing. Default page width is 80 columns. XASM Cross Assemblers Page: 4 2.2 Redirecting the listing file When the listing file is directed to the terminal with the '-t' option on the command line, it is displayed through the standard output file, allowing it to be redirected to a printer etc. via the shell '>' redirection operator (EG: ASMxx filename -f -t >LPT1:). The progress messages ('First pass...' etc) are output through stderr, and will therefore not be redirected with the listing. 2.3 Source file format The assembly source input lines are in the following format: '<label>[:] <instruction> <operands> <comment>' Labels must begin in column one, and must be separated from the instruction field by at least one blank or tab character. Labels may be followed by a ':' if desired, however this is not required by the assembler. If the an instruction or directive requires operands, then the operand field is required, and is separated from the instruction by at least one blank or tab. The optional comment field is delimited from the operand field by at least one blank or tab, and is ignored by the assembler. Blanks or tabs within the operand field are allowed only if contained within the delimiters of a character string, otherwise they will be interpreted as the end of the operand field. Any lines beginning with a '*' or ';' character in column one are considered to be the comments, and are not processed by assembler. XASM Cross Assemblers Page: 5 2.4 Expressions When an 8 or 16 bit value is required as an operand to an assembler directive or an instruction, either a simple value, or an expression consisting of simple values and operators may values. When be used. All expressions are evaluated using 16 bit an expression is evaluated in an instruction requiring an eight bit value, the lower eight bits are used. Expressions are evaluated from left to right, as each operator is encountered, without precedence. Precedence can be forced with the use of brackets. Spaces or tabs are not allowed within an expression, unless they are contained within a character string. The following operators may be used in an expression: 2.4.1 Unary (one operand) operators: ~ = - Negation, returns the negative of the next value. - Complement, returns one's complement of the value. - Swaps the high and low bytes of the next value. 2.4.2 Binary (two operand) operators: + * / \ & | ^ < > - Addition. Subtraction. Multiplication. Division (unsigned). Modulus, returns remainder after division. Bitwise AND. Bitwise OR. Bitwise EXCLUSIVE OR. Shift left Shift right 2.4.3 Values in expressions The following forms of simple values may be used. nnn nnnD nnnT $nnn nnnH %nnn nnnB @nnn nnnO nnnQ 'cc' <label> * $ - Decimal number, eg: 21 "" "": 21d "" "": 21t Hexidecimal number, eg: $15 "" "": 15h Binary number, eg: %10101 "" "": 10101b Octal number, eg: @177 "" "": 177o "" "": 177q ASCII characters, eg: 'A' Value of a label from symbol table. Value of current program counter. "" "" XASM Cross Assemblers Page: 6 2.5 Addressing Modes The assemblers support all addressing modes for their respective processors and will determine the type of addressing to use from the instruction and/or its operands. For cases where different sized offsets are available, the assemblers will always use the smallest (most efficent) form of the offset unless assembling in 'debug' mode in which case the largest offset will be used. 2.5.1 Immediate addressing For all assemblers except ASM85, the operand is determined to be an immediate value if it is preceeded by a pound sign ('#'). For instructions requiring only 8 bits of immediate data, the lower eight bits of the value will be used. The higher 8 bits of a value can be accessed by preceeding it with '=' (swapping high and low bytes). The '#' character is NOT used with immediate values in ASM85, because the immediate addressing context is inherent in the instruction. 2.5.2 Indirect addressing For processors supporting indirection of other addressing modes, this is indicated by placing the addressing reference in square braces ('[]'). Additionally, 8051 notation of a leading '@'. ASM51 supports the XASM Cross Assemblers Page: 7 2.6 Assembler directives The following directives (pseudo instructions) are supported by all of the assemblers: <label> EQU <expression> This directive sets the label on it's line to have the value of the operand expression. ORG <expression> This directive sets the internal program counter to the value of the operand expression, such that subsequent code will be generated at that address. TITLE <string value> This directive sets the title of the program to the text on the remainder of the line. The title is displayed at the top of each page in the listing, and by default is set to the name of the file being assembled. Lines containing this directive will not appear in the listing. PAGE This directive forces a page eject in the listing. Lines containing this directive will not appear in the listing. SPACE This directive causes a blank line to appear in the listing. Lines containing this directive will not appear in the listing. NOLIST This directive turns off the source listing, preventing any further lines from being displayed, in until a LIST directive encountered. NOLIST and LIST may be nested, listing is resumed only when all levels of NOLIST have been turned off. Lines in which errors occur are listed regardless of the NOLIST directive. LIST Re-enables output listing, following a NOLIST directive. END Causes the assembler to stop processing, and ignore the remainder of the source file. NOT required. Note that an END directive is XASM Cross Assemblers Page: 8 DB <expr1>[,<expr2>,<expr3>,...] FCB <expr1>[,<expr2>,<expr3>,...] These directives code the values of expressions into memory as single byte constants. the operand the operand DW <expr1>[,<expr2>,<expr3>,...] FDB <expr1>[,<expr2>,<expr3>,...] These directives code the values of expressions into memory as double byte constants. DRW <expr1>[,<expr2>,<expr3>,...] RDB <expr1>[,<expr2>,<expr2>,...] These directives are similar to DW/FDB, except that the high and low bytes of the coded values are exchanged. DS <expression> RMB <expression> These directives reserve a number of bytes of memory equal to the value of the operand expression. The contents of the reserved storage is undefined. STR 'text string' FCC 'text string' These directive code the string into memory as ASCII byte values. The string may be delimited by any character which is not part of the string text. STRH 'text string' FCCH 'text string' These directives perform exactly directives, except that the high bit is set on the string. STRZ 'text string' FCCZ 'text string' as the the STR/FCC last character in These directives perform exactly as the STR/FCC directives, except that the string has a zero byte ($00) appended. XASM Cross Assemblers Page: 9 2.6.1 Directives for ASM51 Only The following additional directives are supported by ASM51: <label> BIT <expression> Similar to "EQU", except that the label is forced to have the "bit" type, regardless of the type of expression used. <label> DATA <expression> Similar to "EQU", except that the label is forced to have the "direct non-bit" type, regardless of the type of expression used. XASM Cross Assemblers Page: 10 2.7 Error Messages When the assembler detects an error in the source code, it displays a message indicating a possible cause of the error, in the source listing on the line immediately following the line containing the error. Errors which are encountered in the first pass, are displayed at the top of the listing, along with the number of the line in which the error was detected. Forward references in any of the (EQU, ORG, or RMB/DS) directives are not allowed, and will cause an 'Undefined symbol' error in the first pass only, displayed at the top of the listing. XASM Cross Assemblers Page: 11 2.8 Error message summary Message# Message and description. --------+------------------------------------------------------------N/A | | Duplicate symbol: <symbol name> The indicated symbol is defined more that once within this | assembly. --------+------------------------------------------------------------N/A | | Symbol table overflow. There are too many symbols (labels) in the program, and the | assemblers symbol table has become full. --------+------------------------------------------------------------N/A | | Unable to resolve: <symbol name> The assembler is unable to determine a consistant value for | the indicated symbol. This is most likely due to excessive | forward referencing, or a self referencing loop. --------+------------------------------------------------------------1 | | The instruction Unknown instruction field on the indicated line does not | contain a valid instruction or assembler directive. --------+------------------------------------------------------------2 | | Out of range The operand is not the range of values which can be used | with the instruction. eg: A short branch to an address which | is farther than +127 or -128 bytes from the program counter. --------+------------------------------------------------------------3 | Invalid addressing mode | The addressing mode indicated by the operand field of the | indicated line does not apply to the instruction on that line. --------+------------------------------------------------------------4 | Invalid register specification | The instruction on the indicated line specifies a register | which is not a recognized register, or cannot be used in the | context specified by the instruction. --------+------------------------------------------------------------5 | | Undefined symbol A symbol referenced in the indicated line is not defined | anywhere within this assembly, and has no value. --------+------------------------------------------------------------6 | | Invalid expression syntax The expression on the indicated line contains a character | which is not recognized as a valid operator. --------+------------------------------------------------------------7 | | Invalid argument format The indicated line has an operand which is not in proper | format. --------+------------------------------------------------------------8 | | Improperly delimited string A character string constant on the indicated line does not | have a proper closing delimiter. This is normally the single | quote character, but may be another character in conjunction | with the FCC, FCCH, FCCZ, STR, STRH or STRZ directives. ---------------------------------------------------------------------- XASM Cross Assemblers Page: 12 3. MACRO PREPROCESSOR MACRO is an assembly source code pre-processor which provides macro substitution and conditional assembly facilities at the source code level to virtually any assembler or cross assembler. MACRO reads the raw assembler source from one or more files specified as its arguments, and the processed assembler source file is written to standard output where it can be re-directed into a temporary file for later assembly. All files specified as arguments are effectivly concatinated into the output file as they are processed, providing a conveinent way of maintaining large single source programs as more managable separate files. MACRO provides two types of macro definitions, substitution, and instruction. 3.1 Substitution macros Substitution macros may be used anywhere in any non- comment line of the source file (lines not beginning with '*'), and when encountered, are simply replaced by the text specified in the macro definition. Substitution macro's are defined using the 'SET' directive. If the macro definition text contains spaces, tabs, or it must be enclosed in double quote's. The following are examples of substitution macro definitions: sub1 set this_gets_substituted sub2 set "this gets substituted" Substitution macros are only recognized of they are surrounded commas, by non-alphanumeric characters. This prevents substitutions from occuring within other words which may contain the pattern. It does however require the restriction that the macro names contain only alphanumeric characters. 3.1.1 Command line substitutions Substitution macros may also be defined on the command line with arguments of the form "<symbol>=<string>". eg: 'macro source_file1 source_file2 mode=debug >output_file' XASM Cross Assemblers Page: 13 3.2 Instruction macros Instruction macros may only be used in the instruction field of the source file, and when encountered, are replaced by one or more lines of assembly source code. Instruction macros may be passed operands in the operand field of the assembly source code. If multiple operands are to be passed, they should be separated from one another by commas. If a single operand must contain spaces, tabs, or commas, it should be enclosed in double quotes. 3.2.1 Backslash commands The backslash character '\' has special meaning within an instruction macro definition as follows: \n invocation - Substitute the <n>'th parameter from line. <n> may range from zero to the nine, macro parameter zero is considered to be the LABEL from that line, actual parameters from the operand field begin with parameter one. \# - Substitute the number of parameters passed. \$ - Substitute a unique number which the total number of macro invocations to occur in this assembly so far. This is often used to create unique labels within the macro. \@n - Substitute a portion of the current date based on the digit 'n', as follows: \@1 \@2 \@3 \@4 \@5 \@6 \@7 - Day of month, 1 or 2 digits. Day of month, 2 digits. Month of year, 2 digits. Month of year in string form. Month of year in three character string form. Current year, 2 digits. Current hour, 2 digits. \@8 - Current minite, 2 digits. \@9 - Current second, 2 digits. NOTE: The time is recorded when MACRO is first invoked. \\ - Place a backslash character in the macro definition. Instruction macros are defined with the MACRO directive, and are ended with the ENDMAC directive. XASM Cross Assemblers Page: 14 3.2.2 Example instruction macro The following is an example of a instruction type macro using 6809 assembly language: * MACRO TO PRINT A CHARACTER STRING PRINT MACRO \0 PSHS A,X SAVE REGISTERS LDX #LAB2\$ STRING TO PRINT LAB1\$ LDA ,X+ GET CHAR FROM STRING BEQ LAB3\$ END, QUIT JSR PRINTCHR DISPLAY THE CHARACTER BRA LAB1\$ GO BACK FOR NEXT LAB2\$ FCCZ "\1" STRING TO PRINT LAB3\$ PULS A,X RESTORE REGISTERS ENDMAC 3.3 Macro directives MACRO suports the following directives, which may be placed in the assembler source file. Note that only substitution type macros may be used as values in operands to MACRO directives, as MACRO has no knowlege of the labels and symbols used by the assembler. <name> SET <string> The SET defines the substitution type macro with the name specified by <name> to have the text specified by <string>. Double quotes may be used if <string> is to contain tabs, spaces, or commas. If the macro being defined already exists, it is re-defined with the new value. <name> should begin in column one. <name> MACRO The MACRO directive begins the definition of a instruction type macro. are All subsequent lines up to a ENDMAC directive included in the macro definition. These lines are not written to the output file. ENDMAC This directive terminates an instruction type macro definition. IFEQ <string>,<string> The IFEQ directive causes MACRO to process and output all subsequent lines up to an ELSE or ENDIF directive, only if the two argument strings match. IFNE <string>,<string> The IFNE directive causes MACRO to process and output all subsequent lines up to an ELSE or ENDIF directive only the two argument strings do not match. if XASM Cross Assemblers Page: 15 ELSE The ELSE directive causes MACRO to process and output all subsequent lines up to and ENDIF directive only of the preceding IFEQ or IFNE directive failed. ENDIF This directive marks the end of a section of conditional assembly statements following a IFEQ, IFNE, or ELSE directive. INCLUDE "<filename>" The contents of the specified file are included the output file at the point where the INCLUDE directive occurs. Macro processing is performed on the included file. ABORT "<text>" Causes MACRO to terminate, message containing the specified text. displaying an error in XASM Cross Assemblers Page: 16 4. HEX FILE FORMAT UTILITY The HEXFMT utility provides several useful functions for manipulating the HEX output files, usually before programming them into a ROM. It can also translate from MOTOROLA to INTEL format, and change the record size, padding etc. of the output file. The available options to HEXFMT are: -b b=value c=value,value,value d=value f=value -i l=value -m -q r=value s=value -w w=filename Anywhere a 'value' - Output file in BINARY format Identify BASE address of HEX file Calculate checksum Set default byte value Maximum number of consecutive FF's Output file in INTEL format Set output file load address Output file in MOTOROLA format Quiet, Inhibit progress messages Set size (in bytes) of output records Set size (in bytes) of target ROM Do not write output file Write to this file is used, it may be specified in any of the following formats: nnnnn $xxxx @oooooo %bbbbbbbbbbbbbbbb - Decimal number (0 - 65535) Hexidecimal number ($0-$FFFF) Octal number (@0-@177777) Binary number (%0-%1111111111111111) 4.1 Input file HEXFMT reads its input file in either MOTOROLA or INTEL hex format (Such as is produced by the cross assemeblers), and builds a memory image of the ROM which is to be produced. The 's=' option specifies the size (in bytes) of the ROM image (default 8192). The 'b=' option specifies the base (starting) address to be assumed for the ROM image (default is addres in first record). The 'd=' option specifies the value which is to be assumed for all locations in the ROM image which are not loaded from the input file (default is $FF). XASM Cross Assemblers Page: 17 4.2 Output file Unless told otherwise, HEXFMT will write the data back to the same file it came from in the same format (MOTOROLA or INTEL) in which it was read. The '-w' option tells HEXFMT not to write an output file, it is useful if you simply want to know the checksum of the input file. The 'w=' option may be used to specify a different output file. The 'r=' option may be used to tell HEXFMT how many bytes to place in each output file record (default is 32). The 'l=' option tells HEXFMT the beginning load address for the output file records (default is Base address of input file). The 'm=' option tells HEXFMT how many consecutive $FF characters to allow in the output file before breaking the load address sequence (default is 5). Most EPROM's assume the $FF value when in the blank state, and therefore do not need to be programmed with this value. Eliminating consecutive $FF values from the load file will reduce the output file size and download time. The '-i' and '-m' options may be used to force HEXFMT to output the file in INTEL or MOTOROLA hex format, regardless of the input format. The '-b' option causes HEXFMT to write the file in BINARY form. When this is done, the output file will be an exact binary (8 bit) image of the target ROM. XASM Cross Assemblers Page: 18 4.3 Checksumming The 'c=' option may be used to cause HEXFMT to calculate a 16 bit checksum for a section of the ROM, and place it at a specified location. The format of the 'c=' option is: c=start,end,destination HEXFMT will calculate a checksum, which consists of the 16 bit sum of all byte (8 bit values) between the 'start' and 'end' addresses specified (inclusive). This 16 bit value is then stored at the indicated 'destination' address. NOTE: The start, end and destination addresses are given relative to the beginning of the image. ie: 0000 is the first address in the ROM. For example, To calculate the checksum of an 8K (8192 byte) ROM, beginning at the second location, and proceeding to the end of the ROM, storing this value at location 0000 in the ROM, you would use: c=2,8191,0 (decimal) or c=$0002,$1fff,$0000 (hex) The firmware in the ROM could then test the integrity of the ROM using code similar to this (for 6809): * ROUTINE TO TEST ROM CHECKSUM LDD #0 LDX #ROM+2 LOOP ADDB ,X+ ADCA #0 CMPX #ROM+8192 BNE LOOP CMPD >ROM BNE CKFAIL BEGIN WITH ZERO VALUE POINT TO SECOND BYTE OF ROM ADD 8 BIT VALUE... TO 16 BIT COUNTER ARE WE FINISHED (AT END)? NO, KEEP GOING IS CHECKSUM OK? NO, REPORT ROM ERROR Up to ten (10) 'c=' options may be specified in a single HEXFMT command, and each checksum will be calculated and stored (in the order in which they occur in the command line). HEXFMT will also display (but not store) the checksum for the entire ROM image, calculated in the above manner. XASM Cross Assemblers Page: 19 5. APPENDICES 5.1 Object file formats Object files are produced by the assemblers in either of two standard formats, both of which represent the binary data as two-digit printable ASCII hex numbers. The exact contents of the two standard format object files is as follows: 5.1.1 Motorola hex format Data Record: 'Stnnaaaadddddddddddddddddddddddddddddddd...cc' Where: S = 'S', indicates start of data record t = Record type, '1'=data, '9'=end of file. n = Count of number of bytes in record. (in ASCII/HEX) a = Load address of data record. (in ASCII/HEX) d = Actual data bytes in record. (in ASCII/HEX) c = Checksum of count, address, and data. (in ASCII/HEX) Note1: Checksum is computed as one's complement of eight bit sum of all values fron 'nn' to end of data. Note2: Count 'nn' is three greater then the number of data bytes in the record. 5.1.2 Intel hex format Data Record: ':nnaaaattdddddddddddddddddddddddddddddd...cc' Where: : = Indicates start of data record n = Count of number of bytes in record. (in ASCII/HEX) a = Load address of data record. (in ASCII/HEX) t = Record type (00=Data, 01=End of file) d = Actual data bytes in record (in ASCII/HEX) c = Checksum of count, address, and data. (in ASCII/HEX) Note1: Checksum is computed as two's complement of eight bit sum of all values fron 'nn' to end of data. Note2: End of file record contains count of 00. XASM Cross Assemblers Page: 20 5.2 ASCII code chart Most Significant Figure L e a s t S i g n i f i c a n t F i g u r e HEX|| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ===++=====+=====+=====+=====+=====+=====+=====+=====+ 0 || NUL | DLE | | 0 | @ | P | ` | p | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 1 || SOH | DC1 | ! | 1 | A | Q | a | q | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 2 || STX | DC2 | " | 2 | B | R | b | r | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 3 || ETX | DC3 | # | 3 | C | S | c | s | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 4 || EOT | DC4 | $ | 4 | D | T | d | t | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 5 || ENQ | NAK | % | 5 | E | U | e | u | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 6 || ACK | SYN | & | 6 | F | V | f | v | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 7 || BEL | ETB | ' | 7 | G | W | g | w | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 8 || BS | CAN | ( | 8 | H | X | h | x | ---++-----+-----+-----+-----+-----+-----+-----+-----+ 9 || HT | EM | ) | 9 | I | Y | i | y | ---++-----+-----+-----+-----+-----+-----+-----+-----+ A || LF | SUB | * | : | J | Z | j | z | ---++-----+-----+-----+-----+-----+-----+-----+-----+ B || VT | ESC | + | ; | K | [ | k | { | ---++-----+-----+-----+-----+-----+-----+-----+-----+ C || FF | FS | , | < | L | \ | l | | | ---++-----+-----+-----+-----+-----+-----+-----+-----+ D || CR | GS | - | = | M | ] | m | } | ---++-----+-----+-----+-----+-----+-----+-----+-----+ E || SO | RS | . | > | N | ^ | n | ~ | ---++-----+-----+-----+-----+-----+-----+-----+-----+ F || SI | US | / | ? | O | _ | o | DEL | ---++-----+-----+-----+-----+-----+-----+-----+-----+ XASM Cross Assemblers TABLE OF CONTENTS Page 1. INTRODUCTION 1 2. ASSEMBLERS 2 2.1 Using the assemblers 2 2.2 Redirecting the listing file 4 2.3 Source file format 4 2.4 Expressions 5 2.5 Addressing Modes 6 2.6 Assembler directives 7 2.7 Error Messages 10 2.8 Error message summary 11 3. MACRO PREPROCESSOR 12 3.1 Substitution macros 12 3.2 Instruction macros 13 3.3 Macro directives 14 4. HEX FILE FORMAT UTILITY 16 4.1 Input file 16 4.2 Output file 17 4.3 Checksumming 18 5. APPENDICES 19 5.1 Object file formats 19 5.2 ASCII code chart 20 S/N: 07961