; Sample variable declarations ; This sample file demonstrates how to declare and access some simple ; variables in an assembly language program. ; ; Randall Hyde ; ; ; Note: global variable declarations should go in the "dseg" segment: dseg segment para public 'data' ; Some simple variable declarations: character byte ? ;"?" means uninitialized. UnsignedIntVar word ? DblUnsignedVar dword ? ;You can use the typedef statement to declare more meaningful type names: integer typedef sword char typedef byte FarPtr typedef dword ; Sample variable declarations using the above types: J integer ? c1 char ? PtrVar FarPtr ? ; You can tell MASM & DOS to initialize a variable when DOS loads the ; program into memory by specifying the initial value in the operand ; field of the variable's declaration: K integer 4 c2 char 'A' PtrVar2 FarPtr L ;Initializes PtrVar2 with the ; address of L. ; You can also set aside more than one byte, word, or double word of ; storage using these directives. If you place several values in the ; operand field, separated by commas, the assembler will emit one byte, ; word, or dword for each operand: L integer 0, 1, 2, 3 c3 char 'A', 0dh, 0ah, 0 PtrTbl FarPtr J, K, L ; The BYTE directive lets you specify a string of characters byte enclosing ; the string in quotes or apostrophes. The directive emits one byte of data ; for every character in the string (not including the quotes or apostrophes ; that delimit the string): string byte "Hello world",0dh,0ah,0 dseg ends ; The following program demonstrates how to access each of the above ; variables. cseg segment para public 'code' assume cs:cseg, ds:dseg Main proc mov ax, dseg ;These statements are provided by mov ds, ax ; shell.asm to initialize the mov es, ax ; segment register. ; Some simple instructions that demonstrate how to access memory: lea bx, L ;Point bx at first word in L. mov ax, [bx] ;Fetch word at L. add ax, 2[bx] ;Add in word at L+2 (the "1"). add ax, 4[bx] ;Add in word at L+4 (the "2"). add ax, 6[bx] ;Add in word at L+6 (the "3"). mul K ;Compute (0+1+2+3)*123. mov J, ax ;Save away result in J. les bx, PtrVar2 ;Loads es:di with address of L. mov di, K ;Loads 4 into di mov ax, es:[bx][di] ;Fetch value of L+4. ; Examples of some byte accesses: mov c1, ' ' ;Put a space into the c1 var. mov al, c2 ;c3 := c2 mov c3, al Quit: mov ah, 4ch ;Magic number for DOS int 21h ; to tell this program to quit. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main
; Using Pointer Variables in an Assembly Language Program ; ; This short sample program demonstrates the use of pointers in ; an assembly language program. ; ; Randall Hyde dseg segment para public 'data' ; Some variables we will access indirectly (using pointers): J word 0, 0, 0, 0 K word 1, 2, 3, 4 L word 5, 6, 7, 8 ; Near pointers are 16-bits wide and hold an offset into the current data ; segment (dseg in this program). Far pointers are 32-bits wide and hold ; a complete segment:offset address. The following type definitions let ; us easily create near and far pointers nWrdPtr typedef near ptr word fWrdPtr typedef far ptr word ; Now for the actual pointer variables: Ptr1 nWrdPtr ? Ptr2 nWrdPtr K ;Initialize with K's address. Ptr3 fWrdPtr L ;Initialize with L's segmented adrs. dseg ends cseg segment para public 'code' assume cs:cseg, ds:dseg Main proc mov ax, dseg ;These statements are provided by mov ds, ax ; shell.asm to initialize the mov es, ax ; segment register. ; Initialize Ptr1 (a near pointer) with the address of the J variable. lea ax, J mov Ptr1, ax ; Add the four words in variables J, K, and L together using pointers to ; these variables: mov bx, Ptr1 ;Get near ptr to J's 1st word. mov si, Ptr2 ;Get near ptr to K's 1st word. les di, Ptr3 ;Get far ptr to L's 1st word. mov ax, ds:[si] ;Get data at K+0. add ax, es:[di] ;Add in data at L+0. mov ds:[bx], ax ;Store result to J+0. add bx, 2 ;Move to J+2. add si, 2 ;Move to K+2. add di, 2 ;Move to L+2. mov ax, ds:[si] ;Get data at K+2. add ax, es:[di] ;Add in data at L+2. mov ds:[bx], ax ;Store result to J+2. add bx, 2 ;Move to J+4. add si, 2 ;Move to K+4. add di, 2 ;Move to L+4. mov ax, ds:[si] ;Get data at K+4. add ax, es:[di] ;Add in data at L+4. mov ds:[bx], ax ;Store result to J+4. add bx, 2 ;Move to J+6. add si, 2 ;Move to K+6. add di, 2 ;Move to L+6. mov ax, ds:[si] ;Get data at K+6. add ax, es:[di] ;Add in data at L+6. mov ds:[bx], ax ;Store result to J+6. Quit: mov ah, 4ch ;Magic number for DOS int 21h ; to tell this program to quit. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main
; Sample variable declarations ; This sample file demonstrates how to declare and access some single ; dimension array variables in an assembly language program. ; ; Randall Hyde .386 ;Need to use some 80386 option segment:use16 ; addressing modes. dseg segment para public 'data' J word ? K word ? L word ? M word ? JD dword 0 KD dword 1 LD dword 2 MD dword 3 ; Some simple uninitialized array declarations: ByteAry byte 4 dup (?) WordAry word 4 dup (?) DwordAry dword 4 dup (?) RealAry real8 4 dup (?) ; Some arrays with initialized values: BArray byte 0, 1, 2, 3 WArray word 0, 1, 2, 3 DWArray dword 0, 1, 2, 3 RArray real8 0.0, 1.0, 2.0, 3.0 ; An array of pointers: PtrArray dword ByteAry, WordAry, DwordAry, RealAry dseg ends ; The following program demonstrates how to access each of the above ; variables. cseg segment para public 'code' assume cs:cseg, ds:dseg Main proc mov ax, dseg ;These statements are provided by mov ds, ax ; shell.asm to initialize the mov es, ax ; segment register. ; Initialize the index variables. Note that these variables provide ; logical indices into the arrays. Don't forget that we've got to ; multiply these values by the element size when accessing elements of ; an array. mov J, 0 mov K, 1 mov L, 2 mov M, 3 ; The following code shows how to access elements of the arrays using ; simple 80x86 addressing modes: mov bx, J ;AL := ByteAry[J] mov al, ByteAry[bx] mov bx, K ;AX := WordAry[K] add bx, bx ;Index*2 since this is a word array. mov ax, WordAry[bx] mov bx, L ;EAX := DwordAry[L] add bx, bx ;Index*4 since this is a double add bx, bx ; word array. mov eax, DwordAry[bx] mov bx, M ;BX := address(RealAry[M]) add bx, bx ;Index*8 since this is a quad add bx, bx ; word array. add bx, bx lea bx, RealAry[bx] ;Base address + index*8. ; If you have an 80386 or later CPU, you can use the 386's scaled indexed ; addressing modes to simplify array access. mov ebx, JD mov al, ByteAry[ebx] mov ebx, KD mov ax, WordAry[ebx*2] mov ebx, LD mov eax, DwordAry[ebx*4] mov ebx, MD lea bx, RealAry[ebx*8] Quit: mov ah, 4ch ;Magic number for DOS int 21h ; to tell this program to quit. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main
; Multidimensional Array declaration and access ; ; Randall Hyde .386 ;Need these two statements to option segment:use16 ; use the 80386 register set. dseg segment para public 'data' ; Indices we will use for the arrays. J word 1 K word 2 L word 3 ; Some two-dimensional arrays. ; Note how this code uses the "dup" operator to suggest the size ; of each dimension. B2Ary byte 3 dup (4 dup (?)) W2Ary word 4 dup (3 dup (?)) D2Ary dword 2 dup (6 dup (?)) ; 2D arrays with initialization. ; Note the use of data layout to suggest the sizes of each array. B2Ary2 byte 0, 1, 2, 3 byte 4, 5, 6, 7 byte 8, 9, 10, 11 W2Ary2 word 0, 1, 2 word 3, 4, 5 word 6, 7, 8 word 9, 10, 11 D2Ary2 dword 0, 1, 2, 3, 4, 5 dword 6, 7, 8, 9, 10, 11 ; A sample three dimensional array. W3Ary word 2 dup (3 dup (4 dup (?))) dseg ends cseg segment para public 'code' assume cs:cseg, ds:dseg Main proc mov ax, dseg ;These statements are provided by mov ds, ax ; shell.asm to initialize the mov es, ax ; segment register. ; AL := B2Ary2[j,k] mov bx, J ;index := (j*4+k) add bx, bx ;j*2 add bx, bx ;j*4 add bx, K ;j*4+k mov al, B2Ary2[bx] ; AX := W2Ary2[j,k] mov ax, J ;index := (j*3 + k)*2 mov bx, 3 mul bx ;(j*3)-- This destroys DX! add ax, k ;(j*3+k) add ax, ax ;(j*3+k)*2 mov bx, ax mov ax, W2Ary2[bx] ; EAX := D2Ary[i,j] mov ax, J ;index := (j*6 + k)*4 mov bx, 6 mul bx ;DX:AX := j*6, ignore overflow in DX. add ax, k ;j*6 + k add ax, ax ;(j*6 + k)*2 add ax, ax ;(j*6 + k)*4 mov bx, ax mov eax, D2Ary[bx] ; Sample access of a three dimensional array. ; ; AX := W3Ary[J,K,L] mov ax, J ;index := ((j*3 + k)*4 + l)*2 mov bx, 3 mul bx ;j*3 add ax, K ;j*3 + k add ax, ax ;(j*3 + k)*2 add ax, ax ;(j*3 + k)*4 add ax, l ;(j*3 + k)*4 + l add ax, ax ;((j*3 + k)*4 + l)*2 mov bx, ax mov ax, W3Ary[bx] Quit: mov ah, 4ch ;Magic number for DOS int 21h ; to tell this program to quit. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main
; Sample Structure Definitions and Accesses. ; ; Randall Hyde dseg segment para public 'data' ; The following structure holds the bit values for an 80x86 mod-reg-r/m byte. mode struct modbits byte ? reg byte ? rm byte ? mode ends Instr1Adrs mode {} ;All fields uninitialized. Instr2Adrs mode {} ; Some structures with initialized fields. axbx mode {11b, 000b, 000b} ;"ax, ax" adrs mode. axdisp mode {00b, 000b, 110b} ;"ax, disp" adrs mode. cxdispbxsi mode {01b, 001b, 000b} ;"cx, disp8[bx][si]" mode. ; Near pointers to some structures: sPtr1 word axdisp sPtr2 word Instr2Adrs dseg ends cseg segment para public 'code' assume cs:cseg, ds:dseg Main proc mov ax, dseg ;These statements are provided by mov ds, ax ; shell.asm to initialize the mov es, ax ; segment register. ; To access fields of a structure variable directly, just use the "." ; operator like you would in Pascal or C: mov al, axbx.modbits mov Instr1Adrs.modbits, al mov al, axbx.reg mov Instr1Adrs.reg, al mov al, axbx.rm mov Instr1Adrs.rm, al ; When accessing elements of a structure indirectly (that is, using a ; pointer) you must specify the structure type name as the first ; "field" so MASM doesn't get confused: mov si, sPtr1 mov di, sPtr2 mov al, ds:[si].mode.modbits mov ds:[di].mode.modbits, al mov al, ds:[si].mode.reg mov ds:[di].mode.reg, al mov al, ds:[si].mode.rm mov ds:[di].mode.rm, al Quit: mov ah, 4ch ;Magic number for DOS int 21h ; to tell this program to quit. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main
; Arrays of Structures ; ; Randall Hyde dseg segment para public 'data' ; A structure that defines an (x,y) coordinate. ; Note that the Point data type requires four bytes. Point struct X word ? Y word ? Point ends ; An uninitialized point: Pt1 Point {} ; An initialized point: Pt2 Point {12,45} ; A one-dimensional array of uninitialized points: PtAry1 Point 16 dup ({}) ;Note the "{}" inside the parens. ; A one-dimensional array of points, all initialized to the origin. PtAry1i Point 16 dup ({0,0}) ; A two-dimensional array of points: PtAry2 Point 4 dup (4 dup ({})) ; A three-dimensional array of points, all initialized to the origin. PtAry3 Point 2 dup (3 dup (4 dup ({0,0}))) ; A one-dimensional array of points, all initialized to different values: iPtAry Point {0,0}, {1,2}, {3,4}, {5,6} ; Some indices for the arrays: J word 1 K word 2 L word 3 dseg ends ; The following program demonstrates how to access each of the above ; variables. cseg segment para public 'code' assume cs:cseg, ds:dseg Main proc mov ax, dseg ;These statements are provided by mov ds, ax ; shell.asm to initialize the mov es, ax ; segment register. ; PtAry1[J] := iPtAry[J] mov bx, J ;Index := J*4 since there are four add bx, bx ; bytes per array element (each add bx, bx ; element contains two words). mov ax, iPtAry[bx].X mov PtAry1[bx].X, ax mov ax, iPtAry[bx].Y mov PtAry1[bx].Y, ax ; CX := PtAry2[K,L].X; DX := PtAry2[K,L].Y mov bx, K ;Index := (K*4 + J)*4 add bx, bx ;K*2 add bx, bx ;K*4 add bx, J ;K*4 + J add bx, bx ;(K*4 + J)*2 add bx, bx ;(K*4 + J)*4 mov cx, PtAry2[bx].X mov dx, PtAry2[bx].Y ; PtAry3[j,k,l].X := 0 mov ax, j ;Index := ((j*3 +k)*4 + l)*4 mov bx, 3 mul bx ;j*3 add ax, k ;j*3 + k add ax, ax ;(j*3 + k)*2 add ax, ax ;(j*3 + k)*4 add ax, l ;(j*3 + k)*4 + l add ax, ax ;((j*3 + k)*4 + l)*2 add ax, ax ;((j*3 + k)*4 + l)*4 mov bx, ax mov PtAry3[bx].X, 0 Quit: mov ah, 4ch ;Magic number for DOS int 21h ; to tell this program to quit. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main
; Structures Containing Structures as fields ; Structures Containing Arrays as fields ; ; Randall Hyde dseg segment para public 'data' Point struct X word ? Y word ? Point ends ; We can define a rectangle with only two points. ; The color field contains an eight-bit color value. ; Note: the size of a Rect is 9 bytes. Rect struct UpperLeft Point {} LowerRight Point {} Color byte ? Rect ends ; Pentagons have five points, so use an array of points to ; define the pentagon. Of course, we also need the color ; field. ; Note: the size of a pentagon is 21 bytes. Pent struct Color byte ? Pts Point 5 dup ({}) Pent ends ; Okay, here are some variable declarations: Rect1 Rect {} Rect2 Rect {{0,0}, {1,1}, 1} Pentagon1 Pent {} Pentagons Pent {}, {}, {}, {} Index word 2 dseg ends cseg segment para public 'code' assume cs:cseg, ds:dseg Main proc mov ax, dseg ;These statements are provided by mov ds, ax ; shell.asm to initialize the mov es, ax ; segment register. ; Rect1.UpperLeft.X := Rect2.UpperLeft.X mov ax, Rect2.Upperleft.X mov Rect1.Upperleft.X, ax ; Pentagon1 := Pentagons[Index] mov ax, Index ;Need Index*21 mov bx, 21 mul bx mov bx, ax ; Copy the first point: mov ax, Pentagons[bx].Pts[0].X mov Pentagon1.Pts[0].X, ax mov ax, Pentagons[bx].Pts[0].Y mov Pentagon1.Pts[0].Y, ax ; Copy the second point: mov ax, Pentagons[bx].Pts[2].X mov Pentagon1.Pts[4].X, ax mov ax, Pentagons[bx].Pts[2].Y mov Pentagon1.Pts[4].Y, ax ; Copy the third point: mov ax, Pentagons[bx].Pts[4].X mov Pentagon1.Pts[8].X, ax mov ax, Pentagons[bx].Pts[4].Y mov Pentagon1.Pts[8].Y, ax ; Copy the fourth point: mov ax, Pentagons[bx].Pts[6].X mov Pentagon1.Pts[12].X, ax mov ax, Pentagons[bx].Pts[6].Y mov Pentagon1.Pts[12].Y, ax ; Copy the fifth point: mov ax, Pentagons[bx].Pts[8].X mov Pentagon1.Pts[16].X, ax mov ax, Pentagons[bx].Pts[8].Y mov Pentagon1.Pts[16].Y, ax ; Copy the Color: mov al, Pentagons[bx].Color mov Pentagon1.Color, al Quit: mov ah, 4ch ;Magic number for DOS int 21h ; to tell this program to quit. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main
; Pointers to structures ; Pointers to arrays of structures ; ; Randall Hyde .386 ;Need these two statements so option segment:use16 ; we can use 80386 registers dseg segment para public 'data' ; Sample structure. ; Note: size is seven bytes. Sample struct b byte ? w word ? d dword ? Sample ends ; Some variable declarations: OneSample Sample {} SampleAry Sample 16 dup ({}) ; Pointers to the above OnePtr word OneSample ;A near pointer. AryPtr dword SampleAry ; Index into the array: Index word 8 dseg ends ; The following program demonstrates how to access each of the above ; variables. cseg segment para public 'code' assume cs:cseg, ds:dseg Main proc mov ax, dseg ;These statements are provided by mov ds, ax ; shell.asm to initialize the mov es, ax ; segment register. ; AryPtr^[Index] := OnePtr^ mov si, OnePtr ;Get pointer to OneSample les bx, AryPtr ;Get pointer to array of samples mov ax, Index ;Need index*7 mov di, 7 mul di mov di, ax mov al, ds:[si].Sample.b mov es:[bx][di].Sample.b, al mov ax, ds:[si].Sample.w mov es:[bx][di].Sample.w, ax mov eax, ds:[si].Sample.d mov es:[bx][di].Sample.d, eax Quit: mov ah, 4ch ;Magic number for DOS int 21h ; to tell this program to quit. Main endp cseg ends sseg segment para stack 'stack' stk byte 1024 dup ("stack ") sseg ends zzzzzzseg segment para public 'zzzzzz' LastBytes byte 16 dup (?) zzzzzzseg ends end Main