|
Development Requirements
When start developing the exercise, have to use:
|
|
Use the template from Using MASM and replace the assembly code by .
If the code does not work, a demonstration will be requested by the instructor.
†Since related topics may not be covered completely by the due date, no penalty will be applied if submitted after the due date. However, you may lag behind if you are not able to submit it by then. In addition, the Exam I will cover the materials from the Programming Exercise I. Objective Design and implement an MASM assembly program, which displays a tic-tac-toe game. The purpose of this exercise is to get students ready for assembly programming and the second exercise, playing a tic-tac-toe game. |
| | 1|2|3
----- -----
| | 4|5|6
----- -----
| | 7|8|9
I (System) enter the next move: 5
| | 1|2|3
----- -----
|X| 4|5|6
----- -----
| | 7|8|9
| | 1|2|3
----- -----
| | 4|5|6
----- -----
| | 7|8|9
the instructor uses the following string:
board BYTE 0Dh, 0Ah, " | | 1|2|3"
BYTE 0Dh, 0Ah, " ----- -----"
BYTE 0Dh, 0Ah, " | | 4|5|6"
BYTE 0Dh, 0Ah, " ----- -----"
BYTE 0Dh, 0Ah, " | | 7|8|9", 0Dh, 0Ah, 0Dh, 0Ah, 0
# (offset) 0 1 23456789012345678901
where the numbers are offsets (not assembly code) and the new line, “0Dh 0Ah”, is two bytes long.
The offset of the (1-9) is found by using the following formula:
offset = 6 + [(move-1)%3]×2 + [(move-1)÷3]×44For example, if the move is 5, the offset is
6+[(5-1)%3]×2+[(5-1)÷3]×44=6+1×2+1×44=52mov eax, offset ; Load EAX with the offset. mov board[eax], 'X' ; Store the marker to the location, board+offset.Assuming the game has just started, entering the move 5 will result in the following board state:
| | 1|2|3 | | 1|2|3
----- ----- ----- -----
| | 4|5|6 ⇒ |X| 4|5|6
----- ----- ----- -----
| | 7|8|9 | | 7|8|9
MarkBoard.asm
|
TITLE Tic-Tac-Toe (MarkBoard.asm)
COMMENT!
*
* This program shows how to mark the game board.
*
!
INCLUDE Irvine32.inc ; Include Irvine32 macros and procedures
.data
board BYTE 0Dh, 0Ah, " | | 1|2|3"
BYTE 0Dh, 0Ah, " ----- -----"
BYTE 0Dh, 0Ah, " | | 4|5|6"
BYTE 0Dh, 0Ah, " ----- -----"
BYTE 0Dh, 0Ah, " | | 7|8|9", 0Dh, 0Ah, 0Dh, 0Ah, 0
prompt BYTE "Enter the next move (1..9): ", 0
temp DWORD ?
next DWORD ?
const3 BYTE 3
q BYTE ?
r BYTE ?
.code
main PROC
mov edx, OFFSET board
call WriteString ; Print the game board.
mov edx, OFFSET prompt
call WriteString
; Read the next move.
call ReadInt
mov next, eax ; Save the move, next = eax.
call MarkBoard ; Mark the game board.
mov edx, OFFSET board
call WriteString
exit
main ENDP
;;
;; MarkBoard Procedure
;;
;; offset = 6 + [(move-1)%3]×2 + [(move-1)÷3]×44
;;
MarkBoard PROC
pushad ; Save the registers.
mov eax, next
dec eax ; eax = move - 1
idiv const3 ; eax = (move-1) ÷ 3
mov q, al ; quotient: al
mov r, ah ; remainder: ah
movzx eax, r ; eax = remainder: ah
imul eax, eax, 2 ; eax = [(move-1)%3]×2
add eax, 6 ; eax = 6 + [(move-1)%3]×2
mov temp, eax ; temp = 6 + [(move-1)%3]×2
movzx eax, q ; eax = quotient: al
imul eax, eax, 44 ; eax = [(move-1)÷3]×44
add eax, temp ; eax = 6 + [(move-1)%3]×2 + [(move-1)÷3]×44
mov board[eax], 'X' ; Mark the move.
popad ; Pop the registers.
ret
MarkBoard ENDP
END main
|
| An execution example |
|
| Examples of Exercise I Execution |
Start Showing a Tic-Tac-Toe Game. You (User) pick a piece: (X or O) X | | 1|2|3 ----- ----- | | 4|5|6 ----- ----- | | 7|8|9 You (User) enter the next move: (1..9) 5 | | 1|2|3 ----- ----- |X| 4|5|6 ----- ----- | | 7|8|9 Continue?: (Y or N) Y I (System) enter the next move: 3 | |O 1|2|3 ----- ----- |X| 4|5|6 ----- ----- | | 7|8|9 Continue?: (Y or N) Y You (User) enter the next move: (1..9) 8 | |O 1|2|3 ----- ----- |X| 4|5|6 ----- ----- |X| 7|8|9 Continue?: (Y or N) N New game?: (Y or N) Y Start Showing a Tic-Tac-Toe Game. I (System) make the move: 4 | | 1|2|3 ----- ----- X| | 4|5|6 ----- ----- | | 7|8|9 Continue?: (Y or N) Y You (User) enter the next move: (1..9) 9 | | 1|2|3 ----- ----- X| | 4|5|6 ----- ----- | |O 7|8|9 Continue?: (Y or N) Y I (System) enter the next move: 7 | | 1|2|3 ----- ----- X| | 4|5|6 ----- ----- X| |O 7|8|9 Continue?: (Y or N) N New game?: (Y or N) N C:\ASM-workspace\Ex1\Debug\Project.exe (process 41384) exited with code 0 (0x0). Press any key to close this window . . . |
| No. | Directive | Description | |
|---|---|---|---|
| 1 | [name] BYTE initializer |
Defining byte | |
| 2 | [name] DWORD initializer |
Defining doubleword | |
| 3 | END [procid] |
Marks the last line of the program to be assembled. | |
| 4 | ENDP |
Marks the end of a procedure. | |
| 5 |
.IF |
IF statement | |
| 6 | OFFSET n |
Returns the offset of a data label. | |
| 7 | label PROC |
Identifies the beginning of a procedure. | |
| 8 | PROC … USES |
Lists the names of all registers modified within a procedure. | |
| 9 | PROTO |
Creates a prototype for an existing procedure. | |
| 10 | PTR |
Override the declared size of an operand. | |
| No. | Instruction | Description | |
| 1 | add r/m32, imm32 |
Add: r/m32: a 32-bit register or a 32-bit memory operand imm32: a constant 32-bit value Check MASM General-purpose Registers Example: add eax, temp
|
|
| 2 | cmp r/m32, imm32 |
Compare two operands: Example: cmp eax, 10
|
|
| 3 | dec r/m32 |
Decrement by 1: Example: dec eax
|
|
| 4 | call rel32 |
Call procedure: rel32: a 32-bit signed relative displacement Example: call WriteString
|
|
| 5 | idiv r/m32 |
Signed divide:EDX:EAX ÷ r/m32, with result stored inEAX := Quotient,EDX := Remainder.Example: idiv const3
|
|
| 6 | imul r32, r/m32, imm32 |
Signed multiply: doubleword register := r/m32 × immediate doubleword Example: imul eax, eax, 2
|
|
| 7 | je rel8 |
Jump short if equal (ZF=1):rel8: an 8-bit relative offset Example: je L1
|
|
| 8 | jmp rel16 |
Jump rel16: a 16-bit relative offset Example: jmp L1
|
|
| 9 | jne rel8 |
Jump short if not equal (ZF=0)rel8: an 8-bit relative offset Example: jne L1
|
|
| 10 | loop rel8 |
Loop according to ECX counter:Decrement count; jump short if count ≠ 0 Example: loop L1
|
|
| 11 | mov r32, imm32 |
Move: Example: mov edx, OFFSET board
|
|
| 12 | movzx r32, r/m16 |
Move with zero-extend: Example: movzx eax, r
|
|
| 13 | not r/m32 |
One’s complement negation: Example: not eax
|
|
| 14 | popad |
Pop all general-purpose registers: Example: popad
|
|
| 15 | pushad |
Push all general-purpose registers: Example: pushad
|
|
| 16 | ret |
Return from procedure: Example: ret
|
|
| 17 | sub r/m32, imm32 |
Subtract: Example: sub eax, 10
|
|
| Procedure | Call args | Return args | Description | Example |
|---|---|---|---|---|
Crlf |
None | None | Writes a carriage return/linefeed sequence (,) to standard output. | call Crlf |
Randomize |
None | None | Re-seeds the random number generator with the current time in hundredths of seconds. | call Randomize |
RandomRange |
EAX = n, the range |
EAX = random (0 to n-1) |
Generates an unsigned pseudo-random 32-bit integer in the range of 0 through (n-1). |
Get a random number from 1 to 100:
ranNum DWORD ? |
ReadChar |
None | AL = ASCII code |
Reads a single character from standard input and returns the character in the AL register.
The character is not echoed on the screen.
Waits for the character if none is currently in the input buffer.
|
charIn BYTE ?
|
WriteChar |
AL = the character to write |
None | Writes a single character to standard output. | mov al, '$' |
WriteString |
EDX = points to string |
None | Writes a null-terminated string to standard output. |
prompt BYTE "Enter your name: ", 0
|
|
“We used to play spin the bottle when I was a kid,” says comedy writer Gene Perret. “A girl would spin the bottle pointed to you when it stopped, the girl could either kiss you or give you a nickel. By the time I was 14, I owned my own house.” |