Lesson 2 - PC Assembly Language:
- 

GENERAL DISCUSSION ABOUT PC MEMORY:

There are fundamentally two different kinds of memory chips.

1. RAM (Random Access Memory) which you may write to and read from.

2. ROM (Read Only Memory) which as the name implies may only be read from.

Even though a segment consists of 65,535 bytes of memory (counting from zero),
it is conventionally called 64K (K = 1000) memory.  Your PC may address 16
segments of memory.  For the time being we will ignore extended and expanded
memory.  These 16 decimal segments are numbered in hex from 0000h through
f000h.  The first ten segments from 0000h through the top of 9000h are all
dynamic RAM that may be written to and read from.  Your program and its data
may be located anywhere in this region as long as it is above the computer's
operating system which is loaded during boot up and is usually located in 
segment zero just above the 1024 byte interrupt table which occupies the first
1024 bytes of segment zero.

The memory in segment a000h is video RAM devoted to graphics video. The upper 
half of segment b000h is video RAM devoted to text mode video. The rest of 
the segments, c000h through f000h, are usually occupied with various chunks 
of ROM that contain more of the PC's operating system including ASCII and 
extended ASCII character sets in different sizes, plus various chunks of RAM 
in this area that vary according to the PC's manufacturer and video board 
installed.

TEXT MODE VIDEO MEMORY:

Text mode video RAM memory occupies segment b000h from b800h up through b8ffh.
Each text mode video page uses 4000 bytes of video RAM when in normal 25 lines
per page with 80 characters per line mode.  As such up to 4 different text 
pages may be accommodated along with their VGA 4096 byte character sets. See 
TUTOR5.COM for a character set display.  Exercising KISS restraint, we will 
use only the first text page.

A text mode page in video memory alternates each 80 character displayed line
with a data byte (the ASCII character displayed) with an attribute byte. The
attribute byte tells the computer which color to display for each of its data 
bytes in the foreground, the background, normal intensity or high intensity
and with to blink or not blink.  So, each 80 character text mode video line
occupies 160 bytes of video memory.  One byte for the character + 1 byte for
the attribute times 80 characters = 160 bytes per line.  The character byte is
first, followed by its attribute byte.

Once the program sets the es segment to b800h and the video page to page zero
the beginning and ending line addresses of a typical text video page are 
shown below in decimal and hex.

You will recall that each byte has eight bits counting from zero = 76543210.
The little diagram below shows how the arrangement of these bits determines
the foreground color, background color, intensity and whether the data byte
is blinking or not blinking.  The cathode ray tube in your video display has
3 masks that the electron beam sweeps over.  Each mask has a hole over a red,
green and blue phosphor that illuminates when the beam strikes it. By
combining these 3 colors and varying the intensity of the electron beam, the
computer can create 16, 256 or even more colors depending upon the video card
installed in your computer.  The R G B letters below represent red, green and
blue.

line decimal hex begin                                   end hex  decimal line
--   ----    ---                                             ---    ----   --
 0   0000 __ 000                                             09E __ 0158    0
 1   0160 __ 0A0                                             31E __ 0318    1
 2   0320 __ 140                                             1DE __ 0478    2
 3   0480 __ 1E0                                             27E __ 0638    3
 4   0640 __ 280                                             31E __ 0798    4
 5   0800 __ 320                                             3BF __ 0958    5
 6   0960 __ 3C0                                             45E __ 1118    6
 7   1120 __ 460                attribute byte               4FE __ 1278    7
 8   1280 __ 500                                             50E __ 1438    8
 9   1440 __ 5A0   bit no.   7   6 5 4   3   2 1 0           63E __ 1598    9
10   1600 __ 640           Ŀ         6DE __ 1758   10
11   1760 __ 6E0            BL R G B  I  R G B          77E __ 1938   11
12   1920 __ 780                    81E __ 2078   12         
13   2080 __ 820   blink bit background foreground        8BE __ 2138   13
14   2140 __ 8C0    0 = off                                 95E __ 2398   14
15   2400 __ 960    1 = on                intensity bit    9FE __ 2558   15
16   2560 __ A00                              0 = normal     A9E __ 2718   16
17   2720 __ AA0                              1 = high       B3E __ 2788   17
18   2880 __ B40                                             BDE __ 3038   18
19   3040 __ BE0                                             C7E __ 3198   19
20   3200 __ C80                                             D1E __ 3358   20
21   3360 __ D20                                             DBE __ 3518   21
22   3520 __ DC0                                             E5E __ 3678   22
23   3680 __ E60                                             EFE __ 3838   23
24   3840 __ F00                                             F9E __ 3998   24

Here is a table that displays the R G B bit values in the attribute byte that
display the eight fundamental colors in normal or high intensity.

	      Ŀ             
	            Foreground/Background Color Codes      
	      Ĵ                                           
	       R G B    Color                            
	      Ĵ                        
	       0 0 0    Black     Setting the "I" - bit  
	       0 0 1    Blue      will result in eight   
	       0 1 0    Green     additional shades of   
	       0 1 1    Cyan      these eight colors for 
	       1 0 0    Red       the foreground color.  
	       1 0 1    Magenta                          
	       1 1 0    Yellow  ---> (or medium orange)   
	       1 1 1    White                            
	                                                   
	       
	      Ŀ 
	       Foreground  Background  Text Color        
	      Ĵ                      
	          1 1 1       0 0 0    normal display    
	          0 0 0       1 1 1    reverse video     
	            

All of Lesson 1 and Lesson 2 uses an attribute byte of 7 decimal = 00000111
binary which = medium white on a black background.

Let us write a little source code program and then assemble and run it that 
illustrates how the attribute byte determines the data byte's color.  Here is
the source code for DEMO3.ASM.  Use EDLIN.COM to write the source code and
A86.COM to assemble it.  Type edlin demo3.asm and press enter to load it.
Then type 1P and press enter to display the first 23 lines of the source 
code.

When ready to assemble your source code, type:

		    A86 +LS DEMO3.ASM and press enter.

The +L tells the A86.COM assembler to use 3 byte instructions for all 
unconditional jumps, rather than a jump shot instruction.  This makes the 
code a tiny bit longer, but makes it much easier to trouble shoot.  The S
after the +L tells the program NOT to create a symbol table if the assembly
is completed without errors.  We DO NOT use the symbol table.

DEMO3.ASM:

 1: start: mov     ds,cs                   ;data segment = code segment
 2:        mov     ax,3                    ;reset text mode =
 3:        int     10h                     ;clear the screen.
 4:        call    cursof                  ;turn off the cursor
 5:        mov     es,0b800h               ;text mode video segment
 6:        mov     ah,1                    ;start with medium blue
 7:        mov     di,>s0                  ;list 7 medium colors
 8:        mov     si,844                  ;video location to start diz2
 9:        mov     cx,7                    ;display 7 lines
10:        call    diz2                    ;display
11:        mov     ah,9                    ;start bright blue on black
12:        mov     di,>s1                  ;list 7 bright colors
13:        mov     si,1964                 ;video location to start diz2
14:        mov     cx,7                    ;display 7 lines
15:        call    diz2                    ;display
16:        mov     ah,15                   ;bright white
17:        mov     cx,1                    ;display 1 line
18:        mov     di,>s2                  ;exit message
19:        mov     si,0                    ;display top left
20:        call    diz2                    ;do it
21:        mov     ah,0                    ;await key press
22:        int     16h                     ;keyboard
23:        cmp     ah,1                    ;Esc key
24:        jz      exit                    ;if so, go to exit
25:        jmp     start                   ;start all over
26:
27: diz2:  mov    al,[di]                  ;get character to display
28:        inc     di                      ;next one
29:        cmp     al,0                    ;test for zero end of string
30:        jz      diz3                    ;if so, go to diz3
31:        mov     es:[si],ax              ;display ASCII char.+ attribute
32:        add     si,2                    ;next video mem address
33:        jmp     diz2                    ;continue
34: diz3:  inc     ah                      ;next color
35:        add     si,98                   ;next video mem to display
36:        loop    diz2                    ;display 7 lines bright colors
37:        ret                             ;return to next after call

38: exit:  mov     ax,3                    ;reset text mode video
39:        int     10h                     ;also turns cursor ON
40:        mov     ax,4c00h                ;exit instruction
41:        int     21h                     ;return to DOS> prompt
42:
43: s0:
44: db  'This is medium blue    on black',0
45: db  'This is medium green   on black',0
46: db  'This is medium cyan    on black',0
47: db  'This is medium red     on black',0
48: db  'This is medium magenta on black',0
49: db  'This is medium orange  on black',0
50: db  'This is medium white   on black',0
51: s1:
52: db  'This is bright blue    on black',0
53: db  'This is bright green   on black',0
54: db  'This is bright cyan    on black',0
55: db  'This is bright red     on black',0
56: db  'This is bright magenta on black',0
57: db  'This is bright yellow  on black',0
58: db  'This is bright white   on black',0
59: s2: db 'Esc to exit',0
60:
61: curson: mov    ah,1                    ;set cursor type
62:        mov     cx,0607h                ;cursor type
63:        int     10h                     ;do it
64:        mov     dx,0                    ;cursor position
65:        jmp     >c1                     ;> = forward jump
66: cursof: mov    dx,1900h                ;cursor out of view on text
67:c1:     mov     ah,2                    ;set cursor position
68:        mov     bh,0                    ;page zero in text mode
69:        int     10h                     ;do it
70:        ret                             ;return to call+next instruct.

When writing assembly language source code, the upper case (CASE) or lower
case (case) makes no never mind, but hot shot programmers always use lower 
case exclusively.  Until I got drug store reading glasses, I always used 
upper case because it was easier for me to read.

This lesson's call diz2 in demo3.asm's lines 10 and 15 illustrates yet another 
way to display zero terminated ASCII strings.  A zero terminated ASCII string
is nothing more than a group of ASCII characters beginning with a db (define
byte) instruction, then an apostrophe (') to tell the assembler that what
follows are ASCII characters (decimal 32 through decimal 127).  The next
apostrophe at the end of the string tells the assembler that it the end of the 
ASCII characters.  The next 0 tells the diz2 subroutine that it is all done 
displaying that line.  The comma before the 0 tells the assembler that what 
follows should be treated as though it were on the next line with a db before 
it.  As such, you can mix ASCII, decimal and hex on the same line if you 
follow these rules.  It surely saves unnecessary line numbers.

THE PC KEYBOARD:
-
The PC keyboard and the operating system's decoding of its output is a pretty 
sophisticated series of subroutines using a number of different interrupts to 
handle the decoding.  The interrupt we will use in these lessons is interrupt
16h.  It is the most useful for our purposes and will handle most everything
imaginable when used correctly.  It has three fundamental functions.

   Number 1:
   -
   mov ah,0 - int 16: this is the fundamental wait for a key to be pressed.
   It returns the value in the 16 bit ax register.  The 16 bit ax register 
   consists of two 8 bit registers.  The al register for the low 8 bits and
   the ah register for the high 8 bits of ax.  Thus, ah + al = the ax 
   register. After mov ah,0 - int 16h is executed in your program it returns 
   the values in hex in both the al register and ah register as illustrated 
   below for the A key.  All values are in hex.   
   
		       Key   NoShift Shift  Ctrl   Alt             
			     ah-al   ah-al  ah-al  ah-al                

			A    1E/61   1E/41  1E/01  1E/00

   We can see that register ah returns the scan code 1E when the letter A is
   pressed whether or not the shift, Ctrl or Alt key is pressed with it.
   A scan code is the value for the key pressed when the key is released on
   current PCs.

   Register al returns the ASCII value for the letter 'A' if the shift key is
   also pressed or the ASCII value for the letter 'a' if the shift key is not
   pressed.  We need only compare register al with 61 hex or 41 hex to 
   determine whether or not the 'a' or shift 'A' key is pressed.
   
   For our program to determine whether or not the Ctrl A or Alt A keys are
   pressed we must compare register ax with 1E01 hex or 1E00 hex.

The table below illustrates the ax, ah and al register values returned by the
mov ah,0 - int 16h function for ALL the keys on current/up to date, PC 
compatible computers.

IBM PC KEYBOARD SCAN/ASCII CODES IN HEX RETURNED IN ax by: mov ah,0 - int 16H
-

Key   NoShift Shift  Ctrl   Alt            Key    NoShift Shift  Ctrl   Alt  
      ah-al   ah-al  ah-al  ah-al                 ah-al   ah-al  ah-al  ah-al
									     
A     1E/61   1E/41  1E/01  1E/00          F1     3B/00   54/00  5E/00  68/00
B     30/62   30/42  30/02  30/00          F2     3C/00   55/00  5F/00  69/00
C     2E/63   2E/43  2E/03  2E/00          F3     3D/00   56/00  60/00  6A/00
D     20/64   20/44  20/04  20/00          F4     3E/00   57/00  61/00  6B/00
E     12/65   12/45  12/05  12/00          F5     3F/00   58/00  62/00  6C/00
F     21/66   21/46  21/06  21/00          F6     40/00   59/00  63/00  6D/00
G     22/67   22/47  22/07  22/00          F7     41/00   5A/00  64/00  6E/00
H     23/68   23/48  23/08  23/00          F8     42/00   5B/00  65/00  6F/00
I     17/69   17/49  17/09  17/00          F9     43/00   5C/00  66/00  70/00
J     24/6A   24/4A  24/0A  24/00          F10    44/00   5D/00  67/00  71/00
K     25/6B   25/4B  25/0B  25/00          F11    85/00   87/00  89/00  8B/00
L     26/6C   26/4C  26/0C  26/00          F12    86/00   88/00  8A/00  8C/00
M     32/6D   32/4D  32/0D  32/00                                            
N     31/6E   31/4E  31/0E  31/00          NUMERIC KEYPAD                    
O     18/6F   18/4F  18/0F  18/00                                            
P     19/70   19/50  19/10  19/00       Ins  0    52/00   52/30              
Q     10/71   10/51  10/11  10/00       End  1    4F/00   4F/31  75/00  00/01
R     13/72   13/52  13/12  13/00   Dn Arrow 2    50/00   50/32         00/02
S     1F/73   1F/53  1F/13  1F/00       PgDn 3    51/00   51/33  76/00  00/03
T     14/74   14/54  14/14  14/00       <--  4    4B/00   4B/34  73/00  00/04
U     16/75   16/55  16/15  16/00            5            4C/35         00/05
V     2F/76   2F/56  2F/16  2F/00       -->  6    4D/00   4D/36  74/00  00/06
W     11/77   11/57  11/17  11/00       Home 7    47/00   47/37  77/00  00/07
X     2D/78   2D/58  2D/18  2D/00   Up Arrow 8    48/00   48/38         00/08
Y     15/79   15/59  15/19  15/00       PgUp 9    49/00   49/39  84/00  00/09
Z     2C/7A   2C/5A  2C/1A  2C/00        -        4A/2D   4A/2D              
Space 39/20   39/20  39/20  39/20        +        4E/2B   4E/2B              
Esc   01/1B   01/1B  01/1B               *        37/2A   37/2A              
1 !   02/31   02/21         78/00        /        35/2F   35/2F              
2 @   03/32   03/40  03/00  79/00       Del       53/00   53/2E              
3 #   04/33   04/23         7A/00       Enter     1C/02   1C/02  1C/0A       
4 $   05/34   05/24         7B/00                                            
5 %   06/35   06/25         7C/00       TOGGLE and SHIFT KEYS:               
6 ^   07/36   07/5E  07/1E  7D/A0       Read or Write MEM Location 0000:0417 
7 &   08/37   08/26         7E/00       bit  key          when bit = 1       
8 *   09/38   09/2A         7F/00        7   Insert       insert mode on     
9 (   0A/39   0A/38         80/00        6   CapsLock     capslock mode on   
0 )   OB/30   0B/29         81/00        5   NumLock      numlock mode on    
- _   0C/2D   0C/5F  0C/1F  82/00        4   ScrollLock   scroll lock mode on
= +   0D/3D   0D/2B         83/00        3   Alt Shift    key down           
[ {   1A/5B   1A/7B  1A/1B               2   Ctrl Shift   key down           
] }   1B/5D   1B/7D  1B/1D               1   Left Shift   key down           
BakSp 0E/08   0E/08                      0   Right Shift  key down           
; :   27/3B   27/3A                                                          
' "   28/27   28/22                     Read or Write MEM Location 0000:0418 
` ~   29/60   29/7E                     bit  key          when bit = 1       
, <   33/2C   33/3C                      7   Insert       key down           
. >   34/2E   34/3E                      6   CapsLock     key down           
/ ?   35/2F   35/3F                      5   NumLock      key down           
Enter 1C/0D   1C/0D  1C/0A               4   ScrollLock   key down           
Tab   0F/09   0F/00                                                          
\ |   2B/5C   2B/7C  2B/1C              (all above from IBM Technical Manual)
									     
TEXT MODE VIDEO LINE ADDRESSES:        KEYPAD INPUT USEFUL ASCII CHARACTERS:
0-0000  6-0960 12-1920 18-2880             218     194      196     191  
1-0160  7-1120 13-2080 19-3040             195     197      179     180  
2-0320  8-1280 14-2240 20-3200             192     193      196     217  
3-0480  9-1440 15-2400 21-3360             201     203      205     187  
4-0640 10-1600 16-2560 22-3520             204     206      186     185  
5-0800 11-1760 17-2720 23-3680  24-3840    200     202      205     188  

The above table contains a great deal of information about the PC's keyboard
output values.  By all means print it out and place it in a single clear 
plastic cover sheet that you can keep at a handy place on your desk.  I use
it daily.  On the other side of the plastic sheet print out and insert the:

	       IBM - ASCII - DECIMAL - BINARY - HEX - TABLE

This table was included as part of lesson 1.

   Number 2:
   -
   mov ah,1 - int 16h: This function should be used to test the keyboard to
   see if ANY key has been pressed. It does not WAIT for a key to be pressed.
   The source code: mov ah,1 - int 16h - jz nopress will jump to nopress when
   no key is pressed. The following source code illustrates the correct way
   to use it.  Line 5 does NOT wait since a key has been pressed.

	     1:   mov     ah,1                    ;check to see
	     2:   int     16h                     ;if key pressed.
	     3:   jz      nopress                 ;if not pressed go nopress
	     4:   mov     ah,0                    ;unload keyboard buffer
	     5:   int     16h                     ;it DOES NOT WAIT here
	     6:   cmp     al,61h                  ;test for 'a' key
	     7:   jz      gota                    ;if so, jump to gota
	     8: nopress:                          ;continue program here

   Number 3:
   -
   mov ah,2 - int 16h: This function tests memory location 0000:0417 hex and     
   returns its byte value in the al register.

	  Memory        Bit    Key             When bit = 1     
	                           
	  0000:0417h     7     Insert          Insert mode 'on'
			 6     CapsLock        CapsLock mode 'on'
			 5     NumLock         NumLock mode 'on'
			 4     ScrollLock      ScrollLock mode 'on'
   
   Use the test instructions as below to determine which bit is set.

			  byte                word
			  
	     bit no.      76543210            15 14 13 12 11 10 9 8 76543210
			  00000000             0  0  0  0  0  0 0 0 00000000

	     1.   mov     ah,2     
	     2.   int     16h
	     3.   test    al,10000000b        ;bit 7 = 1 ?
	     4.   jz      insert_on
	     5.   test    al,01000000b        ;bit 6 = 1 ?
	     6.   jz      capslock_on
	     7.   test    al,00100000b        ;bit 5 = 1 ?
	     8.   jz      numlock_on
	     9.   test    al,00010000b        ;bit 4 = 1 ?
	    10.   jz      scrolllock_on

   Note that we have illustrated yet another way to input a value in source 
   code in addition to decimal and hex, b = binary.  Sometimes it is easier
   to visualize the individual bits of a byte or word when using b = binary,
   rather using decimal or hex values.  
   
   Your IBM-ASCII-DECIMAL-BINARY-HEX-TABLE reference sheet has all of these 
   printed out for reference from zero through 255 decimal.  Keep this sheet 
   handy on your desk.  I use it many times every day.

   On Friday night of this week, please take the little 20 question Quiz 2
   and e-mail it to me tomorrow morning.

   Love,

   Grandpa
   
