home *** CD-ROM | disk | FTP | other *** search
/ HomeWare 14 / HOMEWARE14.bin / prog / pcgpe10.arj / ASMINTRO.TXT < prev    next >
Text File  |  1994-05-10  |  23KB  |  627 lines

  1.  
  2.         ╓──────────┤% VLA Presents: Intro to Assembler %├──────────╖
  3.         ║                                                          ║
  4.         ╙──────────────────────────────────────────────────────────╜
  5.  
  6.  
  7.  
  8.   » Dedicated To Those Who Wish To Begin Exploring The Art Of Assembler. «
  9.  
  10.  
  11.  
  12. ───────────────────────────  VLA Members Are  ────────────────────────────
  13.  
  14.                          (⌐ Draeden - Main Coder ¬)
  15.                       (⌐ The Priest - Coder/ Artist ¬)
  16.                   (⌐ Lithium -  Coder/Ideas/Ray Tracing ¬)
  17.                    (⌐ The Kabal -  Coder/Ideas/Artwork ¬)
  18.                       (⌐ Desolation - Artwork/Ideas ¬)
  19.  
  20. ────────────────────────── The Finn - Mods/Sounds ──────────────────────────
  21.  
  22.  
  23.    ╓──────────────────═╡ Contact Us On These Boards ╞═──────────────────╖
  24.    ║                                                                    ║
  25.    │  % Phantasm BBS .................................. (206) 232-5912  │
  26.    │  * The Deep ...................................... (305) 888-7724  │
  27.    │  * Dark Tanget Systems ........................... (206) 722-7357  │
  28.    │  * Metro Holografix .............................. (619) 277-9016  │
  29.    │                                                                    │
  30.    ║        % - World Head Quarters      * - Distribution Site          ║
  31.    ╙────────────────────────────────────────────────────────────────────╜
  32.  
  33.      Or Via Internet Mail For The Group: tkabal@carson.u.washington.edu
  34.  
  35.                        Or to reach the other members:
  36.  
  37.                         - draeden@u.washington.edu -
  38.  
  39.                         - lithium@u.washington.edu -
  40.  
  41.                        - desolation@u.washington.edu-
  42.  
  43.  
  44. ────────────────────────────────────────────────────────────────────────────
  45.     VLA 3/93  Introduction to ASSEMBLER
  46. ────────────────────────────────────────────────────────────────────────────
  47.  
  48. Here's something to help those of you who were having trouble understanding
  49. the instructional programs we released.  Dreaden made these files for the 
  50. Kabal and myself when we were just learning.  These files go over some of 
  51. the basic concepts of assembler.  Bonus of bonuses.  These files also have 
  52. programs imbedded in them.  Most of them have a ton of comments so even
  53. the beginning programmers should be able to figure them out.
  54.  
  55. If you'd like to learn more, post a message on Phantasm.  We need to know
  56. where you're interests are before we can make more files to bring out the
  57. little programmers that are hiding inside all of us.
  58.  
  59.     Lithium/VLA
  60.  
  61. ────────────────────────────────────────────────────────────────────────────
  62.  
  63.     First thing ya need to know is a little jargon so you can talk about 
  64. the basic data structures with your friends and neighbors.  They are (in
  65. order of increasing size) BIT, NIBBLE, BYTE, WORD, DWORD, FWORD, PWORD and
  66. QWORD, PARA, KiloByte, MegaByte.  The ones that you'll need to memorize are
  67. BYTE, WORD, DWORD, KiloByte, and MegaByte.  The others aren't used all that 
  68. much, and you wont need to know them to get started.  Here's a little 
  69. graphical representation of a few of those data structures:
  70.  
  71. (The zeros in between the || is a graphical representation of the number of
  72. bits in that data structure.)
  73.  
  74. ──────
  75. 1 BIT :     |0|
  76.  
  77.     The simplest piece of data that exists.  Its either a 1 or a zero.
  78.     Put a string of them together and you have a BASE-2 number system.
  79.     Meaning that instead of each 'decimal' place being worth 10, its only 
  80.     worth 2.  For instance: 00000001 = 1; 00000010 = 2; 00000011 = 3, etc..
  81.  
  82. ──────
  83. 1 NIBBLE:   |0000|
  84. 4 BITs
  85.  
  86.     The NIBBLE is half a BYTE or four BITS.  Note that it has a maximum value
  87.     of 15 (1111 = 15).  Not by coincidence, HEXADECIMAL, a base 16 number 
  88.     system (computers are based on this number system) also has a maximum 
  89.     value of 15, which is represented by the letter 'F'.  The 'digits' in
  90.     HEXADECIMAL are (in increasing order): 
  91.     
  92.     "0123456789ABCDEF"
  93.  
  94.     The standard notation for HEXADECIMAL is a zero followed by the number        
  95.     in HEX followed by a lowercase "h"  For instance: "0FFh" = 255 DECIMAL.
  96.  
  97. ──────
  98. 1 BYTE      |00000000|
  99. 2 NIBBLEs    └─ AL ─┘
  100. 8 BITs
  101.  
  102.     The BYTE is the standard chunk of information.  If you asked how much 
  103.     memory a machine had, you'd get a response stating the number of BYTEs it
  104.     had. (Usually preceded by a 'Mega' prefix).  The BYTE is 8 BITs or 
  105.     2 NIBBLEs.  A BYTE has a maximum value of 0FFh (= 255 DECIMAL).  Notice
  106.     that because a BYTE is just 2 NIBBLES, the HEXADECIMAL representation is
  107.     simply two HEX digits in a row (ie. 013h, 020h, 0AEh, etc..)
  108.  
  109.     The BYTE is also that size of the 'BYTE sized' registers - AL, AH, BL, BH,
  110.     CL, CH, DL, DH.
  111.  
  112. ──────
  113. 1  WORD      |0000000000000000|
  114. 2  BYTEs      └─ AH ─┘└─ AL ─┘     
  115. 4  NIBBLEs    └───── AX ─────┘
  116. 16 BITs
  117.  
  118.     The WORD is just two BYTEs that are stuck together.  A word has a maximum 
  119.     value of 0FFFFh (= 65,535).  Since a WORD is 4 NIBBLEs, it is represented
  120.     by 4 HEX digits.  This is the size of the 16bit registers on the 80x86
  121.     chips.  The registers are: AX, BX, CX, DX, DI, SI, BP, SP, CS, DS, ES, SS,
  122.     and IP.  Note that you cannot directly change the contents of IP or CS in 
  123.     any way.  They can only be changed by JMP, CALL, or RET.
  124.  
  125. ──────
  126. 1  DWORD
  127. 2  WORDs     |00000000000000000000000000000000|
  128. 4  BYTEs      │               └─ AH ─┘└─ AL ─┘     
  129. 8  NIBBLEs    │               └───── AX ─────┘
  130. 32 BITs       └──────────── EAX ─────────────┘
  131.  
  132.     A DWORD (or "DOUBLE WORD") is just two WORDs, hence the name DOUBLE-WORD.
  133.     This can have a maximum value of 0FFFFFFFFh (8 NIBBLEs, 8 'F's) which
  134.     equals 4,294,967,295.  Damn large.  This is also the size or the 386's
  135.     32bit registers: EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP, EIP.  The 'E '
  136.     denotes that they are EXTENDED registers.  The lower 16bits is where the 
  137.     normal 16bit register of the same name is located. (See diagram.)
  138.  
  139. ──────
  140. 1    KILOBYTE   |-lots of zeros (8192 of 'em)-|
  141. 256  DWORDs
  142. 512  WORDs
  143. 1024 BYTEs
  144. 2048 NIBBLEs
  145. 8192 BITs
  146.  
  147.     We've all heard the term KILOBYTE byte, before, so I'll just point out
  148.     that a KILOBYTE, despite its name, is -NOT- 1000 BYTEs.  It is actually
  149.     1024 bytes.
  150.  
  151. ──────
  152.           1 MEGABYTE   |-even more zeros (8,388,608 of 'em)-|
  153.       1,024 KILOBYTEs
  154.     262,144 DWORDs
  155.     524,288 WORDs
  156.   1,048,576 BYTEs
  157.   2,097,152 NIBBLEs
  158.   8,388,608 BITs
  159.  
  160.     Just like the KILOBYTE, the MEGABYTE is -NOT- 1 million bytes.  It is
  161.     actually 1024*1024 BYTEs, or 1,048,578 BYTEs
  162.  
  163. ──────────────────────────────
  164.  
  165.     Now that we know what the different data types are, we will investigate
  166.     an annoying little aspect of the 80x86 processors.  I'm talking about 
  167.     nothing other than SEGMENTS & OFFSETS!
  168.  
  169.  
  170. SEGMENTS & OFFSETS:
  171. ──────────────────
  172.     Pay close attention, because this topic is (I believe) the single most
  173.     difficult (or annoying, once you understand it) aspect of ASSEMBLER.
  174.  
  175. An OverView:
  176.  
  177.     The original designers of the 8088, way back when dinasaurs ruled the 
  178.     planet, decided that no one would ever possibly need more than one MEG
  179.     (short for MEGABYTE :) of memory.  So they built the machine so that it 
  180.     couldn't access above 1 MEG. To access the whole MEG, 20 BITs are needed.
  181.     Problem was that the registers only had 16 bits, and if the used two
  182.     registers, that would be 32 bits, which was way too much (they thought.)  
  183.     So they came up with a rather brilliant (blah) way to do their addressing-
  184.     they would use two registers.  They decided that they would not be 32bits, 
  185.     but the two registers would create 20 bit addressing.  And thus Segments
  186.     and OFfsets were born.  And now the confusing specifics.
  187.  
  188. ──────────────────
  189.     
  190. OFFSET  = SEGMENT*16
  191. SEGMENT = OFFSET /16    ;note that the lower 4 bits are lost
  192.  
  193.                  
  194. SEGMENT * 16    |0010010000010000----|  range (0 to 65535) * 16
  195.  +                    
  196. OFFSET          |----0100100000100010|  range (0 to 65535)
  197.  =
  198. 20 bit address  |00101000100100100010|  range 0 to 1048575 (1 MEG)
  199.                  └───── DS ─────┘
  200.                      └───── SI ─────┘
  201.                      └─ Overlap─┘
  202.  
  203.  This shows how DS:SI is used to construct a 20 bit address.
  204.  
  205. Segment registers are: CS, DS, ES, SS. On the 386+ there are also FS & GS
  206.  
  207. Offset registers  are: BX, DI, SI, BP, SP, IP.  In 386+ protected mode, ANY
  208.         general register (not a segment register) can be used as an Offset
  209.         register.  (Except IP, which you can't access.)
  210.  
  211.     CS:IP => Points to the currently executing code.
  212.     SS:SP => Points to the current stack position.
  213.     
  214. ──────────────────
  215.  
  216.     If you'll notice, the value in the SEGMENT register is multiplied by
  217.     16 (or shifted left 4 bits) and then added to the OFFSET register.
  218.     Together they create a 20 bit address.  Also Note that there are MANY
  219.     combinations of the SEGMENT and OFFSET registers that will produce the 
  220.     same address.  The standard notation for a SEGment/OFFset pair is:
  221.  
  222. ────
  223. SEGMENT:OFFSET or A000:0000 ( which is, of course in HEX )
  224.  
  225.     Where SEGMENT = 0A000h and OFFSET = 00000h.  (This happens to be the 
  226.     address of the upper left pixel on a 320x200x256 screen.)
  227. ────
  228.  
  229.     You may be wondering what would happen if you were to have a segment
  230.     value of 0FFFFh and an offset value of 0FFFFh.  
  231.  
  232.     Take notice: 0FFFFh * 16 (or 0FFFF0h ) + 0FFFFh = 1,114,095, which is 
  233.       definately larger than 1 MEG (which is 1,048,576.)
  234.  
  235.     This means that you can actually access MORE than 1 meg of memory!  
  236.     Well, to actually use that extra bit of memory, you would have to enable
  237.     something called the A20 line, which just enables the 21st bit for
  238.     addressing.  This little extra bit of memory is usually called
  239.     "HIGH MEMORY" and is used when you load something into high memory or
  240.     say DOS = HIGH in your AUTOEXEC.BAT file.  (HIMEM.SYS actually puts it up
  241.     there..)  You don't need to know that last bit, but hey, knowledge is 
  242.     good, right?
  243.  
  244. ──────────────────────
  245.     THE REGISTERS:
  246. ──────────────────────
  247.  
  248.     I've mentioned AX, AL, and AH before, and you're probably wondering what
  249.     exactly they are.  Well, I'm gonna go through one by one and explain
  250.     what each register is and what it's most common uses are.  Here goes:
  251.  
  252. ────
  253. AX (AH/AL): 
  254.     AX is a 16 bit register which, as metioned before, is merely two bytes
  255.     attached together.  Well, for AX, BX, CX, & DX you can independantly 
  256.     access each part of the 16 bit register through the 8bit (or byte sized)
  257.     registers.  For AX, they are AL and AH, which are the Low and High parts
  258.     of AX, respectivly.  It should be noted that any change to AL or AH, 
  259.     will change AX.  Similairly any changes to AX may or may not change AL and
  260.     AH.  For instance:
  261.  
  262. ────────
  263. Let's suppose that AX = 00000h (AH and AL both = 0, too) 
  264.  
  265.     mov     AX,0
  266.     mov     AL,0
  267.     mov     AH,0
  268.  
  269. Now we set AL = 0FFh.  
  270.  
  271.     mov     AL,0FFh
  272.  
  273. :AX => 000FFh  ;I'm just showing ya what's in the registers
  274. :AL =>   0FFh
  275. :AH => 000h
  276.  
  277. Now we increase AX by one:
  278.  
  279.     INC     AX
  280.  
  281. :AX => 00100h (= 256.. 255+1= 256)
  282. :AL =>   000h (Notice that the change to AX changed AL and AH)
  283. :AH => 001h
  284.  
  285. Now we set AH = 0ABh (=171)
  286.  
  287.     mov     AH,0ABh
  288.  
  289. :AX => 0AB00h
  290. :AL =>   000h
  291. :AH => 0ABh
  292.  
  293. Notice that the first example was just redundant...
  294. We could've set AX = 0 by just doing
  295.  
  296.     mov     ax,0
  297.  
  298. :AX => 00000h
  299. :AL =>   000h
  300. :AH => 000h
  301.  
  302. I think ya got the idea...
  303. ────────
  304.  
  305.     SPECIAL USES OF AX:
  306.         Used as the destination of an IN (in port) 
  307.             ex: IN  AL,DX
  308.                 IN  AX,DX
  309.  
  310.         Source for the output for an OUT           
  311.             ex: OUT DX,AL
  312.                 OUT DX,AX
  313.  
  314.         Destination for LODS (grabs byte/word from [DS:SI] and INCreses SI)
  315.             ex: lodsb   (same as:   mov al,[ds:si] ; inc si )
  316.                 lodsw   (same as:   mov ax,[ds:si] ; inc si ; inc si )
  317.  
  318.         Source for STOS      (puts AX/AL into [ES:DI] and INCreses DI)
  319.             ex: stosb   (same as:   mov [es:di],al ; inc di )
  320.                 stosw   (same as:   mov [es:di],ax ; inc di ; inc di )
  321.  
  322.         Used for MUL, IMUL, DIV, IDIV
  323. ────
  324. BX (BH/BL): same as AX (BH/BL)
  325.  
  326.     SPECIAL USES:
  327.         As mentioned before, BX can be used as an OFFSET register.
  328.             ex: mov ax,[ds:bx]  (grabs the WORD at the address created by
  329.                                     DS and BX)
  330.  
  331. CX (CH/CL): Same as AX
  332.     
  333.     SPECIAL USES:
  334.         Used in REP prefix to repeat an instruction CX number of times
  335.             ex: mov cx,10
  336.                 mov ax,0
  337.                 rep stosb ;this would write 10 zeros to [ES:DI] and increase
  338.                           ;DI by 10.
  339.         Used in LOOP
  340.             ex: mov cx,100
  341.             THELABEL:
  342.  
  343.                 ;do something that would print out 'HI'
  344.  
  345.                 loop THELABEL   ;this would print out 'HI' 100 times
  346.                                 ;the loop is the same as: dec cx
  347.                                                           jne THELABAL
  348.             
  349. DX (DH/DL): Same as above
  350.     SPECIAL USES:
  351.         USED in word sized MUL, DIV, IMUL, IDIV as DEST for high word
  352.                 or remainder
  353.  
  354.             ex: mov bx,10
  355.                 mov ax,5
  356.                 mul bx  ;this multiplies BX by AX and puts the result 
  357.                         ;in DX:AX
  358.  
  359.             ex: (continue from above)
  360.                 div bx  ;this divides DX:AX by BX and put the result in AX and
  361.                         ;the remainder (in this case zero) in DX
  362.  
  363.         Used as address holder for IN's, and OUT's (see ax's examples)
  364.             
  365. INDEX REGISTERS:  
  366.  
  367.     DI: Used as destination address holder for stos, movs (see ax's examples)
  368.         Also can be used as an OFFSET register
  369.  
  370.     SI: Used as source address holder for lods, movs (see ax's examples)
  371.         Also can be used as OFFSET register
  372.  
  373.         Example of MOVS:
  374.             movsb   ;moves whats at [DS:SI] into [ES:DI] and increases
  375.             movsw   ; DI and SI by one for movsb and 2 for movsw
  376.  
  377.         NOTE: Up to here we have assumed that the DIRECTION flag was cleared.
  378.             If the direction flag was set, the DI & SI would be DECREASED 
  379.             instead of INCREASED.
  380.             ex:     cld     ;clears direction flag
  381.                     std     ;sets direction flag
  382.  
  383. STACK RELATED INDEX REGISTERS:
  384.     BP: Base Pointer. Can be used to access the stack. Default segment is
  385.         SS.  Can be used to access data in other segments throught the use
  386.         of a SEGMENT OVERRIDE.
  387.  
  388.         ex: mov al,[ES:BP] ;moves a byte from segment ES, offset BP
  389.             Segment overrides are used to specify WHICH of the 4 (or 6 on the
  390.             386) segment registers to use.
  391.  
  392.     SP: Stack Pointer. Does just that.  Segment overrides don't work on this 
  393.         guy.  Points to the current position in the stack.  Don't alter unless
  394.         you REALLY know what you are doing.
  395.         
  396. SEGMENT REGISTERS:
  397.     DS: Data segment- all data read are from the segment pointed to be this
  398.         segment register unless a segment overide is used.
  399.         Used as source segment for movs, lods
  400.         This segment also can be thought of as the "Default Segment" because
  401.         if no segment override is present, DS is assumed to be the segmnet
  402.         you want to grab the data from.
  403.  
  404.     ES: Extra Segment- this segment is used as the destination segment
  405.         for movs, stos
  406.         Can be used as just another segment...  You need to specify [ES:░░]
  407.         to use this segment.
  408.  
  409.     FS: (386+) No particular reason for it's name... I mean, we have CS, DS,
  410.         and ES, why not make the next one FS? :)  Just another segment..
  411.     
  412.     GS: (386+) Same as FS
  413.  
  414.     
  415. OTHERS THAT YOU SHOULDN'T OR CAN'T CHANGE:
  416.     CS: Segment that points to the next instruction- can't change directly
  417.     IP: Offset pointer to the next instruction- can't even access
  418.         The only was to change CS or IP would be through a JMP, CALL, or RET
  419.  
  420.     SS: Stack segment- don't mess with it unless you know what you're
  421.         doing.  Changing this will probably crash the computer.  This is the
  422.         segment that the STACK resides in.
  423.  
  424. ────────
  425. Heck, as long as I've mentioned it, lets look at the STACK:
  426.  
  427.     The STACK is an area of memory that has the properties of a STACK of
  428.     plates- the last one you put on is the first one take off.  The only
  429.     difference is that the stack of plates is on the roof.  (Ok, so that
  430.     can't really happen... unless gravity was shut down...)  Meaning that
  431.     as you put another plate (or piece of data) on the stack, the STACK grows
  432.     DOWNWARD.  Meaning that the stack pointer is DECREASED after each PUSH,
  433.     and INCREASED after each POP.
  434.  
  435.   _____ Top of the allocated memory in the stack segment (SS)
  436.     ■ 
  437.     ■
  438.     ■
  439.     ■ « SP (the stack pointer points to the most recently pushed byte)
  440.  
  441.     Truthfully, you don't need to know much more than a stack is Last In,
  442.     First Out (LIFO).
  443.  
  444.   WRONG ex: push    cx  ;this swaps the contents of CX and AX
  445.             push    ax  ;of course, if you wanted to do this quicker, you'd
  446.             ...
  447.             pop     cx  ;just say XCHG cx,ax
  448.             pop     ax  ; but thats not my point.
  449.  
  450.   RIGHT ex: push    cx  ;this correctly restores AX & CX  
  451.             push    ax
  452.             ...
  453.             pop     ax
  454.             pop     cx
  455.  
  456. ────────────
  457.  
  458. Now I'll do a quick run through on the assembler instructions that you MUST
  459. know:
  460.  
  461. ────
  462. MOV:
  463.  
  464.     Examples of different addressing modes: 
  465.  
  466.         MOV ax,5        ;moves and IMMEDIATE value into ax (think 'AX = 5')
  467.         MOV bx,cx       ;moves a register into another register
  468.         MOV cx,[SI]     ;moves [DS:SI] into cx (the Default Segment is Used)
  469.         MOV [DI+5],ax   ;moves ax into [DS:DI+5]
  470.         MOV [ES:DI+BX+34],al    ;same as above, but has a more complicated
  471.                                 ;OFFSET (=DI+BX+34) and a SEGMENT OVERRIDE
  472.         MOV ax,[546]    ;moves whats at [DS:546] into AX
  473.                         
  474.     Note that the last example would be totally different if the brackets 
  475.     were left out.  It would mean that an IMMEDIATE value of 546 is put into
  476.     AX, instead of what's at offset 546 in the Default Segment.
  477.     
  478. ANOTHER STANDARD NOTATION TO KNOW:
  479.     Whenever you see brackets [] around something, it means that it refers to 
  480.     what is AT that offset.  For instance, say you had this situation:
  481.  
  482. ────────────
  483. MyData  dw  55
  484.     ...
  485.     mov ax,MyData
  486. ────────────
  487.  
  488.     What is that supposed to mean?  Is MyData an Immediate Value?  This is
  489.     confusing and for our purposes WRONG.  The 'Correct' way to do this would
  490.     be:
  491.  
  492. ────────────
  493. MyData  dw  55
  494.     ...
  495.     mov ax,[MyData]
  496. ────────────
  497.  
  498.     This is clearly moving what is AT the address of MyData, which would be
  499.     55, and not moving the OFFSET of MyData itself.  But what if you 
  500.     actually wanted the OFFSET?  Well, you must specify directly.
  501.  
  502. ────────────
  503. MyData  dw  55
  504.     ...
  505.     mov ax,OFFSET MyData
  506. ────────────
  507.  
  508.     Similiarly, if you wanted the SEGMENT that MyData was in, you'd do this:
  509.  
  510. ────────────
  511. MyData  dw  55
  512.     ...
  513.     mov ax,SEG MyData
  514. ────────────
  515.  
  516. ────────────────────────
  517. INT:
  518.     Examples:
  519.         INT 21h     ;calls DOS standard interrupt # 21h
  520.         INT 10h     ;the Video BIOS interrupt..
  521.         
  522.     INT is used to call a subroutine that performs some function that you'd
  523.     rather not write yourself.  For instance, you would use a DOS interrupt 
  524.     to OPEN a file.  You would similiarly use the Video BIOS interrupt to
  525.     set the screen mode, move the cursor, or to do any other function that 
  526.     would be difficult to program.
  527.  
  528.     Which subroutine the interrupt preforms is USUALLY specified by AH.
  529.     For instance, if you wanted to print a message to the screen you'd
  530.     use INT 21h, subfunction 9 by doing this:
  531.  
  532. ────────────
  533.     mov ah,9
  534.     int 21h
  535. ────────────
  536.  
  537.     Yes, it's that easy.  Of course, for that function to do anything, you
  538.     need to specify WHAT to print.  That function requires that you have
  539.     DS:DX be a FAR pointer that points to the string to display.  This string
  540.     must terminate with a dollar sign.  Here's an example:
  541.  
  542. ────────────
  543. MyMessage db    "This is a message!$" 
  544.     ...
  545.     mov     dx,OFFSET MyMessage
  546.     mov     ax,SEG MyMessage
  547.     mov     ds,ax
  548.     mov     ah,9
  549.     int     21h
  550.     ...
  551. ────────────
  552.  
  553.     The DB, like the DW (and DD) merely declares the type of a piece of data.
  554.  
  555.         DB => Declare Byte (I think of it as 'Data Byte')
  556.         DW => Declare Word
  557.         DD => Declare Dword
  558.     
  559.     Also, you may have noticed that I first put the segment value into AX
  560.     and then put it into DS.  I did that because the 80x86 does NOT allow
  561.     you to put an immediate value into a segment register.  You can, however,
  562.     pop stuff into a Segment register or mov an indexed value into the
  563.     segment register.  A few examples:
  564.  
  565. ────────────
  566.   LEGAL:
  567.     mov     ax,SEG MyMessage
  568.     mov     ds,ax
  569.  
  570.     push    SEG Message
  571.     pop     ds
  572.  
  573.     mov     ds,[SegOfMyMessage]     
  574.             ;where [SegOfMyMessage] has already been loaded with 
  575.             ; the SEGMENT that MyMessage resides in
  576.   ILLEGAL:
  577.     mov     ds,10
  578.     mov     ds,SEG MyMessage
  579. ────────────
  580.  
  581. Well, that's about it for what you need to know to get started...
  582.  
  583. ────────────────────────────────────────────────────────────────────────
  584.     And now the FRAME for an ASSEMBLER program.
  585. ──────────────────────────────────────────────────────────────────────
  586.  
  587. The Basic Frame for an Assembler program using Turbo Assembler simplified
  588.     directives is:
  589.  
  590. ;===========-
  591.  
  592.     DOSSEG  ;This arranges the segments in order according DOS standards
  593.             ;CODE, DATA, STACK
  594.     .MODEL SMALL    ;dont worry about this yet
  595.     .STACK  200h    ;tells the compiler to put in a 200h byte stack
  596.     .CODE           ;starts code segment
  597.  
  598.     ASSUME  CS:@CODE, DS:@CODE 
  599.  
  600. START:      ;generally a good name to use as an entry point
  601.  
  602.     mov     ax,4c00h
  603.     int     21h
  604.  
  605. END START
  606.  
  607. ;===========- By the way, a semicolon means the start of a comment.
  608.  
  609.     If you were to enter this program and TASM & TLINK it, it would execute
  610.     perfectly.  It will do absolutly nothing, but it will do it well.
  611.  
  612.     What it does:
  613.         Upon execution, it will jump to START. move 4c00h into AX,
  614.         and call the DOS interrupt, which exits back to DOS.
  615.  
  616.         Outout seen: NONE
  617. ────────────────────────────────────────────────────────────────────────
  618.  
  619. That's nice, eh?  If you've understood the majority of what was presented 
  620. in this document, you are ready to start programming!
  621.  
  622. See ASM0.TXT and ASM0.ASM to continue this wonderful assembler stuff...
  623.  
  624.  
  625. Written By Draeden/VLA
  626.  
  627.