Copyright 1984 by ABComputing May 15, 1984 ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º DOS 1.1, 2.0 Sequential File-Reading º º º º by º º º º Bill Salkin º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Introduction ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ This article discusses sequential file-reading under DOS 1.1 and DOS 2.0. The source code given performs the following functions: read one byte from the file "A:JUNK.TXT", display it, and continue in this manner until an end-of-file (EOF) condition is reached. DOS 2.0 uses a new approach to file handling that was not available under DOS 1.1. For this reason, separate source code and commentary are provided for each release. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ FCB vs. ASCIIZ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ In DOS 1.1, the liaison or "link" between the physical file as stored on the disk, and the file as viewed by the programmer, is called the file control block (FCB). An FCB is a 37-byte data structure containing file-related information such as: the filespec, time and date stamp, the file size, current block, and record size. The FCB map or layout of a "standard" FCB is shown below: 0 ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Drive ³ Filename (8 bytes) ³ 8 ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ File extension ³ Current Block ³ Record Size ³ 16 ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³File size (low) ³File size (high) ³ Date ³²²²²²²²²²²²²²³ 24 ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ²²²²²²²²²²²²²³ ³²²²²²²²²²²²²²²²²²²² Reserved for system use ²²²²²²²²²²²²²²²²²²²²³ 32 ÃÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³Current ³ Random Record ³ Random Record ³ ³Record ³ # (low) ³ # (high) ³ ÀÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ As offset 0 from the start of the FCB is the drive specifier for the file. (Other fields are discussed later.) A file is associated with an FCB by the filename and file extension fields of the FCB. When we speak of "opening" a file, we actually are opening the FCB associated with this file. This abuse of terms is enjoyed by all writers, and I will be equally loose. DOS 2.0 offers an improved approach to file handling by using ASCIIZ strings. This approach is easier to program, more flexible, and more uniform than methods employing FCBs. Furthermore, FCBs need not be used under DOS 2.0, as new file-handling routines have been introduced to perform the functions of earlier FCB-bound ones. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ DOS 1.1 File-handling ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ FCB Structure ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Program 1, shown later in this file, establishes an FCB for file "A:JUNK.TXT" in our data segment, by the statement: FCB DB 1,'JUNK ','TXT',25 DUP(0) An FCB is called unopened when it contains only the drive specifier and filespec. The FCB given above is an unopened FCB. The "1" shown is a drive specifier meaning the file is on the "A" drive (2 = "B" drive, 3 = "C" drive, etc.) Blanks were added after the filename "JUNK" to account for an eight-character filename. The file extension is "TXT," and the remainder of the FCB is padded with zeroes. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Setting the DTA ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Data read from a disk is stored in an area called the Disk Transfer Area (DTA). In Program 1, we instruct DOS to set the DTA location to an area we can access easily. We select IO_AREA (a one-byte buffer in our data segment) as the DTA by using DOS function call 1AH, with DS:DX pointing to the area that we want for our DTA (IO_AREA). MOV AH,1AH ;REQUEST "SET DTA" SERVICE MOV DX,OFFSET IO_AREA ;SET DTA TO IO_AREA INT 21H ;INVOKE "SET DTA" SERVICE The DTA will remain at IO_AREA until the DTA address is reset by another 1AH function call. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Opening an FCB ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ After the DTA has been set to IO_AREA, the FCB (for file "A:JUNK.TXT") is opened. This is required before any read (or write) operation can occur. DOS call 0FH opens the FCB corresponding to the file "A:JUNK.TXT". MOV AH,0FH ;REQUEST "OPEN FCB" SERVICE MOV DX,OFFSET FCB ;MAKE DS:DX -> FCB INT 21H ;INVOKE "OPEN FCB" SERVICE ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ FCB Fields ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ DOS's logical view of a file is a collection of "blocks," with each block consisting of 128 "records." The current block and current record fields of an FCB (offsets 12 and 32 bytes from the FCB start) are used during sequential read/write operations as pointers to the next record to read/write. Setting the current block and record number fields to zero, positions the read/write pointer to the beginning of the file. This is accomplished as follows: MOV WORD PTR FCB+12,0 ;SET CURRENT BLOCK NUMBER TO 0 MOV FCB+32, 0 ;SET CURRENT RECORD TO 0 With the read/write pointer at the start of the file, we next specify the amount of data to be read with each read operation. This amount is given by the value in the record size field (at offset 14 bytes from FCB start) which we change to a "1" as we want to read one byte. (This one-byte length is referred to as RECORD_LENGTH in Program 1.) The code performing this is: MOV WORD PTR FCB+14,RECORD_LENGTH The sequential-read operation automatically updates the current block and record fields, positioning the read/write pointer for the next read operation. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Reading the File ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ DOS call 14H is used to perform the sequential read, with DS:DX pointing to the open FCB for the file to be read. But as DS:DX already points to the desired FCB (from the open service), to read one byte into IO_AREA, we use: MOV AH,14H ;REQUEST "READ FILE" SERVICE INT 21H ;INVOKE "READ FILE" SERVICE The value returned in AL is not zero if an EOF condition was encountered. We continue reading and displaying one byte, until the EOF marker is reached. When the EOF marker is encountered, the FCB is closed using DOS call 10H, and the program terminates. MOV AH,10H ;REQUEST "CLOSE FILE" SERVICE INT 21H ;INVOKE "CLOSE FILE" SERVICE ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Program 1 ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ;COPYRIGHT 1984 BY ABComputing ; ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ ³ ; ³ THIS PROGRAM READS AND DISPLAYS THE FILE "A:JUNK.TXT" ONE ³ ; ³ BYTE AT A TIME. ONLY DOS 1.1 FUNCTION CALLS ARE USED. ³ ; ³ ³ ; ³ THIS FILE IS ASSUMED TO EXIST, AND NO CHECK IS MADE FOR ³ ; ³ THIS. ³ ; ³ ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ; ;------------------------------------------------------------------------------ MAIN_DATA SEGMENT PARA PUBLIC 'DATA' RECORD_LENGTH EQU 1 ;LENGTH OF RECORD READ INTO DTA FCB DB 1,'JUNK ','TXT',25 DUP(0) IO_AREA DB RECORD_LENGTH DUP(0),'$' ;"IN-ROOM" FOR DISK READS MAIN_DATA ENDS ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ STACK SEGMENT PARA STACK 'STACK' DB 40H DUP('STCK') STACK ENDS ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ CODE SEGMENT PARA PUBLIC 'CODE' ASSUME CS:CODE,DS:MAIN_DATA,SS:STACK,ES:NOTHING MAIN PROC FAR ;STANDARD LINKAGE TO DOS PUSH DS ; DO MOV AX,0 ; PUSH AX ; NOT MOV AX,MAIN_DATA ; MOV DS,AX ; ALTER! CALL READ_FILE ;READ AND DISPLAY THE FILE RET ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ ;ROUTINE READ_FILE ; ; BRIEF: ; READS THE FILE "A:JUNK.TXT" AND DISPLAYS IT ON THE SCREEN. ; ; INPUT: ; RECORD_LENGTH: THE NUMBER OF BYTES TO READ FROM THE FILE ; WITH EACH READ OPERATION. ; ; AN FCB FOR THE FILE "A:JUNK.TXT" ; ; AN INPUT DATA AREA (IO_AREA) WHERE EACH RECORD READ FROM THE ; FILE IS BUFFERED. ; ; OUTPUT: ; THE FILE "A:JUNK.TXT" IS DISPLAYED ON THE SCREEN. ; ;------------------------------------------------------------------------------ READ_FILE PROC NEAR PUSH AX PUSH DX ;--PERFORM ALL DISK TRANSFERS TO IO_AREA MOV AH,1AH ;REQUEST "SET DTA" SERVICE MOV DX,OFFSET IO_AREA ;SET DTA TO IO_AREA INT 21H ;INVOKE "SET DTA" SERVICE ;--OPEN FCB FOR FILE MOV AH,0FH ;REQUEST "OPEN FCB" SERVICE MOV DX,OFFSET FCB ;MAKE DS:DX -> FCB INT 21H ;INVOKE "OPEN FCB" SERVICE ;--ADJUST FCB TO READ "RECORD_LENGTH" BYTES, STARTING AT BEGINNING OF FILE MOV WORD PTR FCB+12,0 ;SET CURRENT BLOCK NUMBER TO 0 MOV WORD PTR FCB+14,RECORD_LENGTH MOV FCB+32, 0 ;SET CURRENT RECORD TO 0 ;--READ "RECORD_LENGTH" BYTES INTO IO_AREA (RECALL DS:DX -> FCB) REA1: MOV AH,14H ;REQUEST "READ FILE" SERVICE INT 21H ;INVOKE "READ FILE" SERVICE CMP AL,0 ;AL = 0 IF READ WAS FINE JNE REA2 ;AL <> 0 IF EOF ;--WRITE "IO_AREA" TO SCREEN PUSH DX ;SAVE DX FOR FILE READ MOV AH,9 ;REQUEST "PRINT STRING" SERVICE MOV DX,OFFSET IO_AREA INT 21H ;INVOKE "PRINT STRING" SERVICE POP DX ;RESTORE DX FOR FILE READ. JMP REA1 ;GET NEXT BYTE ;--CLOSE FCB (RECALL DS:DX -> FCB) REA2: MOV AH,10H ;REQUEST "CLOSE FILE" SERVICE INT 21H ;INVOKE "CLOSE FILE" SERVICE POP DX POP AX RET READ_FILE ENDP ;------------------------------------------------------------------------------ MAIN ENDP ;END of MAIN procedure CODE ENDS ;END of CODE Segment END MAIN ;END of assembly. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ DOS 2.0 File-handling ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Program 2, shown below, uses DOS 2.0 function calls to read the file "A:JUNK.TXT". (The same file read by Program 1.) The FCB concept in DOS 2.0 has been replaced by the simpler ASCIIZ string approach. An ASCIIZ string is a string containing the path (optional) and filespec, terminated by a byte of zeroes. An example is: FILE DB 'A:JUNK.TXT',0 Notice that the filespec is typed; the filename and extension are not separate fields as in the FCB approach, nor is the filename blank padded to occupy 8 characters. ASCIIZ strings are easier to use than FCBs and provide a level of insulation from the file-management structure that was not possible under DOS 1.1. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Opening the File ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ A file is opened under DOS 2.0 using one of three access methods. Each access method has an access code, and we use access code 0 to open the file for reading only. (The other access methods allow writing only, or both reading and writing.) When the file specified in the ASCIIZ string is opened, a word pointer, called a handle, is associated with it, and this handle is used whenever we wish to perform any operation with the file. Opening a file under DOS 2.0 automatically points the read/write pointer to the first byte of the file and sets the record size to one byte. How convenient; this is exactly the set up we need to read one byte from a file! It seems quite involved to open a file. At least the explanation is; the required code is simpler to write than it is to explain. ;--OPEN THE FILE "A:JUNK.TXT" FOR READING ONLY. MOV AH,3DH ;REQUEST "OPEN FILE" SERVICE MOV AL,0 ;FILE OPENED FOR READING MOV DX,OFFSET FILE ;DS:DX -> FILE TO BE READ INT 21H ;INVOKE "OPEN FILE" SERVICE ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Reading the File ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ To read the file we invoke DOS function call 3FH, with the file handle in BX, the buffer address in DS:DX, and the number of bytes to read in CX. The number of bytes actually read is returned in AX. If AX = 0, then the EOF marker was read. This one call combines the functions of many DOS 1.1 calls. After the file has been read and displayed, the file handle associated with the file is closed. This closes the file, and the program terminates. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Program 2 ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ;COPYRIGHT 1984 BY ABComputing ; ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ ³ ; ³ THIS PROGRAM READS AND DISPLAYS THE FILE "A:JUNK.TXT" ONE ³ ; ³ BYTE AT A TIME. ONLY DOS 2.0 FUNCTION CALLS ARE USED. ³ ; ³ ³ ; ³ THIS FILE IS ASSUMED TO EXIST, AND NO CHECK IS MADE FOR ³ ; ³ THIS. ³ ; ³ ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ; ;------------------------------------------------------------------------------ MAIN_DATA SEGMENT PARA PUBLIC 'DATA' RECORD_LENGTH EQU 1 ;NUMBER OF BYTES TO READ. FILE DB 'A:JUNK.TXT',0 IO_AREA DB RECORD_LENGTH DUP(0),'$' ;"IN-ROOM" FOR DISK READS MAIN_DATA ENDS ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ STACK SEGMENT PARA STACK 'STACK' DB 40H DUP('STCK') STACK ENDS ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ CODE SEGMENT PARA PUBLIC 'CODE' ASSUME CS:CODE,DS:MAIN_DATA,SS:STACK,ES:NOTHING MAIN PROC FAR ;STANDARD LINKAGE TO DOS PUSH DS ; DO MOV AX,0 ; PUSH AX ; NOT MOV AX,MAIN_DATA ; MOV DS,AX ; ALTER! CALL READ_FILE ;READ AND DISPLAY THE FILE RET ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ ;ROUTINE READ_FILE ; ; ; BRIEF: ; READS THE FILE "A:JUNK.TXT" AND DISPLAYS IT ON THE SCREEN. ; ; INPUT: ; RECORD_LENGTH: THE NUMBER OF BYTES TO READ FROM THE FILE ; WITH EACH READ OPERATION. ; ; THE ASCIIZ STRING "FILE" CONTAINING THE FILE TO BE READ. ; ; AN INPUT DATA AREA (IO_AREA) WHERE EACH RECORD READ FROM ; THE FILE IS BUFFERED. ; ; OUTPUT: ; THE FILE "A:JUNK.TXT" IS DISPLAYED ON THE SCREEN. ; ;------------------------------------------------------------------------------ READ_FILE PROC NEAR PUSH AX PUSH BX PUSH CX PUSH DX ;--OPEN THE FILE "A:JUNK.TXT" FOR READING. THIS CALL SETS THE READ/WRITE ; POINTER TO THE FIRST BYTE OF THE FILE, AND SETS THE RECORD SIZE TO ONE ; BYTE. ; ; ON RETURN AX HAS THE HANDLE (WORD POINTER) ASSOCIATED WITH THE FILE. MOV AH,3DH ;REQUEST "OPEN FILE" SERVICE MOV AL,0 ;FILE OPENED FOR READING MOV DX,OFFSET FILE ;DS:DX -> FILE TO BE READ INT 21H ;INVOKE "OPEN FILE" SERVICE ;--SAVE FILE HANDLE IN BX REGISTER. MOV BX,AX ;BX -> FILE HANDLE ;--PERFORM ALL DISK TRANSFERS TO IO_AREA MOV CX,RECORD_LENGTH ;CX HAS NUMBER OF BYTES TO READ MOV DX,OFFSET IO_AREA ;SET DS:DX -> TO IO_AREA REA1: MOV AH,3FH ;REQUEST "READ" SERVICE INT 21H ;INVOKE "READ" SERVICE CMP AX,0 ;AX HAS NUMBER OF BYTES READ JE REA2 ;READ END OF FILE ;--WRITE "IO_AREA" TO SCREEN (RECALL DS:DX -> IO_AREA) MOV AH,9 ;REQUEST "PRINT STRING" SERVICE INT 21H ;INVOKE "PRINT STRING" SERVICE JMP REA1 ;READ NEXT BYTE ;--AX = 0, SO END-OF-FILE READ. CLOSE FILE HANDLE AND LEAVE. REA2: MOV AH,3EH ;REQUEST "CLOSE FCB" SERVICE INT 21H ;INVOKE "CLOSE FCB" SERVICE POP DX POP CX POP BX POP AX RET READ_FILE ENDP ;------------------------------------------------------------------------------ MAIN ENDP ;END of MAIN procedure CODE ENDS ;END of CODE Segment END MAIN ;END of assembly. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Closing Thoughts ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ In both programs, one byte was read with each read operation to help locate the EOF marker. Reading a file one byte at a time, without any further processing of this byte, causes no noticeable speed degradation, as DOS buffers all file input/output. But if each byte must be inspected for special characters, speed degradation can be significant. For example, disk space can be conserved by compressing "blanks" in source files to tab characters when the file is saved. When this file is later read, each byte must be examined, and if a tab is found, expanded to the appropriate number of blanks. This is a time-consuming process and in this case it is best to read a block (or group) of data with each read operation. Once in memory, this block can be divided into individual bytes and each byte examined. (I have experimented using different RECORD_LENGTH values and the results can be startling. Using a RECORD_LENGTH of 1, a large file took 30 seconds to read and uncompress, one byte at a time, while with RECORD_LENGTH = 80, it took on 5 seconds! I also found, as was expected, that RECORD_LENGTHs significantly larger than 80 did not substantially improve this 5 second time. It's fun to experiment.) My next article on file handling deals with Random I/O. Sequentially yours, Bill Salkin ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ File Name: ÛÛ asm2.txt ÛÛ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ