Thursday, May 17, 2012

8086 Assembly (TASM): "Toy" Program

I thought I'd post this here, just in case I end up losing it and needing it later on.  Or whatever...

This was the assignment given:


Write a program to emulate a child's toy which is played by dropping a marble in one of the three holes ( A, B, or C ) at the top of the toy and watching the changes.  As the marble moves past switches, the values of the switch are changed.   The path which the marble will take is dependent upon the current state of the switch.  Your game display should look something like the following: the letters should be displayed, the numbers representing the switch positions, and the value of each switch which is initially a 0:



                   A                           B                           C
                   1                           2                           3
                   0                           0                           0
                                4                           5
                                0                           0
                   6                           7                           8
                   0                           0                           0


          Treat the toy as a multi-switch device with each switch having two states and being independent of each other.   Each switch's input and output are defined as follows:

          INPUT :
                   hole A :  the marble goes to Switch 1
                   hole B :  the marble goes to Switch 2
                   hole C :  the marble goes to Switch 3
          OUTPUT:
                   When Switch 1 is 0, the marble goes to Switch 6
                   When Switch 1 is 1, the marble goes to Switch 4
                   When Switch 2 is 0, the marble goes to Switch 5
                   When Switch 2 is 1, the marble goes to Switch 4
                   When Switch 3 is 0, the marble goes to Switch 5
                   When Switch 3 is 1, the marble goes to Switch 8
                   When Switch 4 is 0, the marble goes to Switch 7
                   When Switch 4 is 1, the marble goes to Switch 6
                   When Switch 5 is 0, the marble goes to Switch 8
                   When Switch 5 is 1, the marble goes to Switch 7
                   When Switch 6 is 0, the marble exits the Toy
                   When Switch 6 is 1, the marble exits the Toy
                   When Switch 7 is 0, the marble exits the Toy
                   When Switch 7 is 1, the marble exits the Toy
                   When Switch 8 is 0, the marble exits the Toy
                   When Switch 8 is 1, the marble exits the Toy

          The Toy starts with a display of the board having all switches set to 0.

          Accept the input from the keyboard (provide an appropriate prompt)  of A, B, or C which is the selection of the hole into which to drop the marble.  Calculate the state changes of the switches, change them, and then re-display the board in its new state. Continue until the proper exit code is provided.  You must idiot proof your program to ignore improper values.  Use of procedures and Macros as appropriate is required.
And here's the garbage that I regurgitated into Notepad!

; Toy.asm
; 
;    What the array looks like when not crammed onto one line.
;    a[0,0] is the array element at position [0,0].  and so on.
;    Essentially, there are 3 rows, just like the assignment description:
;        1st Row has 3 columns.
;        2nd Row has 2 columns.
;        3rd Row has 3 Columns. 
;        +--------+--------+--------+
;        | a[0,0] | a[0,1] | a[0,2] |
;        | OFF 0  | OFF 1  | OFF 2  |
;        +--------+--------+--------+
;          | a[1,0] | a[1,1] | 
;           | OFF 3  | OFF 4  | 
;        +--------+--------+--------+
;        | a[2,0] | a[2,1] | a[2,2] |
;        | OFF 6  | OFF 7  | OFF 8  |
;        +--------+--------+--------+

.MODEL small

.STACK 100h

.DATA
  ; 1FH = ON
  ; 7FH = OFF
  PRMPT1  DB 10, 10, 13, '[q] Or [Q] To Quit'
     DB 10, 10, 13, '[A], [B], [C] To Drop Ball: $'

  HEADER  DB 10, 10, 13, '          ', 41H, '          ', 42H, '          ', 43H, '$'                 ; A  B  C     
  
  LINE1A  DB 10, 10, 13, '          $'
  LINE1B  DB '          $'
  LINE1C  DB '          $'

  LINE2A  DB 10, 10, 13, '               $'
  LINE2B  DB '          $'

  LINE3A  DB 10, 10, 13, '          $'
  LINE3B  DB '          $'
  LINE3C  DB '          $'
  
  SWITCHES DB 1FH, 1FH, 1FH
     DB 1FH, 1FH
     DB 1FH, 1FH, 1FH
  
.CODE

 START PROC
   MOV AX, @DATA   ; Startup code.
   MOV DS, AX

  DRAWGAME:
    CALL CLRSCRN   ; Clear the screen
  
    MOV DX, OFFSET HEADER  ; Display menu
    MOV AH, 09H
    INT 21H

    MOV DX, OFFSET LINE1A  ; Draw Row 1, Col A
    MOV AH, 09H
    INT 21H

      MOV DL, SWITCHES + 0 ; Display switch 1 value.
      MOV AH, 02h             
      INT 21H                     
    
    MOV DX, OFFSET LINE1B  ; Draw Row 1, Col B
    MOV AH, 09H
    INT 21H

      MOV DL, SWITCHES + 1 ; Display switch 2 value.
      MOV AH, 02h             
      INT 21H                   
    
    MOV DX, OFFSET LINE1C  ; Draw Row 1, Col C
    MOV AH, 09H
    INT 21H    
    
      MOV DL, SWITCHES + 2 ; Display switch 3 value.
      MOV AH, 02h         
      INT 21H                 
    
    MOV DX, OFFSET LINE2A  ; Draw Row 2, Col B
    MOV AH, 09H
    INT 21H

      MOV DL, SWITCHES + 3  ; Display switch 4 value.
      MOV AH, 02h             
      INT 21H                 
    
    MOV DX, OFFSET LINE2B  ; Draw Row 2, Col C
    MOV AH, 09H
    INT 21H

      MOV DL, SWITCHES + 4  ; Display switch 5 value.
      MOV AH, 02h             
      INT 21H                 
       
    MOV DX, OFFSET LINE3A  ; Draw Row 3, Col A
    MOV AH, 09H
    INT 21H

      MOV DL, SWITCHES + 5  ; Display switch 6 value.
      MOV AH, 02h             
      INT 21H                 
    
    MOV DX, OFFSET LINE3B  ; Draw Row 3, Col B
    MOV AH, 09H
    INT 21H

      MOV DL, SWITCHES + 6  ; Display switch 7 value.
      MOV AH, 02h             
      INT 21H                 
    
    MOV DX, OFFSET LINE3C  ; Draw Row 3, Col C
    MOV AH, 09H
    INT 21H 

      MOV DL, SWITCHES + 7  ; Display switch 8 value.
      MOV AH, 02h             
      INT 21H                     

    MOV DX, OFFSET PRMPT1  ; Display menu
    MOV AH, 09H
    INT 21H 
   
  GETINPUT:
   MOV AX, 0
   MOV AH, 08H    ; Get user input.
   INT 21H
   
   CMP_bA:
    CMP AL, 41H    ; Is input = "A"?
    JNE CMP_sA    ; If not, check for "a".
    JMP SWITCH1    ;  If it is, Jump to Switch #1.
    
   CMP_sA:      
    CMP AL, 61H    ; Is input = "a"?
    JNE CMP_bB    ; If not, check for "B".
    JMP SWITCH1    ; If it is, jump to Swtich #1.
    
   CMP_bB:
    CMP AL, 42H    ; Is input = "B"?
    JNE CMP_sB    ; If not, check for "b".
    JMP SWITCH2    ; If it is, jump to Switch #2.
    
   CMP_sB:
    CMP AL, 62H    ; Is input = "b"?
    JNE CMP_bC    ; If not, check for "C".
    JMP SWITCH2    ; If it is, jump to Switch #2.
    
   CMP_bC:
    CMP AL, 43H    ; Is input = "C"?
    JNE CMP_sC    ; If not, check for "c".
    JMP SWITCH3    ; If it is, jump to Swtich #3.
    
   CMP_sC:
    CMP AL, 63H    ; Is input = "c"?
    JNE CMP_bQ    ; If not, check for "Q".
    JMP SWITCH3    ; If it is, jump to Switch #3.
    
   CMP_bQ:
    CMP AL, 51H    ; Is input = "Q"?
    JNE CMP_sQ    ; If not, check for "q".
    JMP EXITPROG   ; If it is, jump to EXITPROG.
    
   CMP_sQ:
    CMP AL, 71H    ; Is input = "q"?
    JNE GETINPUT   ; If it is not, then user did not enter any of the above keys.
    JMP EXITPROG   ; If it is, jump to EXITPROG.
   
  SWITCH1:  
   CMP [SWITCHES + 0], 7FH   ; if character in switch 1 is 7FH
   JE SWITCH1A
   
   CMP [SWITCHES + 0], 1FH   ; if character in switch 1 is 1FH.
   JE SWITCH1B   
   
   SWITCH1B:
    MOV [SWITCHES + 0], 7FH     ; switch character to OFF
    JMP SWITCH4

   SWITCH1A:
    MOV [SWITCHES + 0], 1FH    ; switch character to ON
    JMP SWITCH6
    
  SWITCH2:
   CMP [SWITCHES + 1], 7FH   ; if character in switch 2 is 7FH
   JE SWITCH2A
   
   CMP [SWITCHES + 1], 1FH   ; if character in switch 2 is 1FH.
   JE SWITCH2B   
   
   SWITCH2B:
    MOV [SWITCHES + 1], 7FH  ; switch character to OFF
    JMP SWITCH2

   SWITCH2A:
    MOV [SWITCHES + 1], 1FH  ; switch character to ON
    JMP SWITCH5
 
  SWITCH3:
   CMP [SWITCHES + 2], 7FH   ; if character in switch 3 is 7FH
   JE SWITCH3A
   
   CMP [SWITCHES + 2], 1FH   ; if character in switch 3 is 1FH.
   JE SWITCH3B   
   
   SWITCH3B:
    MOV [SWITCHES + 2], 7FH  ; switch character to OFF
    JMP SWITCH8

   SWITCH3A:
    MOV [SWITCHES + 2], 1FH  ; switch character to ON
    JMP SWITCH5
   
  SWITCH4:
   ; Code for Switch #4 goes here.
   CMP [SWITCHES + 3], 7FH   ; if character in switch 4 is 7FH
   JE SWITCH4A
   
   CMP [SWITCHES + 3], 1FH   ; if character in switch 4 is 1FH.
   JE SWITCH4B   
   
   SWITCH4B:
    MOV [SWITCHES + 3], 7FH  ; switch character to OFF
    JMP SWITCH6

   SWITCH4A:
    MOV [SWITCHES + 3], 1FH  ; switch character to ON
    JMP SWITCH7
   
  SWITCH5:
   CMP [SWITCHES + 4], 7FH   ; if character in switch 5 is 7FH
   JE SWITCH5A
   
   CMP [SWITCHES + 4], 1FH   ; if character in switch 5 is 1FH.
   JE SWITCH5B   
   
   SWITCH5B:
    MOV [SWITCHES + 4], 7FH  ; switch character to OFF
    JMP SWITCH7

   SWITCH5A:
    MOV [SWITCHES + 4], 1FH  ; switch character to ON
    JMP SWITCH8
   
  SWITCH6:
   CMP [SWITCHES + 5], 7FH   ; if character in switch 6 is 7FH
   JE SWITCH6A
   
   CMP [SWITCHES + 5], 1FH   ; if character in switch 6 is 1FH.
   JE SWITCH6B   
   
   SWITCH6B:
    MOV [SWITCHES + 5], 7FH  ; switch character to OFF
    JMP DRAWGAME

   SWITCH6A:
    MOV [SWITCHES + 5], 1FH  ; switch character to ON
    JMP DRAWGAME
   
  SWITCH7:
   CMP [SWITCHES + 6], 7FH   ; if character in switch 7 is 7FH
   JE SWITCH7A
   
   CMP [SWITCHES + 6], 1FH   ; if character in switch 7 is 1FH.
   JE SWITCH7B   
   
   SWITCH7B:
    MOV [SWITCHES + 6], 7FH  ; switch character to OFF
    JMP DRAWGAME

   SWITCH7A:
    MOV [SWITCHES + 6], 1FH  ; switch character to ON
    JMP DRAWGAME
   
  SWITCH8:
   CMP [SWITCHES + 7], 7FH   ; if character in switch 8 is 7FH
   JE SWITCH8A
   
   CMP [SWITCHES + 7], 1FH   ; if character in switch 8 is 1FH.
   JE SWITCH8B   
   
   SWITCH8B:
    MOV [SWITCHES + 7], 7FH  ; switch character to OFF
    JMP DRAWGAME

   SWITCH8A:
    MOV [SWITCHES + 7], 1FH  ; switch character to ON
    JMP DRAWGAME
    
  EXITPROG:
   CALL CLRSCRN
   
   MOV AL, 0    ; exit to DOS.
   MOV AH, 04ch
   INT 21h
 START ENDP

 CLRSCRN PROC
   MOV AH, 0fh
   INT 10h
   
   MOV AL, 00h
   MOV AH, 0
   INT 10h 
   
   RET
 CLRSCRN ENDP 
END START   

PowerShell: Searching For Installed Patches/Updates

I had the need to search for the installation of specific patches on one of my servers recently. This isn't really a big deal...just type "appwiz.cpl" into the Run window and click "View Installed Updates" or take the dangerous journey through the control panel to find the same thing)...

However, even in Windows Server 2008, there is no option to sort this list by KB article (patch name). So what to do?

Hello, PowerShell! Nice to meet you again!



$KB = Read-Host "Enter KB Number (EX: KB2604094, with or without KB): "

 If ($KB.StartsWith("KB", "CurrentCultureIgnoreCase"))
  { $KB = $KB.Substring(2) }
 
 $Result = Get-HotFix | Where {$_.HotFixID -like "*$KB*"} | Select Description, HotFixID, InstalledBy, InstalledOn | Format-List
 
 If ($Result.Count -gt 0) { $Result }
 Else { Write-Host "KB Not Found!" }


Just enter any part of the HotFix ID that want. Here is the output. It's messy, but it gets the job done.


Sunday, May 6, 2012

Final Exam Finished

Well, I paid the price for watching a movie, chatting with the kids, playing a video game (Mass Effect 3, heh), and eating dinner....

all while taking my final exam for CIS 217.

So, I made a few mistakes, mostly not noticing when a question says "Show me which of these is incorrect", and I pick the "correct" answer, thus getting the question wrong. I do it all the time...and it's too late to stop doing it now, I guess!

Anyway, I wanted to let everyone know that there ARE errors in the Final Exam. I've sent Grace a list of the ones that I got wrong that I KNOW to be correct (which I verified with code shortly after submitting the exam). I would have sent the list to everyone, but I'm not going to get hammered for giving out exam answers ;-)

But if you got something wrong and got a bad grade, don't stress over it if you know the answer was right. She'll update it if you let her know.

Cheers!

Final Project Completed

I've finished the final project.  I can see why some of my classmates had trouble with it.  I don't know if passing data between Form objects is covered in the book or not...I stopped reading at around Chapter 3, other than to get the details for weekly assignments.

If anyone got stuck, here is the code for the project...so you can at least see how it is done (or rather, how I implemented it).

Here is the class in Form1 (frmMain in my project). Be sure to add a using statement for System.IO in order to get StreamReader/StreamWriter operational.
public partial class frmMain : Form
    {
        public string[] pbEntries = new string[5];
        public List People = new List();

        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            ReadTextFile();
            AddToListBox();
        }

        public void ReadTextFile()
        {

            int index = 0;                                                          // Index used in loops.
            StreamReader inputFile;                                                 // Declare StreamReader.
            inputFile = File.OpenText("myPhoneBook.txt");                           // Open file and get SR obj.

            while (index < pbEntries.Length && !inputFile.EndOfStream)
            {
                pbEntries[index] = inputFile.ReadLine();                            // Read contents of myPhoneBook.txt, store in pbEntries String array.
                index++;
            }
            
            for (int count = 0; count < pbEntries.Length; count++)
            {
                ConvertToObject(pbEntries[count]);                                  // Read each item in the String array 
            }
            inputFile.Close();                                                      // Close the file.
        }

        public string ConvertToObject(string dataLine)
        {
            string[] pInfo = dataLine.Split(',');                                   // Split entry for each person into sub-entries in the pInfo String array.
            PersonEntry Person = new PersonEntry(pInfo[0], pInfo[1], pInfo[2]);     // New instance of PersonEntry, pass name, email, and phone fields.
            People.Add(Person);                                                     // Add new Person object to People<> List.
            return null;
        }

        public void AddToListBox()
        {
            for (int count = 0; count != People.Count; count++)
            {
                lbPhoneBook.Items.Add(People[count].Name);                          // Durrr...obvious.
            }
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void lbPhoneBook_SelectedIndexChanged(object sender, EventArgs e)
        {
            frmSub Form = new frmSub(People[lbPhoneBook.SelectedIndex]);            // Overload new frmSub, passed PersonEntry object in People<>
            Form.ShowDialog();                                                      //  ...with SelectedIndex of lbPhoneBook.
        }   // No idea why it's throwing these  tags here...that's not part of my project code, it's something to do with the code coloring script.

And here is the code for the second form's code.
public frmSub(PersonEntry thisPerson)
        {
            InitializeComponent();
            lblName.Text = thisPerson.Name;
            lblEmail.Text = thisPerson.Email;
            lblPhone.Text = thisPerson.Phone;
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            this.Hide();
        }

And the required PersonEntry class for the project itself:

public class PersonEntry
    {
        // Fields
        private string _Name;
        private string _Email;
        private string _Phone;

        // Constructor
        public PersonEntry(string Name, string Email, string Phone)
        {
            _Name = Name;
            _Email = Email;
            _Phone = Phone;
        }

        // Name property
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        // Email property
        public string Email
        {
            get { return _Email; }
            set { _Email = value; }
        }

        // Phone property
        public string Phone
        {
            get { return _Phone; }
            set { _Phone = value; }
        }
    }

Wednesday, May 2, 2012

8086 Assembly: ASCII/Decimal to Hex conversion

Well, I finally finished the assignment I was given in my 8086 Assembly class to convert from an ASCII character to it's Hex value, or from 5 decimal values to Hex.  If option #1 in the menu is chosen, you can enter more than 5 numbers and hit 'Enter', but it will error out.  It's only supposed to take 5.  Anyone learning Assembly on their own...here ya go:

; Conversion program
; Write a menu-driven program which accepts a 1, 2, or 3 as input.
;    1) Accept a decimal value (up to 5 digits), and print its hex value
;    2) Accept a character, and print its ascii value in hex. (convert to base 10)
;    3) Quit program.

    .MODEL SMALL

    .STACK 100h

    .DATA
        Menu    DB    10, 13, 'Enter a choice (1, 2, or 3):'
                DB    10, 13, '1) Convert 1 to 5 Decimal values to Hex'
                DB    10, 13, '2) Convert ASCII to Hex'
                DB    10, 13, '3) Quit Program', 10, 13, '$'        
        MenuErr    DB    10, 13, 'Choice must be a 1, 2, or 3!'
                DB    10, 13, 'Try again!', 10, 13, '$'
        AskDec    DB    10, 13, 'Enter a number with 1 to 5 digits: ', 10, 13, '$'        
        AskChar DB    10, 13, 'Enter any character: ', 10, 13, '$'

    .CODE

        START    PROC
                MOV AX, @DATA                ; Startup code
                MOV DS, AX

            dispMenu:
                MOV DX, OFFSET Menu            ; Display menu
                MOV AH, 09H
                INT 21H

                MOV AH, 01H                    ; Get keyboard input
                INT 21H

                CMP AL, '1'                    
                JL dispErr

                CMP AL, '3'                    
                JG dispErr

                CMP AL, '1'                    
                JE goDec
                
                
                CMP AL, '2'                    
                JE goChar
                
                
                CMP AL, '3'                    
                JE goQuit

            dispErr:
                MOV DX, OFFSET MenuErr        ; Display menu error.
                MOV AH, 09H
                INT 21H
                JMP dispMenu                

            goDec:    
                CALL DEC2HEX                ; Call DEC2HEX procedure.
                JMP dispMenu

            goChar:
                CALL CHAR2HEX                ; Call CHAR2HEX procedure.
                JMP dispMenu

            goQuit:                            

                MOV AL, 0                    ; Exit program.
                MOV AH, 4CH
                INT 21H    

        START ENDP

        DEC2HEX PROC                        ; *** Accept a decimal value (up to 5 digits) > print it's hex value.
       
                MOV DX, OFFSET AskDec
                MOV AH, 09H
                INT 21H
           
                MOV AX, 0                     ; Clear AX
                PUSH AX                        ; Save AX to stack (else overwritten when 0Dh is pressed)       

            Again:
                
                MOV AH, 01H                    ; Get keyboard input
                INT 21H
                                    
                CMP AL, 0Dh                    ; If Return is entered, start division.
                JE SDiv1
               
                CMP AL, '0'                    
                JL Again
               
                CMP AL, '9'                    
                JG Again
                            
                MOV AH, 0                    ; Change to a digit.
                SUB AL, 30h                    
                MOV CX, AX                    ; Save digit in CX
                   pop ax

                MOV BX, 10                    ; Division by 10.
                MUL BX                        
               
                ADD AX, CX                    ; Add CX (original number) to AX (number after multiplication).
                PUSH AX                        ; Save on stack.
                JMP Again                    ; Repeat.

            SDiv1:

                mov cx, 0
                MOV BX, 16             
                pop ax
               
            Div1:                            

                DIV BX                      ; Divide (Word-sized).
                PUSH DX                     ; Save remainder.
                   
                ADD CX, 1                   ; Add one to counter   
                MOV DX, 0                   ; Clear Remainder (DX)
                CMP AX, 0                   ; Compare Quotient (AX) to zero
                JNE Div1                      ; If AX not 0, go to "Div1:"
               
            getHex:                            ; Get hex number.
                MOV DX, 0                    ; Clear DX.
                POP DX                        ; Put top of stack into DX.
                ADD DL, 30h                    ; Conv to character.

                CMP DL, 39h                    ; If DL > 39h (character 9)...
                JG MoreHex

            HexRet:                            ; Display hex number
                MOV AH, 02h                    ; 02h to display DL

                INT 21H                        ; Send to DOS
               
                LOOP getHex                 ; LOOP subtracts 1 from CX. If non-zero, loop.   
                JMP Skip
            MoreHex:                        ; Add 7h if DL > 39h (10-15)
                ADD DL, 7h                    ; Add another 7h to DL to get into the A-F hex range.
                JMP HexRet                    ; Return to where it left off before adding 7h.
            Skip:                            ; Skip addition of 7h if it is not needed.
                RET
        DEC2HEX ENDP
            
        CHAR2HEX PROC                        ; Accept a character, print it's ascii value in hex.
                                    
                MOV DX, OFFSET AskChar        ; Display prompt
                MOV AH, 09H
                INT 21H

                MOV AH, 01H                    ; Get keyboard input w/ no echo (AL)
                INT 21H
            
                MOV CL, AL                    ; Copy user input (AL) to CL
                MOV AX, 0                    ; Clear AX (get rid of HO bits)
                MOV AL, CL                    ; Copy user input back into AL

                MOV BX, 16                    ; Set up the divisor (base 16)
                MOV CX, 0                    ; Initialize the counter
                MOV DX, 0                    ; Clear DX

            Divide:                         
                                            ; Dividend in DX/AX pair, Quotient in AX, Remainder in DX.
                DIV BX                      ; Divide (will be word sized).
                PUSH DX                        ; Save DX (the remainder) to stack.
            
                ADD CX, 1                   ; Add one to counter

                MOV DX, 0                    ; Clear Remainder (DX)
                CMP AX, 0                    ; Compare Quotient (AX) to zero
                JNE Divide                    ; If AX not 0, go to "Divide:"
                
            Divide2:
                MOV DX, 0                    ; Clear DX
                POP DX                        ; Put top of stack into DX
       
                ADD DL, 30h                    ; ADD 30h (2) to DL 

                CMP DL, 39h
                JG HexDigit
    
            HexRet2:
                MOV AH, 02h                    ; 02h to display AH (DL)
                INT 21H                        ; Send to DOS

                LOOP Divide2                ; If more to do, Divide2 again
                                            ; LOOP subtracts 1 from CX. If non-zero, loop.
                JMP SkipHex2
            HexDigit:
                ADD DL, 7h                    ; Convert [10-15] to [A-F]
                JMP HexRet2                    ; Return to where I jumped from to do the ADD
            SkipHex2:
                RET
        CHAR2HEX ENDP
    END START