Irvine chapter 10 Structures and macros. A simple point struct used in next program COORD STRUCT X...
-
date post
19-Dec-2015 -
Category
Documents
-
view
233 -
download
0
Transcript of Irvine chapter 10 Structures and macros. A simple point struct used in next program COORD STRUCT X...
A simple point struct used in next program
COORD STRUCT
X WORD ?
Y WORD ?
COORD ENDS;; struct requires end-struct
3 points initialized to (1,1), (2,2), (3,3)TITLE Loop Through Array (AllPoints.asm); Loop through the array of points and set their; X and Y values.; Last update: 11/26/01INCLUDE Irvine32.inc;coor is already defined in smallwin referenced by irvine32.inc.data;;;I added a message up here; Create instances of the COORD structure,; assigning values to both X and Y:point1 COORD <5,10>point2 COORD <10,20>NumPoints = 3AllPoints COORD NumPoints DUP(<0,0>);;3 sets of int points.codemain PROC
mov edi,0 ; array indexmov ecx,NumPoints ; loop countermov ax,1 ; starting X, Y values
L1:mov (COORD PTR AllPoints[edi]).X,axmov (COORD PTR AllPoints[edi]).Y,axadd edi,TYPE COORDinc axLoop L1exit
main ENDPEND main• C:\Masm615>allpoints• just made point #1just made point #2just made point #3
An “employee”
typEmployee STRUCT
Idnum BYTE 9 DUP(0)
Lastname BYTE 30 DUP(0)
Years WORD 0
SalaryHistory DWORD 10 DUP(0)
typEmployee ENDS
Employee slide 1TITLE Intro to STRUCT (Struct1.asm)
INCLUDE Irvine32.inc
typEmployee STRUCTIdnum BYTE 9 DUP(0)Lastname BYTE 30 DUP(0)Years WORD 0SalaryHistory DWORD 10 DUP(0)
typEmployee ENDS
.data
worker typEmployee <>
; override all fields. Either angle brackets; or curly braces can be used:person1 typEmployee {"555223333"}person2 typEmployee <"555223333">
; override only the second field:person3 typEmployee <,"Jones">
; skip the first three fields, and; use DUP to initialize the last field:person4 typEmployee <,,,3 DUP(20000)>
Employee slide 2.codemain PROC; Get the offset of a field within a structure:
mov edx,OFFSET typEmployee.SalaryHistory
; The following generates an "undefined identifier" error:;mov edx,OFFSET Salary
; The TYPE, LENGTH, and SIZE operators can be applied; to the structure and its fields:
mov eax,TYPE typEmployee ; 82mov eax,SIZE typEmployeemov eax,SIZE workermov eax,SIZEOF workermov eax,TYPE typEmployee.SalaryHistory ; 4mov eax,LENGTH typEmployee.SalaryHistory ; 10mov eax,SIZE typEmployee.SalaryHistory ; 40
; The TYPE, LENGTH and SIZE operators can be applied; to instances of the structure:
mov eax,TYPE worker ; 82mov eax,TYPE worker.Years ; 2
; Indirect operands require the PTR operator:mov esi,offset workermov ax,(typEmployee PTR [esi]).Years
exitmain ENDPEND main
There is no output from the program but it is a model for building say an array of employees.
Structs can be nested…a rectangle consists of upper left/lower right coords
TITLE Nested Structures (Struct2.asm)
; This program shows how to declare nested; structures, and how to access the members.; Last update: 8/14/01.INCLUDE Irvine32.incRectangle STRUCT
UpperLeft COORD <>LowerRight COORD <>
Rectangle ENDS.datarect1 Rectangle <>rect2 Rectangle { }rect3 Rectangle { {10,20}, {5,15} }rect4 Rectangle < <10,20>, <5,15> >
.codemain PROC; Direct reference to a nested member.
mov rect1.UpperLeft.X,30; Using an indirect operand, access a; nested member.
mov esi,OFFSET rect1mov (Rectangle PTR [esi]).UpperLeft.Y, 40
; Get the offsets of individual members.mov edi,OFFSET rect2.LowerRightmov edi,OFFSET rect2.LowerRight.X
exitmain ENDPEND main
Showtime system time struct & output (I added clrscr)
SYSTEMTIME STRUCT wYear WORD ? wMonth WORD ? wDayOfWeek WORD ? wDay WORD ? wHour WORD ? wMinute WORD ? wSecond WORD ? wMilliseconds WORD ?SYSTEMTIME ENDS
• I added a bunch of output to the original
The rest of showtime.datasysTime SYSTEMTIME <>XYPos COORD <10,5>consoleHandle DWORD ?colonStr BYTE ":",0TheTimeIs BYTE "The time is ",0.codemain PROCcall clrscr; Get the standard output handle for the Win32 Console.
INVOKE GetStdHandle, STD_OUTPUT_HANDLEmov consoleHandle,eax
; Set the cursor position and get the local time zone.INVOKE SetConsoleCursorPosition, consoleHandle, XYPosINVOKE GetLocalTime,ADDR sysTimemov edx,offset yearcall writestringmovzx eax,sysTime.wYear ; yearcall WriteDeccall crlfmov edx,offset month ; call WriteStringmovzx eax,sysTime.wMonth ; monthcall crlfcall WriteDecmov edx,offset day ; ":"call WriteStringmovzx eax,sysTime.wdayofweek ; daycall WriteDec
call Crlfcall Crlfmov edx,OFFSET TheTimeIs ; "The time is "call WriteStringmovzx eax,sysTime.wHour ; hours
call WriteDecmov edx,offset colonStr ; ":"call WriteStringmovzx eax,sysTime.wMinute ; minutescall WriteDecmov edx,offset colonStr ; ":"call WriteStringmovzx eax,sysTime.wSecond ; seconds
call WriteDecexit
main ENDP
A drunkard’s walkC:\Masm615>walk25,2524,2523,2524,2524,2425,2425,2524,2524,2624,2523,2523,2623,2523,2623,2723,2623,2523,2422,2421,2422,2423,2423,2322,2322,2421,2421,2521,2420,2419,24
Main proc for drunkard’s walkINCLUDE Irvine32.incWalkMax = 30StartX = 25StartY = 25DrunkardWalk STRUCT
path COORD WalkMax DUP(<0,0>)pathsUsed WORD 0
DrunkardWalk ENDSDisplayPosition PROTO currX:WORD, currY:WORD.dataaWalk DrunkardWalk <>.codemain PROC
mov esi,offset aWalkcall TakeDrunkenWalkexit
main ENDP
The take-a-walk procTakeDrunkenWalk PROCLOCAL currX:WORD, currY:WORD;; Take a walk in random directions (north, south, east,; west).; Receives: ESI points to a DrunkardWalk structure; Returns: the structure is initialized with random values;-------------------------------------------------------
pushad; Point EDI to the array of COORD objects.
mov edi,esiadd edi,OFFSET DrunkardWalk.pathmov ecx,WalkMax ; loop countermov currX,StartX ; current X-locationmov currY,StartY ; current Y-location
Again:; Insert current location in array.mov ax,currXmov (COORD PTR [edi]).X,axmov ax,currYmov (COORD PTR [edi]).Y,axINVOKE DisplayPosition, currX, currY;;;this generates output….not shownmov eax,4 ; choose a direction (0-3)call RandomRange.IF eax == 0 ; North inc currY.ELSEIF eax == 1 ; South dec currY.ELSEIF eax == 2 ; West dec currX.ELSE ; East (EAX = 3) inc currX.ENDIF
next:add edi,TYPE COORD ; point to next COORDloop Again
finish:mov ax,WalkMax ; count the steps takensub ax,cxmov (DrunkardWalk PTR [esi]).pathsUsed, axpopadret
TakeDrunkenWalk ENDP
A bunch of useful macros• TITLE Useful Macros (Macro2.ASM)
• ; This program demonstrates several useful macros:• ; mGotoxy, mWrite, mWriteLn, mWriteStr, mReadStr,• ; and mDumpMem.• ; Last update: 8/17/01.
• INCLUDE Irvine32.inc
• ;-----------------------------------------------------• mWriteStr MACRO buffer• ;• ; Improved version of mWriteStr that checks for• ; a blank argument.• ;-----------------------------------------------------• IFB <buffer>• ECHO -----------------------------------------• ECHO * Error: parameter missing in mWriteStr• ECHO * (no code generated)• ECHO -----------------------------------------• EXITM• ENDIF• push edx• mov edx,OFFSET buffer• call WriteString• pop edx• ENDM
useful macros continued• ;-----------------------------------------------------• mWrite MACRO text• ;• ; No changes to this macro.• ;-----------------------------------------------------• LOCAL string• .data ;; local data• string BYTE text,0 ;; define the string• .code• push edx• mov edx,OFFSET string• call Writestring• pop edx• ENDM
• ;-----------------------------------------------------• ; This version supplies a default argument.
• mWriteLn MACRO text := < " " >• ;-----------------------------------------------------• mWrite text• call Crlf• ENDM
useful macros continued• ;-----------------------------------------------------• mGotoxyConst MACRO X:REQ, Y:REQ• ;• ; Set the cursor position• ; This version checks the ranges of X and Y.• ; are not used.• ;------------------------------------------------------• LOCAL ERRS ;; local constant• ERRS = 0• IF (X LT 0) OR (X GT 79)• ECHO Warning: First argument to mGotoxy (X) is out of range.• ECHO ********************************************************• ERRS = 1• ENDIF• IF (Y LT 0) OR (Y GT 24)• ECHO Warning: Second argument to mGotoxy (Y) is out of range.• ECHO ********************************************************• ERRS = ERRS + 1• ENDIF• IF ERRS GT 0 ;; if errors found,• EXITM ;; exit the macro• ENDIF• push edx• mov dh,Y• mov dl,X• call Gotoxy• pop edx• ENDM
useful macros continued• ;------------------------------------------------------• mReadStr MACRO bufferPtr, maxChars• ;• ; Read from standard input into a buffer.• ; EDX cannot be the second argument.• ;------------------------------------------------------• IFIDNI <maxChars> , <EDX>• ECHO Warning: EDX cannot be second argument to mReadStr.• ECHO ***************************************************• EXITM• ENDIF• push ecx• push edx• mov edx,bufferPtr• mov ecx,maxChars• call ReadString• pop edx• pop ecx• ENDM
useful macros continued• ;---------------------------------------------------• ShowRegister MACRO regName• LOCAL tempStr• ;• ; Display a register's name and contents.• ;---------------------------------------------------• .data• tempStr BYTE " ®Name=",0• .code• push eax
• ; Display the register name• push edx• mov edx,offset tempStr• call WriteString• pop edx
• ; Display the register contents• mov eax,regName• call WriteHex• pop eax• ENDM
• .data• message BYTE "Hello there",0• buffer BYTE 50 DUP(?)
• BadYValue TEXTEQU <Warning: Y-coordinate is !> 24>
• ShowWarning MACRO message• mWrite "&message"• ENDM
useful macros …a main drivercount = 4sumVal TEXTEQU %5 + count ; sumVal = 9
.codemain PROC
mGotoxyConst %5 * 10, %3 + 4
;ShowWarning %BadYValue
call Crlfcall Crlf
ShowRegister ECX
mReadStr OFFSET buffer,50 ; ok
mov edx,50;mReadStr buffer,edx ; generates warning
mGotoxyConst 10,20
mWrite "Line one"mWriteLn ; missing argumentmWriteLn "Line two"
mWrite <"Line three",0dh,0ah>
mWriteStr ; missing argument
exitmain ENDPEND main
Macro redefinition
• Macros can be redefined. For example, if you define a macro using – Somemac macro– ---– Endm
• All invocations to the macro use the current definition. But if, later, you use the same name again to (re)define the macro, the macro has been redefined and all subsequent invocations will use the new definition.
Another redefinition exampleINCLUDE Irvine16.inc.codecls macro
local skipjmp short skip
cls_sub proc nearpushaxor cx,cxmov dh,24mov dl,79mov bh, 7xor al,almov ah,6int 10hpoparet
cls_sub endpcls macro call cls_sub endmskip: cls
endmmain PROC
mov ax,@datamov ds,axclsexit
main ENDPEND main
Toupper macro
to_upper MACRO ch
LOCAL done
cmp ch,'a’
jb done
cmp ch,'z' ;;2 semicolons suppresses this comment in expansion
ja done ;but this comment would be displayed
sub ch,32
done:
ENDM
SWAP word macro
SWAP MACRO operand1, operand2
xchg AX,operand1
xchg AX,operand2
xchg AX,operand1
ENDM
16 bit GOTOXY Macro
GOTOXY MACRO Row, ColumnPUSH AXPUSH BXPUSH DXMOV AH, 02H;;rom bios codeMOV DH, RowMOV DL, ColumnMOV BH, 0;;video pageINT 10H ;;bios intPOP DXPOP BXPOP AXENDM
Recursive macro
pushall MACRO reg1, reg2, reg3, reg4, reg5, reg6
IFNB <reg1> ;; If parameter not blank
push reg1
;; push one register and
;; repeat
pushall reg2, reg3, reg4, reg5, reg6
ENDIF
ENDM
;;example call
pushall ax, bx, si, ds
pushall cs, es
Substitute operator (&)
Substitutes a parameter with the actual argument
sort2 MACRO cond, num1, num2
LOCAL done
push AX
mov AX,num1
cmp AX,num2
j&cond done
xchg AX,num2
mov num1,AX
done:
pop AX
ENDM
Literal-text string operator (< >)
* Treats the enclosed text as a single string literal rather
than separate arguments
* Syntax: <text>
range_error1 MACRO number,variable,range
err_msg&number DB '&variable: out of range',0
range_msg&number DB 'Correct range is &range',0
ENDM
• Invoking with
range_error1 1,<Assignment mark>,<0 to 25>
produces
err_msg1 DB 'Assignment mark: out of range',0
range_msg1 DB 'Correct range is 0 to 25',0
Literal-character operator (!)
* Treats the character literally without its default meaning
* Syntax: !character
range_error2 MACRO number,variable,range
err_msg&number DB '&variable: out of range - &range',0
ENDM
• Invoking with
range_error2 3,mark,<can!'!'t be !> 100>
produces
err_msg3 DB 'mark: out of range - can''t be > 100',0
* Without the ! operator, two single quotes will produce a single quote
in the output
Expression Evaluate operator (%)
* Expression is evaluated and its value is used to replace
the expression itself
* Syntax: %expression
init_arry MACRO element_size,name,size,init_value
name &element_size size DUP (init_value)
ENDM
• Assuming NUM_STUDENTS EQU 47
NUM_TESTS EQU 7
Invoking with
init_array Word,marks,%NUM_STUDENTS*NUM_TESTS,-1
produces
marks Word 329 DUP (-1)
Literal-character operator (!)
* Treats the character literally without its default meaning
* Syntax: !character
range_error2 MACRO number,variable,range
err_msg&number DB '&variable: out of range - &range',0
ENDM
• Invoking with
range_error2 3,mark,<can!'!'t be !> 100>
produces
err_msg3 DB 'mark: out of range - can''t be > 100',0
* Without the ! operator, two single quotes will produce a single quote
in the output
Generating data for dictionary program using repeat macro, & and %
;will generate data like:
;wd0 byte 20 dup(0)
;wd1 byte 20 dup(0)
;wd2 byte 20 dup(0)
include irvine32.inc
gen macro val
wd&val byte 20 dup(0)
endm
.data
value=0
wct=20
repeat wct
gen %value
value=value+1
endm
.code
start proc
exit
start endp
end start
Similar but using for include irvine16.inc
.data
wordval label dword
for ctr,<0,1,2,3,4,5,6,7,8,9>
wordval&ctr dword ctr
endm
;;generates
;;wordval0 dword 0
;;etc
.code
main proc
mov ax,@data
mov ds,ax
mov ecx, 9
mov di,0
up:
mov eax,wordval[di]
call writeint
add di,4
call crlf
loop up
exit
main endp
end main
And using this with % to add numbers up
include irvine16.inc ;;32 bit ok too
.data
wordval label dword
for ctr,<0,1,2,3,4,5,6,7,8,9>
wordval&ctr dword ctr
endm
sum macro c
add eax,wordval&c
endm
addup macro
count=0
while count LT 10
sum %count
count=count+1
endm
endm
continued
.code
main proc
mov ax,@data
mov ds,ax
xor eax,eax
addup
call writedec
exit
main endp
end main
A program with I/0 similar to wordsort:
include irvine16.inc
.data
words label byte
for ctr,<0,1,2,3,4,5,6,7,8,9>
words&ctr byte 10 dup(0)
endm
prompt byte 0ah,0dh,"enter",0ah,0dh,'$'
getstart & fill macros
getstart macro x,c
mov x,offset words&c
endm
fill macro
count=0
while count LT 5
print prompt
getstart edx,%count
call readstring
count=count+1
endm
endm
print macro x
pusha
mov ah,9;;DOS print…requires ‘$’ terminator
mov dx,offset x
int 21h
popa
endm
Show macro
show macro
count=0
while count LT 5
getstart edx,%count
call writestring
call crlf
count=count+1
endm
endm
Linked list part1TITLE Creating a Linked List (List.asm)
; This program shows how the STRUC directive; and the REPT directive can be combined to; create a linked list at assembly time.; Last update: 11/8/02
INCLUDE Irvine32.inc
ListNode STRUCT NodeData DWORD ? NextPtr DWORD ?ListNode ENDS
TotalNodeCount = 15NULL = 0Counter = 0
.dataLinkedList LABEL PTR ListNodeREPT TotalNodeCount
Counter = Counter + 1ListNode <Counter, ($ + Counter * SIZEOF ListNode)>
ENDMListNode <0,0> ; tail node
Linked list part2.codemain PROC
mov esi,OFFSET LinkedList
; Display the integers in the NodeData members.NextNode:
; Check for the tail node.mov eax,(ListNode PTR [esi]).NextPtrcmp eax,NULLje quit
; Display the node data.mov eax,(ListNode PTR [esi]).NodeDatacall WriteDeccall Crlf
; Get pointer to next node.mov esi,(ListNode PTR [esi]).NextPtrjmp NextNode
quit:exit
main ENDPEND main
Linklist2 a linklist on the stackC:\Masm615>linklist2enter numbers... 999 to quit34enter numbers... 999 to quit56enter numbers... 999 to quit333enter numbers... 999 to quit12enter numbers... 999 to quit90enter numbers... 999 to quit609enter numbers... 999 to quit45enter numbers... 999 to quit32enter numbers... 999 to quit665enter numbers... 999 to quit435enter numbers... 999 to quit354enter numbers... 999 to quit09enter numbers... 999 to quit54enter numbers... 999 to quit999549354435665324560990123335634
C:\Masm615>
Linklist2…build arbitrary size list (up to stack allocation)
ListNode STRUCT NodeData DWORD ? NextPtr DWORD ?ListNode ENDS
TotalNodeCount = 15;;;not usedNULL = 0Counter = 0
.datanullval dword 0prompt byte "enter numbers... 999 to quit",0;;;;LinkedList LABEL PTR ListNode
ListNode <0,0> ; tail node…not used
.code
Linklist2 mainmain PROCpush nullvalpush nullval;;;this is the tail ptrmov esi,esp;;;current node addressmore:
mov edx,offset promptcall writestringcall crlfcall readint;;;;;;here is where we get datacmp eax,999je doneInputmov ebp,esipush ebp ;;;this is the next node ptrpush eax;;;this is the datamov esi,esp;;;now this is the address of current node
jmp moredoneInput: NextNode:
; Check for the tail node.mov eax,(ListNode PTR [esi]).NextPtrcmp eax,NULLje quit; Display the node data.mov eax,(ListNode PTR [esi]).NodeDatacall WriteDeccall Crlf
; Get pointer to next node.mov esi,(ListNode PTR [esi]).NextPtrjmp NextNode
quit:exit
main ENDPEND main