home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / asm_programming / CHAP18.DOC < prev    next >
Text File  |  1990-07-20  |  14KB  |  355 lines

  1.  
  2.  
  3.  
  4.                                                                            185
  5.  
  6.                                   CHAPTER 18 - PORTS
  7.  
  8.  
  9.              In order to communicate with the outside world, the outside world
  10.              being your printer, your disk drives, your modem etc., the 8086
  11.              uses ports. A port is an address distinct from a memory address
  12.              where the i/o device can be reached.{1}  When IBM set up the
  13.              first PC, they decided what these port addresses would be and
  14.              what the function of each bit at each address would be. Any VGA,
  15.              EGA, CGA or monochrome card has to have it's ports at the same
  16.              addresses as those set by IBM, and these ports have to do the
  17.              same thing. 
  18.  
  19.              Normally, an i/o device has more than one port address. The
  20.              device not only has to transfer the data, it has to tell the
  21.              computer whether it is ready, find out if the computer wants to
  22.              send information, confirm that the transfer was successful etc.
  23.              COM1 is port addresses 3F8 - 3FF. COM2 is 2F8 - 2FF. The CGA
  24.              adapter is ports 3D0 - 3DF. 
  25.  
  26.              In the CGA, port 3D9 sets the different colors. The 8086 writes
  27.              to it, but can't read it. Port 3DA, it's neighbor, tells certain
  28.              status information and is read only. 
  29.  
  30.              All control information for the video cards is passed back and
  31.              forth through the ports. However, the video card comes into
  32.              memory 50 times a second to see what it should write to the
  33.              screen. The characters on the screen don't pass through the
  34.              ports. The mountain comes to Mohammed. 
  35.  
  36.              The data does pass through a port on the way to your serial
  37.              printer. The 8086 sends your printer control information through
  38.              one port address and sends the data through a different port
  39.              address. 
  40.  
  41.              The port instructions can be either with AL or AX. AL and AX are
  42.              the only registers you can use, AL for a byte transfer and AX for
  43.              a word transfer. There are two forms to the input instruction:
  44.  
  45.                  in   al, port_address
  46.              or
  47.                  in   al, dx
  48.  
  49.              port_address is a constant and is limited to 0 - 255. It is a one
  50.              byte constant. DX is the only register than can be used with the
  51.              second form. DX can contain any number from 0 - 65535. The
  52.              ____________________
  53.  
  54.                 1. There is memory address 0000 and there is port address
  55.              0000; they are two entirely different things. You can reach
  56.              memory address 0000 with the DS:SI pair 0000:0000, but DS:SI
  57.              can't get to port address 0000. The instruction "out 0, al"
  58.              writes the contents of al to port address 0000,  but the OUT
  59.              instruction can't get anywhere near memory address 0000.
  60.  
  61.              ______________________
  62.  
  63.              The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
  64.  
  65.  
  66.  
  67.  
  68.              The PC Assembler Tutor                                        186
  69.              ______________________
  70.  
  71.              following two pieces of code do the same thing:
  72.  
  73.                  in   al, 155
  74.  
  75.                  mov  dx, 155
  76.                  in   al, dx
  77.  
  78.              This code moves one byte of data from port 155 to register AL. 
  79.  
  80.              The output instruction is similar. We have:
  81.  
  82.                  out  port_address, al
  83.              or
  84.                  out  dx, al
  85.  
  86.              where port_address is a constant 0-255 and DX can contain a
  87.              number 0 - 65535. 
  88.  
  89.                  out  97, ax
  90.  
  91.              moves a word from AX to port addresses 97-98. Notice that both
  92.              the IN and the OUT instructions follow the  DESTINATION, SOURCE
  93.              ordering found in all the other 8086 instructions.
  94.  
  95.              The  "in  ax, port_address" form is not all that useful. If you
  96.              look at the addresses for the video ports, for COM1 and COM2, you
  97.              will see that they are all larger than 255. Also, most equipment
  98.              can be at several different addresses. A modem can be at COM1,
  99.              COM2, COM3, or COM4. If the port address is hard coded into the
  100.              instructions, you need 4 subprograms to handle the 4 different
  101.              addresses. It is easier to find out where the modem is, then use:
  102.  
  103.              modem_data_address dw   ?
  104.  
  105.                  mov  dx, modem_data_address 
  106.                  in   al, dx
  107.  
  108.              and
  109.                  mov  dx, modem_data_address
  110.                  out  dx, al
  111.  
  112.              If you aren't planning on writing device drivers this is for
  113.              background information only, since all standard i/o is done
  114.              through DOS or BIOS interrupts. 
  115.  
  116.              One last thing is the parity flag. It has been sitting on the
  117.              screen with all the other flags. What is it for?  When you send
  118.              information over a modem, there is a large possibility of line
  119.              interference. If it is text, and an occasional screw up is not
  120.              too bad, using a parity check may be enough.{2}  Parity can be
  121.              even or odd. Even means that an even number of bits are set to 1;
  122.              odd means that an odd number of bits are set to 1. This is not
  123.              whether the number is even or odd, it is whether the number of 1
  124.              ____________________
  125.  
  126.                 2. It is NEVER enough if you are transferring binary data or
  127.              executable files.
  128.  
  129.  
  130.  
  131.  
  132.              Chapter 18 - Ports                                            187
  133.              __________________
  134.  
  135.              BITS is even or odd. Here's a short list.
  136.  
  137.                       NUMBER         BINARY         PARITY
  138.  
  139.                            6           0110         even
  140.                            7           0111         odd
  141.                            8           1000         odd
  142.                            9           1001         even
  143.                           10           1010         even
  144.  
  145.              8 is an even number but has odd parity, 9 is an odd number but
  146.              has even parity. 6 has two 1 bits (even), 7 has three 1 bits
  147.              (odd), 8 has one 1 bit (odd), 9 has two 1 bits (even) and 10 has
  148.              two 1 bits (even).
  149.  
  150.              How does this help us? If there is a chance of 1/100 of screwing
  151.              up a single bit in a byte, there is only a chance of 1/10,000 of
  152.              screwing up two bits in a byte. What this means is that of every
  153.              100 errors, 99 of them will will be detectable because of a
  154.              change in parity (by changing a bit from 0 to 1 or from 1 to 0)
  155.              and only 1 of them will go undetected because two changes will
  156.              keep the same parity. This is a little obscure, so make sure you
  157.              understand why before continuing.
  158.  
  159.              This doesn't help us much yet, because we don't know what the
  160.              parity was originally. 9 has even parity, 7 has odd parity. What
  161.              communications programs do is FORCE the parity. They can either
  162.              force it even or force it odd.
  163.  
  164.              The standard ASCII characters end at 127 - that is, 0111 1111 
  165.              (7F) is the highest legal number you can transmit. The left bit
  166.              is unused, so we can use it to force the parity. We are going to
  167.              force it even, but forcing it odd uses the same technique. 
  168.  
  169.              The steps are:
  170.  
  171.                  (1) Find the parity of the byte.
  172.  
  173.                  (2) If it is even, leave it alone, if it is odd, put a 1 in
  174.                  the left hand bit. The parity is now even.
  175.  
  176.              If both the sending and receiving program have agreed on even
  177.              parity, then on the receiving end, the program:
  178.  
  179.                  (1) Checks for even parity. If the parity is odd, it is an
  180.                  error.
  181.  
  182.                  (2) Puts a 0 back in the left hand bit. The original number
  183.                  is restored.
  184.  
  185.              We are going to make a loop with both parts and use show_regs to
  186.              watch the parity flag. Here's the program:
  187.  
  188.              ; - - - - - - - - - - ENTER DATA BELOW THIS LINE
  189.  
  190.              error_banner  db  "Whoa! We have a screw up.", 13, 10, 0
  191.  
  192.  
  193.  
  194.  
  195.  
  196.              The PC Assembler Tutor                                        188
  197.              ______________________
  198.  
  199.              ; - - - - - - - - - - ENTER DATA ABOVE THIS LINE
  200.  
  201.              ; - - - - - - - - - - ENTER CODE BELOW THIS LINE
  202.                  mov  ax_byte, 0A3h            ; al binary
  203.                  mov  bx_byte, 0A2h            ; unsigned half registers
  204.                  mov  cx_byte, 0A2h            ; unsigned half registers
  205.                  mov  dx_byte, 0A3h            ; dl binary
  206.                  lea  ax, ax_byte
  207.                  call set_reg_style
  208.  
  209.              comm_loop:
  210.                  mov  ax, 0
  211.                  call set_count                ; reset count to 0
  212.                  mov  bx, 0                    ; clear registers
  213.                  mov  cx, 0
  214.                  mov  dx, 0
  215.                  call show_regs                ; (1)
  216.  
  217.                  ; the sending program
  218.  
  219.                  call get_unsigned_byte
  220.                  and  al, 7Fh             ; 0111 1111 - make sure al < 128
  221.                  mov  bl, al                   ; copy to bl
  222.                  call show_regs_and_wait       ; (2)
  223.  
  224.                  and  al, al                   ; check parity
  225.                  call show_regs_and_wait       ; (3)
  226.  
  227.                  jpe  do_nothing
  228.                  or   al, 80h                  ; if parity odd, set left bit
  229.  
  230.              do_nothing:
  231.                  and  al, al                   ; check parity for show_regs
  232.                  call show_regs_and_wait       ; (4)
  233.  
  234.                  ; the receiving program
  235.  
  236.                  mov  dl, al                   ; transmit from al to dl
  237.                  mov  cl, dl                   ; copy to cl
  238.                  call show_regs_and_wait       ; (5)
  239.  
  240.                  and  dl, dl
  241.                  jpe  zero_left_bit            ; is parity even?
  242.                  mov  ax, error_banner
  243.                  call print_string
  244.  
  245.              zero_left_bit:
  246.                  and  dl, 7Fh             ; 0111 1111  binary, left bit 0
  247.                  mov  cl, dl                   ; copy to cl
  248.                  call show_regs_and_wait       ; (6)
  249.                  jmp  comm_loop
  250.  
  251.              ; - - - - - - - - - - ENTER CODE ABOVE THIS LINE
  252.  
  253.              First, we set the register style so AL and DL are binary, BL and
  254.              CL are unsigned. We'll use AL and BL for sending, CL and DL for
  255.              receiving. Next, we reset the counter to 0 so we can see where we
  256.  
  257.  
  258.  
  259.  
  260.              Chapter 18 - Ports                                            189
  261.              __________________
  262.  
  263.              are, and zero AX, BX, CX, and DX. We get a byte and make sure
  264.              that it is 127 or less,{3} then send a copy to BL. BL stays
  265.              unchanged for the rest of the loop. We test the parity. and if it
  266.              is odd, change it. Finally, we send it off to DL.
  267.  
  268.              On the receiving end, we test the parity. If it is odd, we print
  269.              an error message. Then we zero the left hand bit. It is faster to
  270.              zero the left hand bit than to check to see if it needs to be
  271.              zeroed, so we do it for all data. The result is put in CL for
  272.              comparison. AL and DL are shown in binary form so you can count
  273.              the number of 1 bits in the byte.
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.              ____________________
  308.  
  309.                 3. The following could happen if we didn't take this step. We
  310.              get a number > 128 with odd parity. 131 (1000 0011  83h) is an
  311.              example. The sending program sees that it is odd parity, so it
  312.              puts a 1 in the left hand bit. But there is already a 1 in the
  313.              left hand bit, so the parity doesn't change, it is odd. The
  314.              receiving program gets the byte, tests it, notices that it is
  315.              odd, and sends back a transmission error. Since the sending
  316.              program didn't see anything wrong, it just sends the same byte
  317.              again. It will never get through correctly. In real life, the
  318.              sending program would probably test the byte to see if it was
  319.              greater than 127 and print an error if it was.
  320.  
  321.  
  322.  
  323.  
  324.              The PC Assembler Tutor                                        190
  325.              ______________________
  326.  
  327.                                           SUMMARY
  328.  
  329.  
  330.              POSSIBLE I/O INSTRUCTIONS
  331.  
  332.              in  ax, constant (= port address 0 - 255)
  333.              in  ax, DX
  334.  
  335.              in  al, constant (= port address 0 - 255)
  336.              in  al, DX
  337.  
  338.              out constant, ax  (constant = port address 0 - 255)
  339.              out DX, ax
  340.  
  341.              out constant, al  (constant = port address 0 - 255)  
  342.              out DX, al
  343.  
  344.              In these instructions DX holds a port address and 
  345.              can be from  0 - 65535.
  346.  
  347.  
  348.              PARITY
  349.  
  350.              Parity is whether the number of 1 bits in a byte (or word) is
  351.              even or odd. The 8086 sets the parity flag after most arithmetic
  352.              and all logical operations. If parity is even, the flag is 1, if
  353.              parity is odd, the flag is 0.
  354.  
  355.