Guessing Game in Assembly

This assembly language program is designed to create a very simple game where user is allowed to guess a hard coded number between 1 and 255. This hard coded number can be replaced by a randomly generated number using a “random number generator” for EMU8086, which is bit complex because EMU8086 do not contain an instruction to do this implicitly. Program will output if guess is higher or lower than the input number. The code is well commented so that it can be used by anyone who is interested in learning assembly language.

Assembler

This code is written for EMU8086

http://www.emu8086.com/


Flow of the Program

System will print a message saying “Please enter a valid number:” Enter a number and *** Press ENTER *** key to continue.

The approach used to code this program made validating so easy. Because of that such features are implemented in this program. This system do NOT require user to enter a three degit numbers.

Ex : Inputs like 32,1 are valid. They will be converted to nemeric representation.

34 = 034 (Implicitly)
1 = 001 (Implicitly)

Also is users enter a value out of rage such as -1, 256,….. system will print:

“Error – Number out of range!”

Finally, it asks if user wants to retry, when a correct guess is made.
DEMO RUN

*** means ‘Enter key’ is pressed ****

Please enter a valid number: 0
Value is More

Please enter a valid number: 128
Value is More

Please enter a valid number: 170

Value if Less

Please enter a valid number: 255
Value if Less

Please enter a valid number: 256
Error – Number out of range!

Please enter a valid number: -1
Error – Number out of range!

Please enter a valid number: 3333
Error – Number out of range!

Please enter a valid number: 169
You have made fine Guess!

Retry [y/n] ?

 

Source Code



; E091040066_A1.asm:

; Author:   Ayoma Gayan Wijethunga

; Date  :   03/05/2011

; ****** This code is written for EMU8086 *****

.model small
.stack 100h
.data

    number      db  169d    ;variable 'number' stores the random value

    ;declarations used to add LineBreak to strings
    CR          equ 13d
    LF          equ 10d

    ;String messages used through the application
    prompt      db  CR, LF,'Please enter a valid number : $'
    lessMsg     db  CR, LF,'Value if Less ','$'
    moreMsg     db  CR, LF,'Value is More ', '$'
    equalMsg    db  CR, LF,'You have made fine Guess!', '$'
    overflowMsg db  CR, LF,'Error - Number out of range!', '$'
    retry       db  CR, LF,'Retry [y/n] ? ' ,'$'

    guess       db  0d      ;variable user to store value user entered
    errorChk    db  0d      ;variable user to check if entered value is in range

    param       label Byte

.code

start:

    ; --- BEGIN resting all registers and variables to 0h
    MOV ax, 0h
    MOV bx, 0h
    MOV cx, 0h
    MOV dx, 0h

    MOV BX, OFFSET guess    ; get address of 'guess' variable in BX.
    MOV BYTE PTR [BX], 0d   ; set 'guess' to 0 (decimal)

    MOV BX, OFFSET errorChk ; get address of 'errorChk' variable in BX.
    MOV BYTE PTR [BX], 0d   ; set 'errorChk' to 0 (decimal)
    ; --- END resting

    MOV ax, @data           ; get address of data to AX
    MOV ds, ax              ; set 'data segment' to value of AX which is 'address of data'
    MOV dx, offset prompt   ; load address of 'prompt' message to DX

    MOV ah, 9h              ; Write string to STDOUT (for DOS interrupt)
    INT 21h                 ; DOS INT 21h (DOS interrupt)

    MOV cl, 0h              ; set CL to 0  (Counter)
    MOV dx, 0h              ; set DX to 0  (Data register used to store user input)

; -- BEGIN reading user input
while:

    CMP     cl, 5d          ; compare CL with 10d (5 is the maximum number of digits allowed)
    JG      endwhile        ; IF CL > 5 then JUMP to 'endwhile' label

    MOV     ah, 1h          ; Read character from STDIN into AL (for DOS interrupt)
    INT     21h             ; DOS INT 21h (DOS interrupt)

    CMP     al, 0Dh         ; compare read value with 0Dh which is ASCII code for ENTER key
    JE      endwhile        ; IF AL = 0Dh, Enter key pressed, JUMP to 'endwhile'

    SUB     al, 30h         ; Substract 30h from input ASCII value to get actual number. (Because ASCII 30h = number '0')
    MOV     dl, al          ; Move input value to DL
    PUSH    dx              ; Push DL into stack, to get it read to read next input
    INC     cl              ; Increment CL (Counter)

    JMP while               ; JUMP back to label 'while' if reached

endwhile:
; -- END reading user input

    DEC cl                  ; decrement CL by one to reduce increament made in last iteration

    CMP cl, 02h             ; compare CL with 02, because only 3 numbers can be accepted as IN RANGE
    JG  overflow            ; IF CL (number of input characters) is greater than 3 JUMP to 'overflow' label

    MOV BX, OFFSET errorChk ; get address of 'errorChk' variable in BX.
    MOV BYTE PTR [BX], cl   ; set 'errorChk' to value of CL

    MOV cl, 0h              ; set CL to 0, because counter is used in next section again

; -- BEGIN processing user input

; -- Create actual NUMERIC representation of
;--   number read from user as three characters
while2:

    CMP cl,errorChk
    JG endwhile2

    POP dx                  ; POP DX value stored in stack, (from least-significant-digit to most-significant-digit)

    MOV ch, 0h              ; clear CH which is used in inner loop as counter
    MOV al, 1d              ; initially set AL to 1   (decimal)
    MOV dh, 10d             ; set DH to 10  (decimal)

 ; -- BEGIN loop to create power of 10 for related possition of digit
 ; --  IF CL is 2
 ; --   1st loop will produce  10^0
 ; --   2nd loop will produce  10^1
 ; --   3rd loop will produce  10^2
 while3:

    CMP ch, cl              ; compare CH with CL
    JGE endwhile3           ; IF CH >= CL, JUMP to 'endwhile3

    MUL dh                  ; AX = AL * DH whis is = to (AL * 10)

    INC ch                  ; increment CH
    JMP while3

 endwhile3:
 ; -- END power calculation loop

    ; now AL contains 10^0, 10^1 or 10^2 depending on the value of CL

    MUL dl                  ; AX = AL * DL, which is actual positional value of number

    JO  overflow            ; If there is an overflow JUMP to 'overflow'label (for values above 300)

    MOV dl, al              ; move restlt of multiplication to DL
    ADD dl, guess           ; add result (actual positional value of number) to value in 'guess' variable

    JC  overflow            ; If there is an overflow JUMP to 'overflow'label (for values above 255 to 300)

    MOV BX, OFFSET guess    ; get address of 'guess' variable in BX.
    MOV BYTE PTR [BX], dl   ; set 'errorChk' to value of DL

    INC cl                  ; increment CL counter

    JMP while2              ; JUMP back to label 'while2'

endwhile2:
; -- END processing user input

    MOV ax, @data           ; get address of data to AX
    MOV ds, ax              ; set 'data segment' to value of AX which is 'address of data'

    MOV dl, number          ; load original 'number' to DL
    MOV dh, guess           ; load guessed 'number' to DH

    CMP dh, dl              ; compare DH and DL (DH - DL)

    JC greater              ; if DH (GUESS) > DL (NUMBER) cmparision will cause a Carry. Becaus of that if carry has been occured print that 'number is more'
    JE equal                ; IF DH (GUESS) = DL (NUMBER) print that guess is correct
    JG lower                ; IF DH (GUESS) < DL (NUMBER) print that number is less

equal:

    MOV dx, offset equalMsg ; load address of 'equalMsg' message to DX
    MOV ah, 9h              ; Write string to STDOUT (for DOS interrupt)
    INT 21h                 ; DOS INT 21h (DOS interrupt)
    JMP exit                ; JUMP to end of the program

greater:

    MOV dx, offset moreMsg  ; load address of 'moreMsg' message to DX
    MOV ah, 9h              ; Write string to STDOUT (for DOS interrupt)
    INT 21h                 ; DOS INT 21h (DOS interrupt)
    JMP start               ; JUMP to beginning of the program

lower:

    MOV dx, offset lessMsg  ; load address of 'lessMsg' message to DX
    MOV ah, 9h              ; Write string to STDOUT (for DOS interrupt)
    INT 21h                 ; DOS INT 21h (DOS interrupt)
    JMP start               ; JUMP to beginning of the program

overflow:

    MOV dx, offset overflowMsg ; load address of 'overflowMsg' message to DX
    MOV ah, 9h              ; Write string to STDOUT (for DOS interrupt)
    INT 21h                 ; DOS INT 21h (DOS interrupt)
    JMP start               ; JUMP to beginning of the program

exit:

; -- Ask user if he needs to try again if guess was successful
retry_while:

    MOV dx, offset retry    ; load address of 'prompt' message to DX

    MOV ah, 9h              ; Write string to STDOUT (for DOS interrupt)
    INT 21h                 ; DOS INT 21h (DOS interrupt)

    MOV ah, 1h              ; Read character from STDIN into AL (for DOS interrupt)
    INT 21h                 ; DOS INT 21h (DOS interrupt)

    CMP al, 6Eh             ; check if input is 'n'
    JE return_to_DOS        ; call 'return_to_DOS' label is input is 'n'

    CMP al, 79h             ; check if input is 'y'
    JE restart              ; call 'restart' label is input is 'y' ..
                            ;   "JE start" is not used because it is translated as NOP by emu8086

    JMP retry_while         ; if input is neither 'y' nor 'n' re-ask the same question

retry_endwhile:

restart:
    JMP start               ; JUMP to begining of program
return_to_DOS:
    MOV ax, 4c00h           ; Return to ms-dos
    INT 21h                 ; DOS INT 21h (DOS interrupt)
    end start

RET

Share

4 comments on “Guessing Game in Assembly

  1. AKINLABI OLUWAPELUMI EMMANUEL May 17, 2012 4:04 PM

    Programming is what i want to venture in to and i need a mentor like you. Please can i meet you online on and chat interface.kindly reply me and i will love my request to be granted sir.

    from obafemi awolowo university
    osun state
    Nigeria

  2. Ayoma June 1, 2012 10:04 PM

    Good to hear from you and I’m glad to hear that you are interested in programming. If you check left edge of this page, you’ll know how to contact me for more details…

  3. Mikel January 31, 2013 8:39 AM

    Thanks for this program. Can I just ask how will you edit the program so that you could count the number of times the user tried to guess and print it out when the program ends? Thanks

  4. Ayoma February 25, 2013 3:05 PM

    Hi Mikel,

    What you have to do is adding another variable on top to keep the count and incrementing that in each execution of “start” section (by adding INC instruction right below “start” label). Finally in the “retry_while” section you can print the value of variable into command line. Printing part can be somewhat difficult as you have to convert the numeric value to a String in order to print it via DOS intercept 21h. I will post the program with this addition as soon as possible.

    Regards,
    Ayoma.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>