32-bit Assembly Language Tutorial

-  Introduction
-  Using the Assembler Library
-  Procedures and Interrupts
-  Video Page Swapping Example
-  Conditional Jumps
-  Integer Arithmetic
-  Structures and Macros
-  Numeric Conversions and Libraries
-  Disk Storage
-  File Processing
Introduction

Welcome to Xander Obrzut's tutorial on 32-bit Assembly Language. In this tutorial Xander will guide you through as much knowledge of assembly language as the books he possess contain.

Xander owns a 16-bit reference manual for Assembly Language and a 32-bit reference manual for Assembly Language. Using these books, Xander will produce a easy to understand guide, with example programs at the end of each chapter for you, the programmer, to compile using MASM.

For your first program, at the end of this introduction, will be the Instructions to compile a 'Hello World' example program. These compiler instructions will be used through out this tutorial - so it is a good idea to learn right here and now how to use MASM and LINK to compile assembly code.

Your First Assembly Program - Hello_World.asm

In the table below is your first taste of assembly code. Take a good review of the code - it will be explained in details after the program code listing. Also, there will be details on how to compile the code using MASM - the Microsoft compiler.

; --------------------------(Start of Program Listing)-------------------------------------------

title Hello World Program(hello.asm)
; this program displays "Hello, World!"
.model small
.stack 100h
.data
message db "Hello, World!",0dh,0ah,'$'
.code
main proc
movax,@data
movds,ax
movah,9
movdx, offset message
int 21h
movax,4C00h
int 21h
main endp
end main

; --------------------------(END OF PROGRAM)-----------------------------------------

Program Explanation

The above code starts with a title directive. This is where you can name the program you are working on and also provide the filename at the end of the title for future reference. Next comes the actual beginning of a program - the .model and .stack directives. The model dictates to the compiler several things, such as the program calling definitions to use such as far or near, to size of over all program code in machine code.

The .stack directive dictates how much space to allocate on the stack (the place where data is stored - we come to the stack at a later point in this tutorial). Here we allocate 100h (hex) space for the program. Following the .stack directive comes the first segment of the program.

Assembly programs are divided in to segments. You can have multiply .code segments that are linked together and also multiple .data segments. This, how ever, is only for .exe programs where as .com programs (virus etc...) do not have a .data segment but allocate variables at the end of the program code.

The message db "Hello, World!" section is a variable being declared called 'message' which uses db (define byte) as storage space. It is stored in bytes. You can define bytes,words,double words, and quad words if not more in the data segment.

Finally, we have the juice of the program. The .code segment. This is divided yet again in to procedures. This program starts with 'main proc' - just a name which can be any name but we decided up on 'main' to name the first procedure. At the end of the code is 'main endp' which tells the compiler this procedure has finished.

Now, let us look at the actual code. The first two lines initialise the data segment to ds. It is not possible to move @data directly in to ds (data segment) so it is first passed to the register AX in the first line of code, and ax is passed in to ds in the second line of code making ds point to the start of the .data segment (message db "Hello, World!" etc...

Next, we call DOS with the function in ah number 9 (out put data) - then call the interrupt 21h (this is calling DOS) to display the data segment. We move the offset of the message to display in to dx - this is so DX now points to message - and at the end of message we terminate it with 0dh,0ah,'$' telling DOS the end of the string. Remove these lines and you'll out put too much data and possibly run in to physical ram.

The last two lines of the code move 4C00h (exit Program / return to DOS) in to AX can call DOS with the INT 21h command. This safely returns the program to the command prompt - otherwise only God knows what would happen!

The last two lines of the actual program listing are main endp (discussed above) and also 'end main', now the latter is the actual end of the program. This tells the compiler not to process any more of the file hello.asm

Compiling hello.asm with MASM

Try the following line:
ML /Zi /Zm /Fm /Fl hello.asm /link /co C:\Irvine.lib
This is one way to compile hello.asm - the /Zi means include debugging info, /Fl means produce a listing file, (hello.lst) /Fm means produce a map file (hello.map), and /Zm means use MASM 5.12 compatibility mode.
Another way - a much easier way - is to simply state the following...
masm hello
link hello
This, will also produce a compiled .exe to run from the command line. I just thought you would like to see a few options for ML :)

Now, when you run that code - your command prompt will prolly say they can not find masm or link - this is because you need to declare the PATH= directive on the command line before doing that. I included in the download a file called autoexec.bat - run that file by typing its name from the command line and you will automatically be included the right PATH= statements to the 'bin' and 'binr' folders for MASM. Examine the autoexec.bat file by right clicking it and selecting 'Edit' to see what all the buff is about with this file...

One final point of worth noting is the CV command. This command runs the program in a debugger mode - pressing F8 I believe forwards you through the program command by command execution and you can watch the registers change as well as observe other things. It is pretty neat and can be invoked by typing CV hello

This will load hello.exe in to CV for examination. Cool, eh?

Using the Assembler Library

Irvine.lib Library Example

Title Link Library Demo Program(lnkdemo.asm)
; This program calls various i/o procedures
; in the link library
.model small
.stack 100h
WhiteOnBlue = 1Fh
GreetingLoc = 0400h
.data
greeting db "Link Library Demo Program"
db 0dh,0ah,0dh,0ah
db "What is your name? ",0
numberPrompt db 0dh,0ah
db "Please enter a 16-bit integer: ",0
userNamedb 50 dup(0)
pressAnyKeydb 0dh,0ah,0dh,0ah
db "Press any key...",0
.code
extrn Clrscr:proc,Crlf:proc,Gotoxy:proc
extrn Readint:proc,Readstring:proc,Scroll:proc
extrn Readkey:proc,Writeint:proc,Writestring:proc
main proc
movax,@data
movds,ax
; Clear the screen, scroll a blue window.
call near ptr Clrscr
movcx,0400h; upper left corner
mov dx,0B28h; lower right corner
movbh,WhiteOnBlue
call near ptr Scroll
; Display a greeting and ask for the
; user's name.
movdx,GreetingLoc
call near ptr Gotoxy
movdx,offset greeting
call near ptr Writestring
movdx,offset userName
call near ptr Readstring
; Ask the user to enter a signed decimal integer.
; Redisplay the number in hex and binary.
movdx,offset numberPrompt
call near ptr Writestring
call near ptr Readint; in put an integer
call near ptr Crlf
movbx,16display in hexidecimal
call near ptr Writeint
call near ptr Crlf
mov bx,2; display in binary
call near ptr Writeint
movdx,offset pressAnyKey
call near ptr Writestring
call near ptr Readkey
call near ptr Clrscr
movax,4C00h
int 21h
main endp
end main

; ----------------------(END OF PROGRAM LISTING)--------------------------------

With this program, you are required to link to the irvine.lib after compiling to an .obj with MASM. There fore, use link /co lnkdemo and when it asks you for the .lib to link to - enter 'c:\irvine.lib' or where ever the irvine.lib was unzipped to enter.

This is an excellent example of using an external library for simplifying complex assembly operations.

After the title, .stack, and .model directives come two constants (WhiteOnBlue & GreetingLoc). These constants are declared out side the .data segment because the compiler does not include them as data in the program but rather replaces their labels when used in side the code segment with the value of the constant.

Next, comes the .data segment of the program. This is where we declare four strings, with terminators at the end of the strings. These strings will be loaded at the start of the .code segment with the first mov commands. The mov command will load ax with the @data location and then point ds to ax thus initialising the .data segment.

Now, the first few lines after the .code declaration start with the label 'extrn' followed by some procedure names. These procedures are 'external' to the program .code segment but are used in side it. The extrn command tells the compiler to look in a different segment to this one to find these procedures.

The rest of the code is simply loading registers with the correct values for the external procedures to use. For example, the Writestring procedure requires the offset of the message (terminated, obviously) to display to be loaded in to the dx register before calling Writestring. There are many examples of calls through out this program listing. If you also notice, the call statement has a 'near ptr' in between the call and procedure being called.

This 'near ptr' declaration tells the compiler not to look too far for the procedure in side the code block. That means, to use a memory model that is probably 16-bits wide rather than 32-bits wide for a far ptr. This, in turn, decreases the amount of RAM used for calling the procedures. Further more, 'near ptr' is required by MASM because with out it, MASM craps out with an error message if it is not included. Quicks of the job, I guess.

Procedures and Interrupts

Now that we have covered some of the fundamentals of assembly programming, we can look to increase our knowledge base with writing our own procedures and also take a look at some other INT (interrupts.)

The next program has no out put, there fore we suggest you run it with CV to see the state of the registers when the program is ran. This is because the program asks for in put in one sub-routine, and another sub-routine processes two arrays in an addition of integers in side registers to observe via CV.

Compile as usual, with masm and link - but this time you are not required to use the irvine.lib with this assembly.

;---------------------------------(START OF PROGRAM LISTING)-------------------------------------
title Subroutine Demonstration(SUBS.ASM)
; This program calls two subroutines: one for
; keyboard input, another to add the elements
; in an array of integers.
.model small
.stack 100h
.data
char db ?
sum dw ?
array dw 100h,200h,300h,400h,500h
array_size = 5
.code
main proc
movax,@data; set up the DS register
mov ds,ax
call near ptr inputChar; input keyboard into AL
mov char,AL; store in a variable
; prepare to call the calcSum procedure.
movbx,offset array; BX points to array
movcx,array_size; CX = array count
call near ptr calcSum; calculate sum
movsum,ax; store in a variable
movax,4C00h; return to DOS
int 21h
main endp
inputChar proc
movah,1; input character from keyboard
int 21h
ret
inputChar endp
;-----------------------------------------------
; Calculate the sum of an array of integers. Input:
; BX points to the array and CX contains the
; array size. Returns the SUM in AX.
;-----------------------------------------------
calcSum proc
push bx; save BX, CX
push cx
movax,0
CS1:
add ax,[bx]
addbx,2; point to next integer
loop CS1
pop cx
pop bx
ret
calcSum endp
end main

; -------------------(END OF PROGRAM LISTING)------------------------------------

This is a relatively short program to illustrate what makes assembly programs powerful (and some times bloated!) The sub-routines, or procedures, can extend a programs functionality and make it modular. Eventually, when you have written a collection of sub-routines or procedures (the two names are interchangeable) then you will want to include them in a library, just like K.R. Irvine did in his 32-bit assembly book.

As you can see in this program - it starts out with a title and .data segment and moving the @data segment in to AX and then AX in to DS so DS points to the start of the data segment. But, now directly after that we have a call to a procedure what is written after the main proc as a proc of its own called inputChar proc. This inputChar procedure receives a character from key board in put.

We again use 'near ptr' because MASM can not handle any thing other wise. Perhaps Turbo Assembler by Borland would do better?

Now, following this call to inputChar, we loads the registers with the correct values for the call to the procedure calcSum. This procedure, adds up the numbers stored in the array of integers (100h,200h,300h...) This routine eventually returns with the SUM in AX. This AX word pointer has the data pointed to put in to a variable called 'sum' with the mov sum,ax command.

A point worth noting of the calcSum procedure - is it introduces some new commands called push and pop. These commands relate to the stack declared at the start of the program with the .stack 100h directive. This stack grows downwards in memory. There fore, what ever is put on the stack last, is the first to be taken off! This is why the push commands are a mirror image of the pop commands. DX,CX is pushed where as CX,DX is popped from the stack. Try and visualise it in your head - memory locations starting at 0000:0100H - moving downwards to 0000:0090h to 0000:0080h as each value is put on to the stack. The stack pointer decreases or increases its memory location with each push and pop.

Well, we will winky take a look at the stack more in subsequent chapters of this tutorial.

Also, in the calcSum procedure you see the 'add' command. This creates a simple addition via one register and a data. The data could be another register [bx] or a variable offset var1.

Video Page Swapping Example

Graphics starter program

title Video Page Swapping Example(page.asm)
; This program switches back and forth between
; text pages 0 and 1 on a colour display.
.model small
.stack 100h
.data
page0 db 'This is video page zero.$'
page1 db 'This is video page one.$'
.code
main proc
mov ax,@data; Initialise the DS register
movds,ax
movah,9; Display a message
movdx, offset page0
int 21h
to_page_1:
movah,5; set video page
moval,1; to page 1
int 10h
movah,9; display a message
movdx,offset page1
int 21h
movah,1; get keystroke
int 21h
to_page_0:
movah,5; set video page
moval,0; to page 0
int 10h
movax,4c00h; return to DOS
int 21h
main endp
end main

PAGES.ASM DESTRUCTION

The program starts with the usual suspects of title,.model, and .stack. There is the .data and .code segements as per usual. At the start, as with all .data segment programs, we initialise the .data segment via AX to DS. Then, we start calling DOS INT 21h (DOS Interrupt) to display a message (mov ah,9) via dx with dx loaded with the offset of the page0 message.

Then, we turn to INT 10h, the video Interrupt - with ah,5 loaded (set video page) and al,0 (to this page number) and call INT 10h. Then we repeat calling INT 21h with ah,9 loaded to display message in dx with offset page1.

Using labels to_page_0: and to_page_1: etc... we can navigate between program segments. Eventually, as per usual, at the end of the program, we call DOS INT 21h with ax,4c00h loaded (return to DOS.)

For a little trial of your own - try using the jmp to_page_1: command to loop back to the initial to_page_1: segment for a continuous looping program. You'll have to press Ctrl+C or Ctrl+D to exit this program - or just simply exit DOS command.com. IF you exit DOS - remember to run autoexec.bat to set the PATH=%PATH% variables again!

Conditional Jumps

Using conditional jumps to direct program flow.

title Test Alphabetic Input(ISALPHA.ASM)
; This program reads and displays characters
; until a non-alphabetic character is entered.
.model small
.stack 100h
.code
main proc
movax,@data
movds,ax
L1:
mov ah,1; input a character
int 21h; AL = character
call near ptr Isalpha; test value in AL
jnzexit; exit if not alphabetic
jmpL1
exit:
movax,4c00h; return to DOS
int 21h
main endp
; Isalpha sets ZF = 1 if the character
; in AL is alphabetic.
Isalpha proc
pushax; save AX
andal,11011111b; convert to uppercase
cmpal,'A'; check A to Z range
jbB1; jump if below the ASCII code for A
cmpal,'Z'; check A to Z range
jaB1; jump if above the ASCII code for Z
testax,0; ZF = 1
B1:
popax; restore AX
ret
Isalpha endp
end main

XOR Encryption Program

Title Encryption Program(encrypt.asm)
.model small
.stack 100h
XORVAL = 239; any value between 0-255
.code
main proc
mov ax,@data
movds,ax
L1:
movah,6; direct console input
movdl,0FFh; do not wait for character
int 21h; AL = character
jzL2; quit if ZF = 1 (EOF)
xoral,XORVAL; encrypt the char
movah,2; write to output
movdl,al
int 21h
jmp L1; repeat the loop
L2:
movax,4c00h; return to DOS
int 21h
main endp
end main

Using encrypt.exe

encrypt < plain.txt > coded
encrypt < coded > plain.txt

This is a simple two way system for encryption. First, input the plain text file in to encrypt with out put going to coded file. Then to decrypt coded, in put coded file in to encyrpt with out put going to a plain text file.

Interger Arithmetic

Display ASCII binary Program

title Display ASCII Binary(BIN.ASM)
; This program displays a number in binary.
.model small
.stack 100h
.data
prompt db "Enter a decimal integer: ",0
.code
extrn Clrscr:proc,Crlf:proc
extrn Readint:proc,Writestring:proc
main proc
movax,@data
movds,ax
; prompt for an integer:
call near ptr Clrscr
movdx,offset prompt
call near ptr Writestring
call near ptr Readint; read integer into AX
call near ptr Crlf
movcx,16; number of bits in AX
L1:
shlax,1; shift AX left into Carry Flag
movdl,'0'; choose '0' as default digit
jnc L2; if no carry, jump to L2
movdl,'1'; else move '1' to dl
L2:
push ax; save AX
movah,2; display DL
int 21h
pop ax; restore AX
loop L1; shift another bit to left
movax,4C00h; exit program
int 21h
main endp
end main
Structures and Macros

The following program is an example of structures. It uses a student data base for a premise on how to use structures. Structures are basically data blocks that can be initialised by other variables either with their own unique data or as a standard data model. This will be shown in greater detail in the program that follows this paragraph.

Student Structure Demonstration.

Title Structure Input Example(STRUC.ASM)
.model small
.stack 100h
STUNUMBER_SIZE = 7
LASTNAME_SIZE = 20
ACTIVE_STATUS = 1
STUDENT_COUNT = 5
typStudent struc
IdNum db STUNUMBER_SIZE + 1 dup(?)
Lastname db LASTNAME_SIZE + 1 dup(?)
Credits dw ?
Status db ?
typStudent ends
.data
progTitle db "Student Structure Demonstration",0
srec typStudent <>; create a blank student
; Initialise and declare a structure variable:
rec2 typStudent <"1234","Baker",32,ACTIVE_STATUS>
; Declare an array of students:
allStudents typStudent STUDENT_COUNT dup( <> )
.code
extrn Clrscr:proc,Writestring:proc,Readstring:proc
extrn Crlf:proc,Readint:proc
main proc
movax,@data
movds,ax
call near ptr Clrscr
movdx,offset progTitle
call near ptr Writestring
call near ptr Crlf
; Use a loop to input an array of students.
movsi,offset allStudents
movcx,STUDENT_COUNT
L1:
call near ptr InputStudent
addsi,SIZE typStudent
Loop L1
movax,4c00h
int 21h
main endp
; Input the fields for a single student from
; the console. Input parameter: SI points to the
; typStudent object.
InputStudent proc
pushax
pushcx
pushdx
movdx,si; point to the structure
adddx,IdNum; point to the IdNum field
movcx,STUNUMBER_SIZE
call near ptr Readstring; get the student ID
call near ptr Crlf
movdx,si
adddx,LastName
movcx,LASTNAME_SIZE
call near ptr Readstring; get the last name
call near ptr Crlf
call near ptr Readint; get the credits
mov(typStudent PTR [si]).Credits,ax
call near ptr Crlf
mov(typStudent PTR [si]).Status, ACTIVE_STATUS
popdx
popcx
popax
ret
InputStudent endp
end main

; ---------------------(END OF PROGRAM LISTING)-----------------------

In this above code program example, you see your first use of struc (structures.) These structures are much like objects in the Assembly world. They can be created at the start of the program, to be used through out the program via initialising variables to these structures. They can contain new data, or original data on structure declare - even empty data.

At the end of the program main procedure is the InputStudent procedure. This procedure is called in a loop with CX holding the student number count (5) and this will loop until CX is zero calling the InputStudent procedure on each loop. This is where you enter data at the console (with out out put telling you what data needs in putting - check the program code listing on what data needs in putting at what time...) and this in put data is stored in the student structures declared through out the program.

Numeric Conversions and Libraries

Character Filtering Example

title Character Filtering(XLAT.ASM)
; This program filters input from the console
; by screening out all ASCII codes less than
; 32 or greater than 127. Uses INT 16h for
; direct keyboard input.
.model small
.stack 100h
INPUT_LENGTH = 20
.data
validchars label byte
db 32 dup (0); invalid chars: 0-31
db 96 dup (0FFh); valid chars: 32-127
db 128 dup (0); invalid chars: 128-255
.code
main proc
movax,@data
movds,ax
movbx,offset validchars
movcx,INPUT_LENGTH
getchar:
movah,0; keyboard input
int 16h; CHAR is in AL
movdl,al; save copy in DL
xlat validchars; look up char in AL
oral,al; invalid char?
jz getchar; yes: get another
movah,2; no: output the char
int 21h
loop getchar
mov ax,4c00h
int 21h
main endp
end main

----------------------(END OF PROGRAM LISTING)-----------------

One of the best uses of XLAT is to filter out unwanted characters from a stream of text. Suppose we want to input a string of characters from the keyboard and echo only those with ASCII values from 32 to 127. We can set up a translate table, place a zero in each table position corresponding to an invalid character, and place 0FFh in each valid position:

validchars db 32 dup (0) ; invalid chars 0-31
db 96 dup (0FFh); valid chars 32-127
db 128 dup (0) ; invalid chars 128-255

If XLAT returns a value of zero in AL, we skip the character and jump back to the top of the loop. (When AL is ORed with itself, the Zero Flag is set if AL equals 0). If the character is valid, 0FFh is returned in AL , and we use INT 21h to display the character in DL.

Library Functions

Now we are slowly shifting along to the beat of assembly language. Let us take a look back at the irvine.lib library. This library stores a collection of routines to be used in programs through out this tutorial. If there is an extrn reference in a source code, you know you must include the irvine.lib during the link compiling section. But, there are more tricks of the trade when it comes to examing existing libraries and making your own libraries!

lib irvine.lib,con

This command, the lib command, with con after the comma at the end of the command, views a listing of the library contents. This is useful for dissecting the library. Yet, there is more...type lib /help for further details.

C:\>lib /help
Microsoft (R) Library Manager Version 3.20.010
Copyright (C) Microsoft Corp 1983-1992. All rights reserved.
USAGE: LIB library [options] [commands] [,listfile [,newlibrary]]
Options:
/?: display LIB options
/HELP: display help on LIB
/IGNORECASE: ignore case on names
/NOEXTDICTIONARY: do not build extended dictionary
/NOIGNORECASE: do not ignore case on names
/NOLOGO: do not display signon banner
/PAGESIZE:n: set library page size to n
Commands:
+name: add object file
-name: delete object file
-+name: replace object file
*name: copy (extract) object file
-*namemove (delete and extract) object file

To create a lbrary use this command: lib string;

Then add individual object files to the created library as follows: lib string +strwrite

Then as stated earlier, to view the listing of the library type: lib string,con

Disk Storage

Set Default Drive

mov ah,0Eh; set default drive
mov dl,0; select drive A
int 21h
mov numberOfDrives,al

To set the default disk drive, call function 0Eh and pass it a number in DL corresponding to the disk drive (A = 0, B = 1, C = 2, etc)

Get Default Drive

mov al,19h; get default drive
int 21h
mov current_drive,al

To find out which drive is currently the default, call DOS function 19h. DOS returns the number of the logged drive in AL (A = 0,B=1,C=2, etc)

Get Disk Free Space (36h)

This may be redundant now with much larger disks, but it is worth a try on a floppy I guess...

mov ah,36h; get disk space
mov dl,3; select drive C
int 21h
; Return values: AX = sectors per cluster
BX = available clusters
CX = bytes per sector
DX = clusters per drive
; (calculate disk free space)
push dx; clusters per drive
push cx; AX = AX * CX = bytes per cluster
push axAX = cluster size
push bxDX:AX = available bytes
; (get total disk capacity)
pop ax; cluster size
pop dx; clusters per drive
pop dx; DX:AX = total disk capacity

Get Current Directory (47h)

To get the current directory, call DOS function 47h with INT 21h. Pass a drive code in DL (default = 0, A=1,B=2,C=3,etc) and point DS:SI to a 64-byte buffer. In this buffer, DOS places a null terminated string with the full pathname from the root directory to the current directory (the drive letter and leading backslash are omitted)

.data
pathname db 64 dup(0); path stored here
.ocde
mov ah,47h; get current directory path
mov dl,0; on default drive
mov si,offset pathname
int 21h
jc display_error

Set Current Directory (3Bh)

.data
pathname db 'C:\ASM\PROGS',0
.code
mov ah,3Bh; set current directory
mov dx, offset pathname
int 21h
jc display_error

Create Subdirectory (39h)

.data
pathname db '\ASM',0
.code
mov ah,39h; create subdirectory
mov dx,offset pathname
int 21h
jc display_error
File Processing

Well, so far, we have covered quite a lot of ground. You will find now and in the previous chapter that we are not including full program listings but rather program excerpts - this is because you should now be talented enough in asm programming to write your own .data segment and initialise it to ds as well as call DOS with ax loaded with 4c00h to return to DOS safely.

In the following sections are some file commands, namely DOS related, that alter the file system to some degree.

Delete File (41h)

.data
filespec db "C:\Sample.obj",0
.code
mov ah,41h; delete file
mov dx,offset filespec
int 21h
jc display_error

If DOS fails and the carry flag is set, the possible error codes are 2 (file not found), 3 (path not found), and 5 (access denied because file is read only). To delete a file that is read only, you must first call Function 43h (change file mode) to change its attribute.

Rename File (56h)

.data
oldname db "prog1.asm",0
newname db "prog2.asm",0
.code
mov ah,56h; rename file
mov dx,offset oldname
mov di,offset newname
int 21h
jc display_error

The error codes are the same as Delete File (41h) but with one exception, 11h (not same device) which is where the filenames refer to files on different disks.

The following statements move prog1.asm from the current directory to the \asm\progs directory...

.data
oldname db "prog1.asm",0
newname db "\asm\progs\prog1.asm",0
.code
mov ah,56h; rename file
mov dx,offset oldname
mov di,offset newname
int 21h
jc display_error

File I/O Services

Create File (3Ch)

.data
newfile db "NEWFILE.DOC",0
handle dw ?
.code
mov dx,offset newfile
mov ah,3ch; function: create file
mov cx,0; normal file attrib.
int 21h
jc display_error
mov handle,ax

As you can see there is a moment during this program when a 0 gets moved into CX and this is the 'normal attribute'. There are other attributes you can move in to CX:

00h   Normal File
01h   Read-only File
02h   Hidden File
04h   System File

Well, that might be all well and good if you want to DESTROY an existing file, but what if you want to preserve an already existing file? Calling 3Ch will just zero the existing file to the beginning, so it is not a good idea to call that routine on an already existing file - another means follows - which you should use before calling 3Ch to check if a file is already existing before writing or reading it...

Create New File (5Bh)

.data
filename db "FILE1.DOC",0
.code
mov ah,5Bh; create new file
mov cx,0; normal attrib.
mov dx,offset filename
int 21h
jc error_routine

Error codes: If DOS sets the carry flag - the errors are as follows;

3 - PATH NOT FOUND

4 - TOO MANY FILES OPEN

5 - ACCESS DENIED

Another Solution to the Existing File Dilemma...

You can, instead of using 5Bh, use 3Dh (open file). Using 3Dh will set the carry flag if the file does not exist and return AX = 2 (file not found). Then you can safely use 3Ch to create your file. Sorted.

Open File (3Dh)

3Dh has several attributes - one of which is the 'open state' of the function call. This is basically if you want to open the file for reading,writing, or both.

AL   Mode

0   Input (read only)

1   Output (write only)

2 (INPUT-OUTPUT)

3Dh (Open File) Code segemnt

.data
filename db 'C:\FILE1.DOC',0
infilehandle dw ?
.code
mov ah,3Dh; function: open file
mov al,0; choose the input mode
mov dx,offset filename
int 21h; call DOS
jc display_error; ERRROR? Display error
mov infilehandle,ax; no error: save the file handle

Close File (3Eh)

To close a file, call function 3Eh and place the file handle in BX. It also sets the date and time of a file when closed...

.data
infile db 'B:\FILE1.DOC',0
infilehandle dw ?
.code
mov ah,3Eh; close the file handle
mov bx,infilehandle
int 21h
jc display_error

Read from File or Device (3Fh)

.data
buffersize = 512
filehandle dw ?
buffer db buffersize dup(0)
.code
mov ah,3Fh; read from file or device
mov bx,filehandleBX = file handle
mov cx,buffersize; number of bytes to read
mov dx,offset buffer; point to buffer
int 21h
jc Display_Error; error if CF = 1
cmp ax,cxcompare the bytes requested
jbe exityes: quit reading

Write to File or Device (40h)

.data
buffer db 100h dup(?); output buffer
handle dw ?; file handle
.code
write_to_file:
mov ah,40h; write to file or device
mov bx,handle; file handle returned by open
mov cx,100h; number of bytes to write
mov dx,offset buffer; DX points to the buffer
int 21h; write bytes
jc display_Error; ERROR? Display error
cmp ax,100h; all bytes written?
jne close_file; no? Disk is full

Conclusion

Well, we've come to the end of the tutorial. There are some parts I missed out on purpose, other parts I kept in for prosperities sake. But, overall, I believe with this tutorial you can start on your way to becoming an advanced assembly programmer. Use the Internet to search for more code snippets - hell - buy a book! But, most of all, keep reading, studying, and learning about assembly language. Because, high-level languages have their place, but nothing beats some raw machine code!



© APO Networks 2009 (Designed for Lynx)