Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: 80x86 Assembly with Masm: Tutorial IV

  1. #1
    Senior Member
    Join Date
    Sep 2001
    Posts
    138

    80x86 Assembly with Masm: Tutorial IV

    80x86 Assembly with Masm 5.0: Tutorial IV
    ferguson_travis@hotmail.com

    Previous tutorials can be found at http://www25.brinkster.com/cheeseball as can code examples.

    This tutorial will cover the definition of Arrays as well as File input/output using Microsoft Macro Assembler 5.00. Tutorial II has a link as to where to find the assembler and linker, Google.com is also another good reference.

    Arrays in MASM are quite simple. Inside the data segment (The part between the .data and .code) simply put “<varname> <type> <number> DUP(X)”. Where varname is the variable name you wish to declare, type is the type of variable it will be, number is the number of the types in the array, DUP means we are duplicating what is inside the brackets. And a simple code example:
    http://www25.brinkster.com/cheeseball/tut04-1.asm
    Code:
    .model small
    .stack
    .data
    array1	dw 50	DUP("A")	;Set array1 = 50 A's.
    
    .code
    start:
    mov ax, SEG array1		;Put address of data segment into ax
    mov ds, ax			;then into DS (we can't do this directly)
    lea di, array1			;put address of array1 into DI
    
    add di, 50			;move to position 50
    mov al, "$"			;put $ into al
    mov [di], al			;put the $ into DI at position 50	
    				;we now have 49 letter A's ending with a $
    
    mov ax, SEG array1		;Put segment address of array1 into AX
    mov ds, ax			;Then into DS
    mov dx, OFFSET array1	;text at DS:DX
    mov ah, 09h			;print text to screen
    int 21h				;Function 9h of Interrupt 21h
    
    mov ax, 4c00h			;Function 4c00h of Int 21h
    int 21h				;Return to OS
    
    end start			;End program (it starts at Start Label)
    As you can see in the above example, arrays open your programming style and let you do things that would otherwise be extremely difficult. We could have easily used any data type before the DUP command (i.e. DW, DB, BYTE, or DWORD). We can create any type of array (I used a character array because it will be the most common).

    Now we get to learn about a new register, the FLAGS register. This register is 16 bits and inside there are a series of flags which give the status of certain things the CPU has been doing. The CF flag is the first (and only for this tutorial) we will be working with. The CF flag is stored at the 0 bit of the register, in order to access this we will be working with a new instruction, LAHF, which loads the low byte of the FLAGS register into the high byte of the AX register, thus making AH = first 8 bits of FLAGS. Now that we know how to access FLAGS we need to find out how to only read one flag from it. This part is trivial using the SHL and SHR opcodes. SHL shifts everything in a register one place to the left so “0101” would become “1010” and “0001” would become “0010”. So now for a very wonderful example of how this will work:

    Code:
          LAHF                     ;put FLAGS into AH
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
                                          ;AH now holds CF flag value 0 or 1
    After this we can simply test AH for either 00h or 01h, TRUE or FALSE. There are far better ways to do this, mainly using the AND opcode. The MUCH easier way of doing this would be:

    Code:
    	LAHF
    	AND ah, 01h
    The SHL (and SHR) instructions both occupy 2 bytes of space. The AND instruction only takes up 3 bytes, thus we can either take up 14 bytes clearing the other flags out of AH or we can take up 3 bytes. Now for what we have all been waiting for, we are going to open, close, read, and write to a file. (to keep the size of this tutorial down we are not going to be doing this all in the same program, we will split it up into multiple programs).

    First of all, opening a file is quite a bit easier than it sounds (actually I think it is easier than in C). First of all, just like almost everything in assembly (at least x86 DOS programming) we are going to be using an interrupt. Most file IO operations are accomplished using INT 21h. To open a file we first need to know what function in INT 21h it is, and what values we must pass along with it. Here is that information
    Code:
    	AH = 3dh
    	AL = bit 0-2 is the Access mode
    		000 = Read Only
    		001 = Write Only
    		010 = Read/Write Mode
    	         bits 4-6 is the Sharing mode (DOS 3.5 and up).  (I never use these)
    		000 Compatibility mode
    		001 Deny all
    		010 deny write
    		011 deny read
    		100 deny none
    	DS:DX = SEGMENT:OFFSET of ASCIIZ pathname.  
    
    The output is as follows:
    	CF = 0 if it worked
    	AX = Handle if it worked
    	CF = 1 if we got an error
    	AX = Error Code
    		01h = missing file sharing program
    		02h = file not found
    		03h = path not found or no file exist at path
    		04h = no file handle available. 
    		05h = access denied
    		0ch = access mode not permitted
    As you can see, there is not that much more needed to open a file than is needed to print text to the screen, and there is also built in handling of errors we simply have the test the end results of opening the file and jump to the correct fix if there is an error. Now to learn how to close files.

    Code:
    Closing a File:
    	AX = 3e00h
    	BX = File Handle
    	
    The output of this will be:
    	CF = 0 if it worked
    	AX = nothing, it will be random
    	CF = 1 if function did not work.
    	AX = error code – 06h if file not opened or incorrect file handle
    Warning:  Do not call this with a 00h file handle as handle 00h is the STDIN and will lock your access to the machine.  
    
    Reading from a file or device:
    	AH = 3fh
    	BX = Handle
    	CX = Number of bytes to read from file
    	DS:DX = SEGMENT:OFFSET of buffer to hold info that is in the file
    The output will be:
    	CF = 0 if successful
    	AX = Number of bytes read
    	CF = 1 if an error occurred
    		05h = Access denied
    		06h = incorrect handle or file not opened
    	CF + AX = 0 then EOF (End of File)
    	CF = 0  AND  AX < CX  EOF or error occurred.
    
    Creating Files:
    	AH = 3ch
    	CX = File Attrib
    		Bit 0 = read only
    		Bit 1 = hidden file
    		Bit 2 = system file
    		Bit 3 = volume (ignore this one)
    		Bit 4 = directory (ignore this one too for now)
    		Bit 5 = archive bit
    		Bit 6-15 = reserved (do not touch)
    	DS:DX = ASCIIZ pathname
    The output is as follows: 
    	CF = 0 if successful
    	AX = File Handle
    	CF = 1 if an error occurred
    		03h = path not found
    		04h = no handle available.
    		05h = access denied
    
    Writing to files:
    	AH = 40h
    	BX = File Handle
    	CX = number of bytes to write
    	DS:DX = SEGMENT:OFFSET of information to write
    Now we have all the information needed to do anything with a file. All we need now is to learn how to use it. For doing this we have a very great and informative (slightly non optimized as I am using shl and shr instead of AND in the code) code example:
    http://www25.brinkster.com/cheeseball/tut04-2.asm

    Code:
    .model small
    .stack
    .data
       failedcf db "Failed to create file!$"
       generr   db "General error!$"
       readf    db "Read Failed!$"
       
       message  db "Message to put into blank file!$",0
       
       filename db "test.tst",0
       buffer   db 50 DUP ("$")
       handle   dw ?
       
    .code
    start:
       mov ax, @data                 ;Put data segment into AX
       mov ds, ax                    ;Then put it into DS
       
       mov ah, 3dh                   ;function 3dh of int 21h (open file)
       mov al, 02h                   ;for read/write mode
       mov dx, OFFSET filename       ;filename ASCIIZ at DS:DX
       int 21h                       ;Call interrupt to finish open
       
       mov handle, ax                ;put handle or error into handle
       
       LAHF                          ;put FLAGS into AH
       shl ah, 1                     ;shift ah left one
       shl ah, 1                     ;shift ah left one
       shl ah, 1                     ;shift ah left one
       shl ah, 1                     ;shift ah left one
       shl ah, 1                     ;shift ah left one
       shl ah, 1                     ;shift ah left one
       shl ah, 1                     ;shift ah left one
       shr ah, 1                     ;shift ah right one
       shr ah, 1                     ;shift ah right one
       shr ah, 1                     ;shift ah right one
       shr ah, 1                     ;shift ah right one
       shr ah, 1                     ;shift ah right one
       shr ah, 1                     ;shift ah right one
       shr ah, 1                     ;shift ah right one
                                     ;AH now holds CF flag value 0 or 1
       cmp ah, 00h                   ;if successful open
       je fileopen                   ;then goto fileopen
       cmp ah, 01h                   ;if not successful open
       je filenoopen                 ;then goto filenoopen
       
       filenoopen:
          cmp handle, 01h            ;if no file sharing software
          je generror                ;goto generror
          cmp handle, 02h            ;if file not found
          je filenotfound            ;goto filenotfound
          cmp handle, 03h            ;if path not found
          je filenotfound            ;goto filenotfound
          cmp handle, 04h            ;if no handle aval
          je generror                ;goto generror
          cmp handle, 05h            ;if access denied
          je generror                ;goto generror
          cmp handle, 0ch            ;if access mode not permitted
          je generror                ;goto generror
          jne generror               ;else goto generror
       
       generror:
          mov dx, OFFSET generr      ;print generr to screen
          mov ah, 09h                ;function 09h of int 21h (print text)
          int 21h                    ;call int 21h
          
          mov ax, 4c00h              ;function 4ch of int 21h (return to OS)
          int 21h                    ;call int 21h
          
       filenotfound:
          mov ah, 3ch                ;function 3c (create file) int 21h
          mov cx, 00h                ;no special attribs
          mov dx, OFFSET filename    ;ASCIIZ offset of filename
          int 21h                    ;create the file
          
          mov handle, ax             ;save handle into handle
          
          mov dx, OFFSET message     ;put offset of message into DX
          mov bx, handle             ;handle into BX
          mov cx, SIZEOF message     ;send into file message size
          mov ah, 40h                ;function 40h (write to file)
          int 21h                    ;call int 21h
          
          LAHF
          mov dh, ah
          
          mov ax, 3e00h              ;closing file (function 3eh of int 21)
          mov bx, handle             ;file with handle
          int 21h                    ;call int 21h
          
          mov ah, dh                 ;put old EFLAGS into AH
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
                                     ;AH now holds CF flag value 0 or 1
          cmp ah, 00h                ;if successful open
          je start                   ;then goto fileopen
          cmp ah, 01h                ;if not successful open
          je failedcreatefile        ;goto failedcreatefile
          
          failedcreatefile:
             mov dx, OFFSET failedcf ;offset of failedcf
             mov ah, 09h
             int 21h
             
             mov ax, 4c00h           ;return to DOS 
             int 21h                 ;call int 21h
             
       fileopen:
          mov ah, 3fh                ;read file
          mov bx, handle             ;file with handle in handle
          mov cx, 50                 ;num of chars to read
          mov dx, OFFSET buffer      ;offset to store at DS:DX
          int 21h                    ;call int to finish off
          
          LAHF                       ;put FLAGS into AH
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shl ah, 1                  ;shift ah left one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
          shr ah, 1                  ;shift ah right one
                                     ;AH now holds CF flag value 0 or 1
          cmp ah, 00h                ;if read worked
          je readsuccess             ;goto readsuccess
          cmp ah, 01h                ;if it did not work
          je readfailed              ;goto readfailed
          
          readfailed:
             mov dx, OFFSET readf    ;print text to screen func
             mov ah, 09h             ;function 09, int 21h
             int 21h                 ;call int 21h
             
             mov ax, 4c00h           ;RETURN TO OS
             int 21h
             
          readsuccess:
             mov ax, 3e00h           ;closing file (function 3eh of int 21)
             mov bx, handle          ;file with handle
             int 21h                 ;call int 21h
             
             mov dx, OFFSET buffer   ;print message at buffer
             mov ah, 09h             ;function 09h of int 21h
             int 21h                 ;call int 21h
             
             mov ax, 4c00h           ;return to OS int 21h end start
             int 21h
    end start
    Yeah, that is a LOT longer than the rest of the code used in all my tutorials. Sorry I think I got a little carried away with that one (not really, everything there is needed to keep the program flow logical). This code completes this tutorial and hopefully now we understand file handling and arrays in assembly. If anyone has any questions you can reach me at the email address above.
    http://www25.brinkster.com/cheeseball

    -- Do not dwell in the past, do not dream of the future, concentrate the mind on the present moment--

  2. #2
    Senior Member
    Join Date
    Oct 2001
    Posts
    638
    Nice tutorial dude. Seems you're fast becoming established as AO's resident Assembly guru .
    OpenBSD - The proactively secure operating system.

  3. #3
    Senior Member
    Join Date
    Oct 2001
    Posts
    385
    One question: Anyone know where I can get MASM (any version)?
    Preliminary operational tests were inconclusive (the dang thing blew up)

    \"Ask not what the kernel can do for you, ask what you can do for the kernel!\"

  4. #4
    Senior Member
    Join Date
    Sep 2001
    Posts
    138
    there was a link in tutorial 2 for a site that did have it...
    http://www25.brinkster.com/cheeseball

    -- Do not dwell in the past, do not dream of the future, concentrate the mind on the present moment--

  5. #5
    Senior Member
    Join Date
    Aug 2001
    Posts
    110
    Nice work cheeseball.
    Listen closely to your enemies. They tell you your faults.

  6. #6
    AO Antique pwaring's Avatar
    Join Date
    Aug 2001
    Posts
    1,409
    Excellent tutorials so far, I might start learning assembly if you can keep up the good work Cheesball!
    Paul Waring - Web site design and development.

  7. #7
    Senior Member
    Join Date
    Feb 2002
    Posts
    170
    Great work Cheeseball. I learn a lot every time. One question though.
    How much of the stuff you've written about can be apllied in Linux with NASM?

    Cheers,
    Mankan

    \"The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise.\"
    - Edsger Dijkstra

  8. #8
    Senior Member
    Join Date
    Sep 2001
    Posts
    138
    All of it technically can, although in linux printing to the screen and things of that nature are going to be slightly different, once you have seen how they are accomplished it should be quite easy to learn to use NASM in linux....basically the theory behind programming in assembly ports, although the code does not.
    http://www25.brinkster.com/cheeseball

    -- Do not dwell in the past, do not dream of the future, concentrate the mind on the present moment--

  9. #9
    Junior Member
    Join Date
    Nov 2002
    Posts
    13
    star_eng@hotmail.com

    HI I need a tutorial for MASM6.11, where can i find it

  10. #10
    Junior Member
    Join Date
    Jan 2003
    Posts
    18

    8086 Assembly language programming

    Hey guys, i'm writing a code in assembly language using Turbo Assembler 2.0. If anybody out there is using it too then maybe you can help me with my question. ( I just hope cheeseball can read this.)

    I'm creating in assembly language a game. To provide a good user interface i have a module which creates a window (with shadow). the width and height of the window depends on the coordinates passed into the stack.
    Now, because assembly language has no built-in functions, I have to write one which creates and destroys a window.

    Let's say I'll create a window with blue background and white foreground with these parameters: row1 = 10, col1=20, row2=20, col2=60.

    In assembly, I'll only invoke function 06 of int 10 like this:

    mov ah, 06
    mov al, 00
    mov bh, 17h
    mov cx, 0a14h
    mov dx, 143dh
    int 10h

    now, my problem is when i try to remove the window, the underlying screen data is removed too.

    how do i display this window so that when i remove it, the underlying data is also preserved?
    And, how do I allocate memory dynamically in assembly?
    Turn on. Tune in. Drop out.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •