home *** CD-ROM | disk | FTP | other *** search
/ The Party 1994: Try This At Home / disk_image.bin / source / asmtutwp / asmtut.doc (.txt) next >
Word Document  |  1995-02-19  |  959KB  |  1,338 lines

  1.  
  2.                        A introduction to x86 assembly
  3. Written by Gavin Estey                 email: gavin@senator.demon.co.uk
  4.  
  5. This document is version:
  6.  
  7. |0.9 Beta 2/19/95|
  8.  
  9. This will hopefully be the final version of this unless somebody finds some
  10. mistakes in it. I have spent over 620 minutes creating this document (not
  11. including writing or testing the code or the original text document) so I
  12. hope you will find it useful.
  13.  
  14. This version is still in testing which means that I cannot be sure that  all
  15. the code will compile and work correctly. I have done my best to  make  sure
  16. that all the information contained in  this  document  is  correct.  If  any
  17. mistakes are found please could you notify me be email.
  18.  
  19. If someone who has a computer that doesnΓÇÖt have a VGA card/monitor could
  20. you please compile the code on P29 that checks what graphics the computer
  21. can handle and tell me if it returned DX as 0.
  22.  
  23. This document was written by Gavin Estey. No part of this can be  reproduced
  24. and sold in any commercial product without my written permission  (email  me
  25. for more information). I am not responsible for any damage caused in  anyway
  26. from this document.
  27.  
  28. If you enjoy this document then a donation would be gratefully received.  No
  29. payment is necessary but none will turned down. If any mistakes are  noticed
  30. then I would like to be notified. If you would like any other help  or  have
  31. suggestions for a later version of this document.
  32.  
  33. Firstly you will need a suitable assembler to  compile  your  programs.  All
  34. examples have been tested with two compilers: A86 and Turbo Assembler(   ver
  35. 4. A86 is a very good shareware assembler capable of producing  code  up  to
  36. 80286. This can be found on your local simtel  mirror  (try  ftp.demon.co.uk
  37. or ftp.cdrom.com) under simtel/msdos/asmutil called A86V322.ZIP.
  38.  
  39. Firstly I am going to talk about SEGMENTS and OFFSETS. This (for me  anyway)
  40. is probably the hardest part of assembly to understand.
  41. Segments and offsets:
  42.  
  43. The original designers of the 8088 decided that nobody will  every  need  to
  44. use more that one megabyte of memory. So they built the chip so it  couldn't
  45. access above that. The problem is to access a whole  megabyte  20  bits  are
  46. needed (one bit being either a one or a zero). Registers only have  16  bits
  47. and they didn't want to use two because that  would  be  32  bits  and  they
  48. thought that this would be too much for  anyone.  They  decided  to  do  the
  49. addressing with two registers but not 32 bits. Is this confusing? Blame  the
  50. designers of the 8088.
  51.  
  52. OFFSET = SEGMENT * 16
  53. SEGMENT = OFFSET / 16 (the lower 4 bits are lost)
  54.  
  55. SEGMENT * 16     |0010010000010000 - ---|  range (0 to 65535) * 16
  56. OFFSET                 |-- - -0100100000100010|  range (0 to 65535)
  57. 20 bit address         |00101000100100100010|  range 0 to 1048575 (1 MEG)
  58.                          =====  DS =====
  59.                                   ====== SI =====
  60.  
  61. (note DS and SI overlap). This is how  DS:SI  is  used  to  make  a  20  bit
  62. address. The segment is in DS and the offset is in SI.
  63. Segment registers are: CS, DS, ES, SS. On the 386+ there are also FS & GS
  64.  
  65. Offset registers  are: BX, DI, SI, BP, SP, IP.  In 386+ protected mode,  ANY
  66. general register (not  a  segment  register)  can  be  used  as  an   Offset
  67. register.  (Except IP, which you can't access.)
  68.  
  69. Registers:
  70.  
  71. AX, BX, CX and DX are general purpose registers.  On  a  386+  they  are  32
  72. bits; EAX, EBX, ECX and EDX. The all can be  split  up  into  high  and  low
  73. parts, each being 8 bits.
  74.  
  75. EAX   32 bits
  76. AX    16 bits
  77. AH    8 bits
  78. AL    8 bits
  79.  
  80. This means that you can use AH and AL to store different numbers  and  treat
  81. them as separate registers for some tasks.
  82.  
  83. BX (BH/BL): same as AX
  84. CX (CH/CL): Same as AX (used for loops)
  85. DX (DH/DL): Same as AX (used for multiplication/division)
  86.  
  87. DI and SI are index registers and can be used as offset registers.
  88.  
  89. SP: Stack Pointer. Does just that. Points to the  current  position  in  the
  90. stack. Don't alter unless you REALLY know what you  are  doing  or  want  to
  91. crash your computer.
  92. The Stack:
  93.  
  94. This is and area of memory that is like a stack of plates. The last one  you
  95. put on is the first one that you take off (LOFO). If another piece  of  data
  96. is put on the stack it grows downwards.
  97.                                     [pic]
  98. Diagram 1: This shows how the stack is organised
  99.  
  100. PUSH and POP:
  101.  
  102. Push puts a value onto the stack and pop takes  it  back  off.  Here's  some
  103. code. (you can't compile this - yet.)
  104.  
  105.       push cx         ;put cx on the stack
  106.       push ax         ;put ax on the stack
  107.       .
  108.       .
  109.        .                ;this  is  going  to  pop  them   back   in        .
  110.  ;the wrong so they are reversed
  111.       pop cx          ;put value from stack into cx
  112.       pop ax          ;put value from stack into ax
  113.  
  114. This means that cx is equal to what ax is and ax is equal to what cx was.
  115. Some instructions:
  116.  
  117. MOV: this moves a value from one place to another.
  118.  
  119. Syntax:
  120. MOV destination, source
  121.  
  122. for example:
  123.        MOV  ax,10        ;moves  an  immediate  value  into  ax   MOV  bx,cx
  124. ;moves value from cx into bx
  125.  
  126.  
  127. INT: calls a DOS or BIOS function, mainly to do something you  would  rather
  128. not write a function for e.g. change video mode, open a file etc.
  129.  
  130. Syntax:
  131. INT interrupt number
  132.  
  133. Note: an h after a number denotes that that number is in hex.
  134.  
  135.       INT 21h         ;Calls DOS standard interrupt 21h
  136.       INT 10h         ;Calls the Video BIOS interrupt
  137.  
  138. All interrupts need a value to specify  what  subroutine  to  use.  This  is
  139. usually in AH. To print a message on the screen all you need to do is this:
  140.  
  141.       MOV ah,9      ;subroutine number 9
  142.       INT 21h       ;call the interrupt
  143.  
  144. But first you have to specify what to print. This function  needs  DS:DX  to
  145. be a far pointer to where the string is. The string  has  to  be  terminated
  146. with a dollar sign ($).
  147.  
  148. This example shows how it works:
  149.       MyMessage db    "This is a message!$"
  150.       .
  151.       .
  152.       .
  153.       mov dx,OFFSET MyMessage
  154.       mov ax,SEG MyMessage
  155.       mov ds,ax
  156.       mov ah,9
  157.       int 21h
  158.  
  159. DB declares a piece of data. This is the same as in BASIC:
  160.       LET MyMessage$ = "This is a message!"
  161.  
  162. DB declares a byte, DW declares a word and DD declares a Dword.
  163.  
  164. This is your first assembly program. Cut this in and then  assemble  it.  If
  165. you are using A86, type:
  166.       A86 name of file
  167. If you are using Turbo Assembler then type:
  168.       tasm name of file
  169.       tlink name of file minus extention
  170. With tlink you can make a .COM file by using a /t switch.
  171. ;THIS IS A SIMPLE PROGRAM TO DISPLAY A MESSAGE ON THE ;SCREEN. SHOULD
  172. OUTPUT This is a message! TO SCREEN AND ;RETURN WITH NO ERRORLEVEL. THIS
  173. CANΓÇÖT BE MADE INTO A .COM FILE WITH TLINK AS IT GENERATES AN ERROR.
  174.  
  175.       .MODEL SMALL ;Ignore the first two lines
  176.                     ;I'll explain what this means later.
  177.       .STACK        ;allocate a stack
  178.       .CODE        ;a directive to start code segment
  179.  
  180.         START:         ;generally   a   good   name    to    use    as    an
  181.  ;entry point
  182.  
  183.       JMP BEGIN    ;jump to BEGIN: (like goto)
  184.  
  185.       MyMessage db "This is a message!$"
  186.  
  187.       BEGIN:       ;code starts here
  188.  
  189.         mov   dx,OFFSET   MyMessage       ;put   the   offset   of   message
  190.             ;in DX
  191.         mov   ax,SEG    MyMessage      ;put    the    segment    that    the
  192.       ;message is in in AX
  193.       mov ds,ax                   ;copy AX into DS
  194.       mov ah,9                    ;move 9 into ah to call
  195.          int    21h                        ;function    9    of    interrupt
  196.                   ;21h       -       display       a        string        to
  197. ;screen.
  198.  
  199.       MOV ax,4c00h ;move the value of 4c00 hex into AX
  200.       INT 21h      ;call interrupt 21h, subroutine 4C ;which returns
  201. control to dos, otherwise it would of ;crashed. The 00 on the end means
  202. what errorlevel it ;would return to DOS. This can be checked in a batch
  203. file
  204.  
  205.       END START    ;end here
  206.  
  207. Some instructions that you need to know:
  208.  
  209. This is just a list of  some  basic  assembly  instructions  that  are  very
  210. important and are used often.
  211.  
  212. ADD   Add the contents of one number to another
  213.  
  214. Syntax:
  215.  
  216.       ADD operand1,operand2
  217.  
  218. This adds operand2 to operand1. The answer is stored in operand1.  Immediate
  219. data cannot be used as operand1 but can be used as operand2.
  220.  
  221. SUB   Subtract one number from another
  222.  
  223. Syntax:
  224.       SUB operand1,operand2
  225.  
  226. This subtracts operand2 from operand1. Immediate  data  cannot  be  used  as
  227. operand1 but can be used as operand2.
  228.  
  229. MUL   Multiplies two unsigned integers (always positive)
  230. IMUL  Multiplies two signed integers (either positive or negitive)
  231.  
  232. Syntax:
  233.       MUL register or variable
  234.       IMUL register or variable
  235.  
  236. This multiples the register given by the number in AL  or  AX  depending  on
  237. the size of the operand. The answer is given in AX. If the answer is  bigger
  238. than 16 bits then the answer is in DX:AX (the high 16 bits  in  DX  and  the
  239. low 16 bits in AX).
  240.  
  241. On a 386, 486 or Pentium the EAX register can be  used  and  the  answer  is
  242. stored in EDX:EAX.
  243.  
  244. DIV   Divides two unsigned integers(always positive)
  245. IDIV  Divides two signed integers (either positive or negitive)
  246.  
  247. Syntax:
  248.       DIV register or variable
  249.       IDIV register or variable
  250.  
  251. This works in the same way as MUL and IMUL by dividing the number in  AX  by
  252. the register or variable given. The answer  is  stored  in  two  places.  AL
  253. stores the answer and the remainder is in AH. If the operand  is  a  16  bit
  254. register than the number in DX:AX is divided by the operand and  the  answer
  255. is stored in AX and remainder in DX.
  256. The way we entered the address of the message we wanted to print was  a  bit
  257. cumbersome. It took three lines and it isnΓÇÖt the easiest thing to remember
  258.  
  259.       mov dx,OFFSET MyMessage
  260.       mov ax,SEG MyMessage
  261.       mov ds,ax
  262.  
  263. We can replace all this with just one line. This makes the code easier to
  264. read and it easier to remember. This only works if the data is only in the
  265. data is in one segment i.e. small memory model.
  266.  
  267.       lea dx,MyMessage
  268. or    mov dx,OFFSET MyMessage
  269. Using lea is slightly slower and results in code which is larger.
  270.  
  271. LEA means Load Effective Address.
  272.  
  273. Syntax:
  274. LEA destination,source
  275.  
  276. Desination can be any 16 bit register and the source must be a memory
  277. operand (bit of data in memory). It puts the offset address of the source
  278. in the destination.
  279.  
  280. Keyboard input:
  281.  
  282. We are going to use interrupt 16h, function 00h to read the  keyboard.  This
  283. gets a key from the keyboard buffer.  If there isn't  one,  it  waits  until
  284. there is. It returns the SCAN code in AH and the ASCII translation in AL.
  285.  
  286.         MOV ah,00h           ;function 00h of
  287.    INT 16h       ;interrupt 16h
  288.  
  289. All we need to worry about for now is the ascii value which is in al.
  290.  
  291. Printing a character:
  292.  
  293. The problem is that we have the key that has been pressed in ah. How  do  we
  294. display it? We can't use function 9h  because  for  that  we  need  to  have
  295. already defined the string which has to end with  a  dollar  sign.  This  is
  296. what we do instead:
  297.  
  298. ;after calling function 00h of interrupt 16h
  299.         MOV dl,al       ;move al (ascii code) into dl
  300.         MOV ah,02h      ;function 02h of interrupt 21h
  301.         INT 21h         ;call interrupt 21h
  302.  
  303. If you want to save the  value  of  ah  then  push  it  before  and  pop  it
  304. afterwards.
  305. Control flow:
  306. Firstly, the most basic command:
  307.       JMP label
  308. This is the same as GOTO in basic.
  309.  
  310.             JMP ALabel
  311.      .
  312.       .
  313.       ALabel:
  314.       ;code to do something
  315.  
  316. What do we do if we want to compare somthing. We have just got  a  key  from
  317. the user but we want to do something with it. Lets print  something  out  if
  318. it is equal to somethine else. How do we do that? Its easy. We use the  jump
  319. on condition commands. Here is a list of them:
  320.  
  321. Jump on condition commands:
  322.  
  323. |JA     |jumps if the first number was above the second number |
  324. |JAE    |same as above, but will also jump if they are equal   |
  325. |JB     |jumps if the first number was below the second        |
  326. |JBE    |same as above, but will also jump if they are equal   |
  327. |JNA    |jumps if the first number was NOT above  (same as JBE)|
  328. |JNAE   |jumps if the first number was NOT above or the same as|
  329. |       |(same as JB)                                          |
  330. |JNB    |jumps if the first number was NOT below (same as JAE) |
  331. |JNBE   |jumps if the first number was NOT below or the same as|
  332. |       |(same as JA)                                          |
  333. |JZ     |jumps if the two numbers were equal                   |
  334. |JE     |same as JZ, just a different name                     |
  335. |JNZ    |jumps if the two numbers are NOT equal                |
  336. |JNE    |same as above                                         |
  337.  
  338.  
  339. [NOTE: There are quite a few more but these are  the  most  useful.  If  you
  340. want the full list then get a good assembly book]
  341.  
  342. They are very easy to use.
  343.  
  344. Syntax:
  345.         CMP register containing value, a value
  346.     jump command destination
  347.  
  348. An example of this is:
  349.       cmp al,'Y'      ;compare the value in al with Y
  350.       je ItsYES       ;if it is equal then jump to ItsYES
  351. The following program is an example of how to use control and input and
  352. output.
  353.  
  354. .MODEL  SMALL
  355. .STACK                            ;define a stack
  356. .CODE
  357. Start:                            ;a good place to start.
  358.  
  359.       lea dx,StartUpMessage       ;display a message on th e
  360.             ;screen
  361.       mov ah,9                ;using function 09h
  362.       int 21h                 ;of interrupt 21h
  363.       lea dx,Instructions     ;display a message on the
  364.       ;screen
  365.       mov ah,9                ;using function 09h
  366.       int 21h                 ;of interrupt 21h
  367.  
  368.        mov ah,00h              ;function 00h of
  369.       int 16h                 ;interrupt 16h gets a
  370.             ;character from user
  371.       mov bl,al               ;save bl
  372.       mov dl,al               ;move ascii value of key
  373.             ;pressed to dl
  374.  
  375.        mov ah,02h              ;function 02h of
  376.       int 21h                 ;interrupt 21h displays a
  377.         ;character to screen
  378.       cmp bl,'Y'              ;is al=Y?
  379.       je Thanks                   ;if yes then goto Thanks
  380.        cmp bl,'y'              ;is al=y?
  381.       je Thanks              ;if yes then goto Thanks
  382.       jmp TheEnd
  383. Thanks:
  384.       lea dx,ThanksMsg        ;display message
  385.       mov ah,9                ;using function 9
  386.       int 21h                 ;of interrupt 21h
  387. TheEnd:
  388.       lea dx,GoodBye          ;print goodbye message
  389.       mov ah,9                ;using function 9
  390.       int 21h                 ;of interrupt 21h
  391.       mov AX,4C00h            ;terminate program and
  392.             ;return to DOS using
  393.       INT 21h                 ;interrupt 21h function 4CH
  394.  
  395. .DATA
  396. ;0Dh,0Ah adds a enter at the beginning
  397.  
  398. StartUpMessage DB "A Simple Input Program$"
  399. Instructions  DB 0Dh,0Ah,"Just press a Y to continue...$ΓÇ¥
  400. ThanksMsg      DB 0Dh,0Ah,"Thanks for pressing Y!$"
  401. GoodBye        DB 0Dh,0Ah,"Have a nice day!$"
  402.  
  403.         END
  404. Procedures:
  405.  
  406. Assembly, like C and Pascal can have procedures. These are very  useful  for
  407. series of commands that have to be repeated often.
  408.  
  409. This is how a procedure is defined:
  410.  
  411. PROC AProcedure
  412.     .
  413.     .          ;some code to do something
  414.     .
  415.     RET          ;if this is not here then your computer
  416. ;will crash
  417. ENDP AProcedure
  418.  
  419. You can specify how you want the procedure to be called by adding a  FAR  or
  420. a NEAR after the procedure name. Otherwise it defaults to the  memory  model
  421. you are using. For now you are better off not doing this  until  you  become
  422. more experianced. I usually add a NEAR in as compilers canΓÇÖt decide  between
  423. a near and a far very well. This means if the  jump  needs  to  be  far  the
  424. compiler will warn you and you can change it.
  425.  
  426. This is a program which uses a procedure.
  427.  
  428. ;a simple program with a procedure that prints a message ;onto the screen.
  429. (Use /t switch with tlink). Should ;display Hello There! on the screen.
  430.  
  431. .MODEL  TINY
  432. .CODE
  433. ORG     100h
  434.  
  435. MAIN    PROC
  436.          JMP Start             ;skip the data
  437. HI      DB "Hello There!$" ;define a message
  438. Start:                         ;a good place to start.
  439.         Call Display_Hi    ;Call the procedure
  440.         MOV AX,4C00h       ;terminate program and return
  441.         ;to DOS using
  442.         INT 21h            ;interrupt 21h function 4Ch
  443.  
  444. Display_Hi PROC            ;Defines start of procedure
  445.         lea dx,HI          ;put offset of message into DX
  446.         mov ah,9           ;function 9 of
  447.         int 21h            ;interrupt 21h
  448.         RET                ;THIS HAS TO BE HERE
  449. Display_Hi ENDP            ;Defines end of procedure
  450.  
  451. Main    ENDP
  452.         END MAIN
  453. Memory Models:
  454.  
  455. We have been using the .MODEL directive  to  specify  what  type  of  memory
  456. model we  use, but what does this mean?
  457.  
  458. Syntax:
  459.       .MODEL MemoryModel
  460.  
  461. Where MemoryModel can be SMALL, COMPACT, MEDIUM, LARGE, HUGE, TINY OR FLAT.
  462.  
  463. Tiny:
  464. This means that there is only one segment for both code and data. This  type
  465. of program can be a .COM file.
  466.  
  467. Small:
  468. This means that by default all code is place in  one  physical  segment  and
  469. likewise all data declared in  the  data  segment  is  also  placed  in  one
  470. physical segment. This means that all proedures and variables are  addressed
  471. as NEAR by pointing at offsets only.
  472.  
  473. Compact:
  474. This means that by default all elements of code (procedures) are  placed  in
  475. one physical segment but each element of data  can  be  placed  in  its  own
  476. physical segment. This means that data elements are  addressed  by  pointing
  477. at both at the segment and offset addresses. Code elements (procedures)  are
  478. NEAR and varaibles are FAR.
  479.  
  480. Medium:
  481. This is the opposite to compact. Data elements are near and  procedures  are
  482. FAR.
  483.  
  484. Large:
  485. This means that both procedures and variables are FAR. You have to point  at
  486. both the segment and offset addresses.
  487.  
  488. Flat:
  489. This isnΓÇÖt used much as it is for 32 bit unsegmented memory space. For  this
  490. you need a dos extender. This is what you would have  to  use  if  you  were
  491. writing a program to  interface  with  a  C/C++  program  that  used  a  dos
  492. extender such as DOS4GW or PharLap.
  493.  
  494. Macros:
  495.  
  496. (All code examples given are for macros in Turbo Assembler. For A86 either
  497. see the documentation or look in the A86 macro example later in this
  498. document).
  499.  
  500. Macros are very useful for doing something that is done often but for  which
  501. a procedure canΓÇÖt be  use.  Macros  are  substituted  when  the  program  is
  502. compiled to the code which they contain.
  503.  
  504. This is the syntax for defining a macro:
  505.  
  506. Name_of_macro    macro
  507. ;
  508. ;a sequence of instructions
  509. ;
  510. endm
  511.  
  512. These two examples are for macros that take away the boring job  of  pushing
  513. and popping certain registers:
  514.  
  515.       SaveRegs macro
  516.             pop ax
  517.             pop bx
  518.             pop cx
  519.             pop dx
  520.       endm
  521.       RestoreRegs macro
  522.             pop dx
  523.             pop cx
  524.             pop bx
  525.             pop ax
  526.       endm
  527. Note that the registers are popped in the reverse order to they wer popped.
  528.  
  529. To use a macro in you program you just use the  name  of  the  macro  as  an
  530. ordinary macro instruction:
  531.  
  532.       SaveRegs
  533.       ;some other instructions
  534.       RestoreRegs
  535.  
  536. This example shows how you can use a macro to save  typing  in.  This  macro
  537. simply prints out a variable to the screen.
  538.  
  539. The only problems with macros is that if you overuse them it  leads  to  you
  540. program getting bigger and bigger and that you have problems  with  multiple
  541. definition of labels and variables. The correct way to  solve  this  problem
  542. is to use the LOCAL directive for declaring names inside macros.
  543.  
  544. Syntax:
  545.       LOCAL name
  546. Where ΓÇ£nameΓÇ¥ is the name of a local variable or label.
  547.  
  548. If you have comments in a macro everytime you use that  macro  the  comments
  549. will be added again into your source code. This means that  it  will  become
  550. unesescarily long. The way to get round this is to define  comments  with  a
  551. ;; instead of a ;. This example illustrates this.
  552.  
  553.       ;a normal comment
  554.       ;;a comment in a macro to save space
  555.  
  556. Macros with parameters:
  557. Another useful property of macros is that  they  can  have  parameters.  The
  558. number of parameters is only restricted by the length of the line.
  559.  
  560. Syntax:
  561. Name_of_Macro macro par1,par2,par3
  562. ;
  563. ;commands go here
  564. endm
  565.  
  566. This is an example that adds the first and second parameters  and  puts  the
  567. result in the third:
  568.  
  569.       AddMacro macro num1,num2,result
  570.             push ax          ;save ax from being destroyed
  571.             mov ax,num1      ;put num1 into ax
  572.             add ax,num2      ;add num2 to it
  573.             mov result,ax    ;move answer into result
  574.             pop ax           ;restore ax
  575.       endm
  576.  
  577. On the next page there is an example of some a useful macro to exit  to  dos
  578. with a specified . There are two versions of this program because  both  A86
  579. and Turbo Assembler handle macros differently.
  580. ;this is a simple program which does nothing but use a ;macro to exit to
  581. dos. This will only work with tasm and ;should be compiled like this: tasm
  582. /m2 macro.asm
  583. ;because tasm needs more than one pass to work out what ;to do with macros.
  584. It does cause a warning but this can ;be ignored.
  585.  
  586. .MODEL small
  587. .STACK
  588. .CODE        ;start the code segment
  589.  
  590. Start:       ;a good a place as any to start this
  591.  
  592. ;now lets go back to dos with another macro
  593.       BackToDOS 0     ;the errorlevel will be 0
  594.  
  595. BackToDOS macro errorlevel
  596.  
  597. ;;this is a macro to exit to dos with a specified ;;errorlevel given. No
  598. test is done to make sure that a
  599. ;;procedure is actually passed or it is within range.
  600.  
  601.       mov ah,4Ch          ;;terminate program and return
  602.                                   ;;to DOS using
  603.       mov al,errorlevel   ;;put errorlevel into al
  604.       int 21h             ;;interrupt 21h function 4Ch
  605.  
  606.       endm                   ;;end macro
  607. end                          ;end program
  608. Procedures that pass parametres:
  609. Procedures can be made even  more  useful  if  they  can  be  made  to  pass
  610. parameters to each other. There are three ways of  doing  this  and  I  will
  611. cover all three methods:
  612. ΓÇó In registers,
  613. ΓÇó In memory,
  614. ΓÇó In stack.
  615.  
  616. In registers:
  617.  
  618. Advantages:      Easy to do and fast.
  619. Disadvantages:   The is not many registers.
  620.  
  621. This is very easy to do, all you have to do is to  is  move  the  parameters
  622. into registers before calling the procedure. This example adds  two  numbers
  623. together and then divides by the third it then returns the answer in dx.
  624.  
  625.       push ax          ;save value of ax
  626.       push bx          ;save value of bx
  627.       push cx          ;save value of cx
  628.       mov ax,10        ;first parameter is 10
  629.       mov bx,20        ;second parameter is 20
  630.       mov cx,3         ;third parameter is 3
  631.       Call ChangeNumbers ;call procedure
  632.       pop cx           ;restore cx
  633.       pop bx           ;restore bx
  634.       pop ax           ;restore dx
  635. .....
  636. ChangeNumbers PROC     ;Defines start of procedure
  637.       add ax,bx        ;adds number in bx to ax
  638.       div cx           ;divides ax by cx
  639.       mov dx,ax        ;return answer in dx
  640.       ret
  641. ChangeNumbers ENDP     ;defines end of procedure
  642. How to use a debugger:
  643.  
  644. This is a good time to use a debugger to  find  out  what  your  program  is
  645. actually doing. I am going to demonstrate  how  to  use  Turbo  Debugger  to
  646. check if this program is working properly. First we  need  to  compile  this
  647. program to either a .EXE or .COM file. Then type:
  648.       td name of file
  649. Turbo Debugger then loads. You can see the instructions that  make  up  your
  650. programs,  for example the first few lines of this program is shown as:
  651.       cs:0000 50       push   ax
  652.       cs:0001 53       push   bx
  653.       cs:0002 51       push   cx
  654. (This might be slighly different than is shown on your screen but  hopefully
  655. you will get the main idea)
  656. [pic]This diagram shows what the Turbo Debugger(  screen looks like
  657.  
  658. The numbers that are moved into the registers are different  that  the  ones
  659. that we typed in because they are represented in their hex  form  (base  16)
  660. as this is the easiest base to convert to and from binary  and  that  it  is
  661. easier to understand than binary also.
  662.  
  663. At the left of this display there is a  box  showing  the  contents  of  the
  664. registers. At this time all the main registers are empty. Now press F7  this
  665. means that the first line of the program is run. As the  first  line  pushed
  666. the ax register into the stack, you can see that the stack pointer (SP)  has
  667. changed. Press F7 until the line which contains mov ax,000A is  highlighted.
  668. Now press it again. Now if you look at the box which contains  the  contents
  669. of the registers you can see that AX contains A. Press it again and  BX  now
  670. contains 14, press it again and CX contains 3. Now if  you  press  F7  again
  671. you can see that AX now contains 1E which is A+14. Press it  again  and  now
  672. AX contains A again, A being 1E divided by 3 (30/3 =  10).  Press  F7  again
  673. and you will see that DX now also contains A. Press it three more times  and
  674. you can see that CX,BX and AX are all set back to their origional values  of
  675. zero.
  676. Passing through memory:
  677.  
  678. Advantages:      Easy to do and can use more parameters
  679. Disadvantages:   Can be slower
  680.  
  681. To pass parameters through memory all you need to  do  is  copy  them  to  a
  682. variable which is stored in memory. You can use a varable in  the  same  way
  683. that you can use a register but commands with registers are  a  lot  faster.
  684. This table shows the timing for the MOV  command  with  registers  and  then
  685. variables and then the amount of clock cycles (the speed -  smaller  faster)
  686. it takes to do them.
  687.  
  688. KEY:  reg8 means an 8 bit register eg AL
  689.       mem8 means an 8 bit variable declared with DB
  690.       reg16 means an 16 bit register eg AX
  691.       mem16 means an 16 bit variable declared with DW
  692.       imm8 means an immediate byte eg MOV al,8
  693.       imm16 means an immediate word eg MOV ax,8
  694.  
  695. |Instruction          |486 |386 |286 |86  |
  696. |MOV reg/mem8,reg8    |1   |2/2 |2/3 |2/9 |
  697. |MOV reg,mem16,reg16  |1   |2/2 |2/3 |2/9 |
  698. |MOV reg8,reg/mem8    |1   |2/4 |2/5 |2/8 |
  699. |MOV reg16,reg/mem16  |1   |2/4 |2/5 |2/8 |
  700. |MOV reg8,imm8        |1   |2   |2   |4   |
  701. |MOV reg16,imm16      |1   |2   |2   |4   |
  702. |MOV reg/mem8,imm8    |1   |2/2 |2/3 |4/10|
  703. |MOV reg/mem16,imm16  |1   |2/2 |2/3 |4/10|
  704.  
  705.  
  706. These timings are taking from the ΓÇÿBorland( Turbo Assembler( Quick
  707. ReferenceΓÇÖ
  708.  
  709. This shows that  on  the  8086  using  variables  in  memory  can  make  the
  710. instuction four times as slow. This means that you should  avoid  using  too
  711. many  variables  unnecessarily.  On  the  486  it  doesnΓÇÖt  matter  as  both
  712. instructions take the same amount of time.
  713.  
  714. The method actually used  is  nearly  identical  to  passing  parameters  in
  715. registers. This example is just another version of  the  example  given  for
  716. passing in registers.
  717. FirstParam  db 0  ;these are all variables to store
  718. SecondParam db 0  ;the parameters for the program
  719. ThirdParam  db 0
  720. Answer        db 0
  721. .....
  722.       mov FirstParam,10      ;first parameter is 10                 mov
  723. SecondParam,20   ;second parameter is 20
  724.       mov ThirdParam,3 ;third parameter is 3
  725.       Call ChangeNumbers
  726. .....
  727. ChangeNumbers PROC          ;Defines start of procedure
  728.       push ax                ;save ax
  729.       push bx                ;save bx
  730.       mov ax,FirstParam      ;copy FirstParam into ax
  731.       mov bx,SecondParam     ;copy SecondParam into bx
  732.       add ax,bx              ;adds number in bx to ax
  733.       mov bx,ThirdParam      ;copy ThirdParam into bx
  734.       div bx                 ;divides ax by bx
  735.       mov Answer,ax          ;return answer in Answer
  736.       pop bx                 ;restore bx
  737.       pop ax                 ;restore ax
  738.       ret
  739. ChangeNumbers ENDP           ;defines end of procedure
  740.  
  741. This way may seem more complicated but it is not  really  suited  for  small
  742. numbers of this type of parameters. It is  much  more  useful  when  dealing
  743. with strings or large numbers of big values.
  744.  
  745. Passing through Stack:
  746.  
  747. This is the most powerful and flexible method of  passing  parameters.  This
  748. example shows the ChangeNumbers procedure that has been  rewritten  to  pass
  749. its parameters through the stack.
  750.       mov ax,10        ;first parameter is 10
  751.       mov bx,20        ;second parameter is 20
  752.       mov cx,3         ;third parameter is 3
  753.       push ax          ;put first parameter on stack
  754.       push bx          ;put second parameter on stack
  755.       push cx          ;put third parameter on stack
  756.       Call ChangeNumbers
  757. .....
  758. ChangeNumbers PROC     ;Defines start of procedure
  759.       push bp
  760.       mov bp,sp
  761.       mov ax,[bp+8]    ;get the parameters from bp
  762.       mov bx,[bp+6]  ;remember that first it is last out
  763.       mov cx,[bp+4]    ;so number is larger
  764.       add ax,bx        ;adds number in bx to ax
  765.       div cx           ;divides ax by cx
  766.       mov dx,ax        ;return answer in dx
  767.       ret
  768. ChangeNumbers ENDP     ;defines end of procedure
  769.  
  770. This diagram shows the contents of the stack for a program with two
  771. parameters:
  772.                                     [pic]
  773.  
  774. To get a parameter from the stack all you need to do is work  out  where  it
  775. is. The last parameter is at BP+2 and then the next and BP+4.
  776. Files and how to used them:
  777.  
  778. Files can be opened, read and written to. DOS has some ways  of  doing  this
  779. which  save  us  the  trouble  of  writing  our  own  routines.  Yes,   more
  780. interrupts. Here is a list of helpful functions of  interrupt  21h  that  we
  781. are going to need to use for our simple file viewer.
  782.  
  783. Function 3Dh: open file
  784. Opens an existing file for reading, writing or appending  on  the  specified
  785. drive and filename.
  786.  
  787. INPUT:
  788.         AH = 3Dh
  789.         AL = access mode
  790.              bits 0-2   000 = read only
  791.                         001 = write only
  792.                         010 = read/write
  793.              bits 4-6   Sharing mode (DOS 3+)
  794.                         000 = compatibility mode
  795.                         001 = deny all  (only  current  program  can  access
  796. file)
  797.                         010 = deny write (other programs can only read it)
  798.                         011 = deny read (other programs can  only  write  to
  799. it)
  800.                         100 = deny none
  801.         DS:DX = segment:offset of ASCIIZ pathname
  802.  
  803. OUTPUT:
  804.         CF = 0 function is succesful
  805.         AX = handle
  806.         CF = 1 error has occured
  807.         AX = error code
  808.                 01h missing file sharing software
  809.                 02h file not found
  810.                 03h path not found or file does not exist
  811.                 04h no handle available
  812.                 05h access denied
  813.                 0Ch access mode not permitted
  814.  
  815. What does ASCIIZ mean? An ASCIIZ string is a ASCII string  with  a  zero  on
  816. the end (instead of a dollar sign).
  817.  
  818. Important: Remember to save the file handle it is needed for later.
  819.  
  820. How to save the file handle:
  821. It is important to save the  file  handle  because  this  is  needed  to  do
  822. anything with the file. Well how is this done? There are two methods,  which
  823. is better?
  824.  
  825. ΓÇó Copy the file handle into another register and don't use that register.
  826. ΓÇó Copy it to a variable in memory.
  827.  
  828. The disadvantages with the first method is that you will  have  to  remember
  829. not to use the register you saved it in and it wastes a  register  that  can
  830. be used for something more useful. We are going to use the second.  This  is
  831. how it is done:
  832.  
  833.       FileHandle DW 0     ;use this for saving the file
  834. ;handle
  835.  
  836.      MOV FileHandle,ax   ;save the file handle (same as
  837. ;FileHandle=ax)
  838.  
  839.  
  840. Function 3Eh: close file
  841. Closes a file that has been opened.
  842.  
  843. INPUT:
  844.         AX = 3Eh
  845.         BX = file handle
  846.  
  847. OUTPUT:
  848.         CF = 0 function is sucsessful
  849.         AX = destroyed
  850.         CF = 1 function not sucsessful
  851.         AX = error code - 06h file not opened or unautorized handle.
  852.  
  853. Important: Don't call this function with a zero  handle  because  that  will
  854. close the standard input (the keyboard) and  you  won't  be  able  to  enter
  855. anything.
  856.  
  857. Function 3Fh: read file/device
  858. Reads bytes from a file or device to a buffer.
  859.  
  860. INPUT:
  861.         AH = 3Fh
  862.         BX = handle
  863.         CX = number of bytes to be read
  864.         DS:DX = segment:offset of a buffer
  865.  
  866. OUTPUT:
  867.         CF = 0 function is successful
  868.         AX = number of bytes read
  869.         CF = 1 an error has occured
  870.                 05h access denied
  871.                 06h illegal handle or file not opened
  872. If CF = 0 and AX = 0 then the file pointer was already at  the  end  of  the
  873. file and no more can be read. If CF = 0 and AX is smaller than CX then  only
  874. part was read because the end of the file was reached or an error occured.
  875.  
  876. This function can also be used to get input from the keyboard. Use a  handle
  877. of 0, and it stops reading after  the  first  carriage  return,  or  once  a
  878. specified number of characters have been read.  This  is  a  good  and  easy
  879. method to use to only let the user enter a certain amount of characters.
  880.  
  881. Note: If you are using A86 this will cause an error. Change  @data  to  data
  882. to make it work.
  883.  
  884. .MODEL small
  885. .STACK
  886. .CODE
  887.       mov ax,@data     ;base jaddress of data
  888.       mov ds,ax        ;segment
  889.  
  890.       lea dx,FileName  ;put address of fileneame in dx
  891.       mov al,2         ;access mode - read and write
  892.       mov ah,3Dh       ;function 3Dh -open a file
  893.       int 21h          ;call DOS service
  894.       mov Handle,ax    ;save file handle for later
  895.       jc ErrorOpening
  896.  
  897.       mov dx,offset Buffer  ;address of buffer in dx
  898.       mov bx,Handle         ;handle in bx
  899.       mov cx,100            ;amount of bytes to be read
  900.       mov ah,3Fh            ;function 3Fh - read from file
  901.       int 21h               ;call dos service
  902.       jc ErrorReading
  903.  
  904.       mov bx,Handle    ;put file handle in bx
  905.       mov ah,3Eh       ;function 3Eh - close a file
  906.       int 21h          ;call dos service
  907.  
  908.       mov di,OFFSET Buffer+101  ;Where to put the "$"
  909.       mov byte ptr [di],"$"     ;Put it at es:di
  910.       mov ah,9                  ;write a string to the
  911.       mov dx,OFFSET Buffer    ;screen using function 9h
  912.       int 21h                      ;of interrupt 21h
  913.  
  914.       mov AX,4C00h     ;terminate program and return to
  915.                                                                       ;DOS
  916. using
  917.       INT 21h          ;interrupt 21h function 4CH
  918.  
  919. ErrorOpening:
  920.       mov dx,offset OpenError ;display an error
  921.  
  922.       mov ah,09h       ;using function 09h
  923.       int 21h          ;call dos service
  924.  
  925.  
  926.      mov ax,4C01h ;end program with an errorlevel of 1
  927.       int 21h
  928.  
  929. ErrorReading:
  930.       mov dx,offset ReadError ;display an error
  931.                                                    mov ah,09h       ;using
  932. function 09h
  933.       int 21h          ;call dos service
  934.  
  935.       mov ax,4C02h ;end program with an errorlevel of 2
  936.         int 21h
  937.  
  938. .DATA
  939.  
  940. Handle        DW ? ;variable to store file handle
  941. FileName      DB "C:\test.txt",0 ;file to be opened
  942.  
  943. OpenError     DB "An error has occured(opening)!$"
  944. ReadError     DB "An error has occured(reading)!$"
  945.  
  946. Buffer        DB 101 dup (?) ;buffer to store data from
  947.                                                        ;file one bigger for
  948. $
  949. END
  950.  
  951. Function: 3Ch: Create file
  952. Creates a new empty file on a specified drive with a specified pathname.
  953.  
  954. INPUT:
  955.         AH = 3Ch
  956.         CX = file attribute
  957.                 bit 0 = 1 read-only file
  958.                 bit 1 = 1 hidden file
  959.                 bit 2 = 1 system file
  960.                 bit 3 = 1 volume (ignored)
  961.                 bit 4 = 1 reserved (0) - directory
  962.                 bit 5 = 1 archive bit
  963.                 bits 6-15 reserved (0)
  964.     DS:DX = segment:offset of ASCIIZ pathname
  965.  
  966. OUTPUT:
  967.     CF = 0 function is successuful
  968.     AX = handle
  969.     CF = 1 an error has occured
  970.                 03h path not found
  971.                 04h no availible handle
  972.                 05h access denied
  973.  
  974. Important: If a file of the same name exists then  it  will  be  lost.  Make
  975. sure that there is no file of the same name.  This  can  be  done  with  the
  976. function below.
  977.  
  978. Function 4Eh: find first matching file
  979. Searches for the first file that matches the filename given.
  980.  
  981. INPUT:
  982.     AH = 4Eh
  983.     CX = file attribute mask (bits can be combined)
  984.                 bit 0 = 1 read only
  985.                 bit 1 = 1 hidden
  986.                 bit 2 = 1 system
  987.                 bit 3 = 1 volume label
  988.                 bit 4 = 1 directory
  989.                 bit 5 = 1 archive
  990.                 bit 6-15 reserved
  991.     DS:DX = segment:offset of ASCIIZ pathname
  992.  
  993. OUTPUT:
  994.     CF = 0 function is successful
  995.     [DTA] Disk Transfer Area = FindFirst data block
  996.  
  997. Example of checking if file exists:
  998. File    DB "C:\file.txt",0   ;name of file that we want
  999.  
  1000.         LEA dx,File      ;address of filename
  1001.         MOV cx,3Fh       ;file mask 3Fh - any file
  1002.         MOV ah,4Eh           ;function 4Eh - find first file
  1003.         INT 21h          ;call dos service
  1004.         JC NoFile
  1005.         ;print message saying file exists
  1006. NoFile:
  1007.         ;continue with creating file
  1008. This example program creates a file and then writes to it.
  1009. .MODELSMALL
  1010. .STACK
  1011. .CODE
  1012.       mov ax,@data     ;base jaddress of data
  1013.       mov ds,ax        ;segment
  1014.  
  1015.       mov dx,offset StartMessage    ;display the starting
  1016.                  ;message
  1017.      mov ah,09h     ;using function 09h
  1018.      int 21h        ;call dos service
  1019.  
  1020.      mov dx,offset FileName ;put offset of filename in dx
  1021.      xor cx,cx      ;clear cx - make ordinary file
  1022.      mov ah,3Ch     ;function 3Ch - create a file
  1023.      int 21h        ;call DOS service
  1024.      jc Error       ;jump if there is an error
  1025.  
  1026.      mov dx,offset FileName ;put offset of filename in dx
  1027.      mov al,2       ;access mode -read and write
  1028.      mov ah,3Dh     ;function 3Dh - open the file
  1029.      int 21h        ;call dos service
  1030.      jc Error       ;jump if there is an error
  1031.      mov Handle,ax  ;save value of handle
  1032.  
  1033.      mov dx,offset WriteMe   ;address of information to
  1034.       ;write to the file
  1035.      mov bx,Handle  ;file handle for file
  1036.      mov cx,38      ;38 bytes to be written
  1037.      mov ah,40h     ;function 40h write to file
  1038.      int 21h        ;call dos service
  1039.      jc error       ;jump if there is an error
  1040.      cmp ax,cx      ;was all the data written? Does
  1041. ;ax=cx?
  1042.      jne error      ;if it wasn't then there was an error
  1043.  
  1044.      mov bx,Handle  ;put file handle in bx
  1045.      mov ah,3Eh     ;function 3Eh - close a file
  1046.      int 21h        ;call dos service
  1047.  
  1048.      mov dx,offset EndMessage ;display the final message
  1049.             ;on the screen
  1050.      mov ah,09h     ;using function 09h
  1051.      int 21h        ;call dos service
  1052.  
  1053. ReturnToDOS:
  1054.      mov AX,4C00h   ;terminate program and return to DOS
  1055.      int 21h        ;using interrupt 21h function 4CH
  1056.  
  1057. Error:
  1058.      mov dx,offset ErrorMessage ;display an error message
  1059.               ;on the screen
  1060.      mov ah,09h      ;using function 09h
  1061.      int 21h         ;call dos service
  1062.      jmp ReturnToDOS ;lets end this now
  1063.  
  1064. .DATA
  1065. StartMessage    DB "This program creates a file calledΓÇ¥,
  1066.   ΓÇ£NEW.TXT in the C: directory.$"
  1067. EndMessage      DB 0Ah,0Dh,"File create OK, look atΓÇ¥,
  1068.   ΓÇ£file to be sure.$"
  1069. Handle          DW ? ;variable to store file handle
  1070. ErrorMessage    DB "An error has occurred!$"
  1071. WriteMe         DB "HELLO, THIS IS A TEST, HAS ITΓÇ¥,
  1072.   ΓÇ£WORKED?",0 ;ASCIIZ
  1073. FileName        DB "C:\new.txt",0
  1074. END
  1075.  
  1076. How to find out the DOS version:
  1077.  
  1078. In many programs it is necessary to find out what the DOS version  is.  This
  1079. could be because you are using a DOS function that needs the revision to  be
  1080. over a certain level.
  1081.  
  1082. Firstly this method simply finds out what the version is.
  1083.  
  1084.       mov   ah,30h     ;function 30h - get MS-DOS version
  1085.       int   21h        ;call DOS function
  1086.  
  1087. This function returns the major version number in AL and the  minor  version
  1088. number in AH. For example if it was version 4.01,  AL  would  be  4  and  AH
  1089. would be 01. The problem is that if on DOS 5 and higher  SETVER  can  change
  1090. the version that is returned. The way to get  round  this  is  to  use  this
  1091. method.
  1092.  
  1093.       mov   ah,33h    ;function 33h - actual DOS version
  1094.       mov   al,06h     ;subfunction 06h
  1095.       int   21h        ;call interrupt 21h
  1096.  
  1097. This will only work on DOS version 5 and above so you need  to  check  using
  1098. the former method. This will return  the  actual  version  of  DOS  even  if
  1099. SETVER has changed the version. This returns the major  version  in  BL  and
  1100. the minor version in BH.
  1101.  
  1102. Fast string print:
  1103.  
  1104. We have been using a DOS service, function 9 of interrupt  21h  to  print  a
  1105. string on the screen. This isnΓÇÖt too fast  nor  does  it  allow  us  to  use
  1106. different colours or position the text. There is  another  way  to  print  a
  1107. string to the screen - direct to memory. This is harder as you have  to  set
  1108. up everything manually but it has a lot of benifits mainly speed.
  1109.  
  1110. TextAttribute db 7     ;contains the character attribute
  1111.                        ;default is grey on black
  1112. ......
  1113. FastTextPrint PROC
  1114. .286    ;need this for shift instructions. Take out if less
  1115.         ;than 286
  1116. ;========================================================
  1117. ;INPUT: AH - Row
  1118. ;       AL - Column
  1119. ;       CX - Length of string
  1120. ;       DS:DX - The string
  1121. ;       TextAttribute - the colour of the text
  1122. ;OUTPUT: none
  1123. ;========================================================
  1124.         push ax bx cx dx bp si di es ;save registers
  1125.         mov bl,ah      ;move row into bl
  1126.         xor bh,bh        ;clear bh
  1127.         shl bx,5         ;shift bx 5 places to the left
  1128.         mov si,bx        ;move bx into si
  1129.         shl bx,2         ;shift bx 2 places to the left
  1130.         add bx,si        ;add si to bx
  1131.         xor ah,ah        ;clear ah
  1132.         shl ax,1         ;shift ax 1 place to the left
  1133.         add bx,ax        ;add ax onto bx
  1134.         mov ax,0b800h    ;ax contains text video memory
  1135.         mov es,ax        ;move ax into es
  1136.         mov si,dx        ;mov dx into si
  1137. FastTextPrintLoop:
  1138.        mov ah,ds:[si]  ;put the char at ds[si] into ah
  1139.        mov es:[bx],ah    ;move the char in ah to es[bx]
  1140.        inc si                ;increment si (si+1)
  1141.        inc bx            ;increment bx (bx+1)
  1142.        mov ah,TextAttribute ;put the attribute into ah
  1143.        mov es:[bx],ah    ;put ah into es position at bx
  1144.        inc bx            ;increment bx (bx+1)
  1145.        loop FastTextPrintLoop     ;loop CX times
  1146.        pop es di si bp dx cx bx ax ;restore registers
  1147.        ret             ;return
  1148. FastTextPrint ENDP
  1149. Explanation  of new terms in this procedure:
  1150.  
  1151. In this procedure there was several things that you have not come across
  1152. before. Firsly the lines:
  1153.  
  1154.       push ax bx cx dx bp si di es      ;save registers
  1155.       pop es di si bp dx cx bx ax       ;restore registers
  1156.  
  1157. This is just an easier way of pushing and popping more than one register.
  1158. When TASM (or A86) compiles these lines it translates it into separate
  1159. pushes an pops. This way just saves you time typing and makes it easier to
  1160. understand.
  1161.  
  1162. Note: To make these lines compile in A86 you need to put commas (,) in
  1163. between the registers.
  1164.  
  1165. This line might cause difficulty to you at first but they are quite easy to
  1166. understand.
  1167.  
  1168.       mov ah,ds:[si]   ;put the char at ds[si] into ah
  1169.  
  1170. What this does is to move the number stored in DS at the location stored in
  1171. SI into AH. It is easier to think of DS being like an array in this
  1172. command. It is the same as this line in C.
  1173.  
  1174.       ah = ds[si];
  1175.  
  1176. Shifts:
  1177.  
  1178. There are four different ways of shifting numbers either left or right one
  1179. binary position.
  1180.  
  1181. SHL Unsigned multiple by two
  1182. SHR Unsigned devide by two
  1183. SAR Signed devide by two
  1184. SAL same as SHL
  1185.  
  1186. The syntax for all four is the same.
  1187.  
  1188. Syntax:
  1189. SHL operand1,operand2
  1190.  
  1191. Note: The 8086 cannot have the value of opperand2 other than 1. 286/386
  1192. cannot have operand2 higher than 31.
  1193.  
  1194. Using shifts is a lot faster than using MULΓÇÖs and DIVΓÇÖs.
  1195.  
  1196. Loops:
  1197.  
  1198. Using Loop is a better way of making a loop then using JMPΓÇÖs. You place the
  1199. amount of times you want it to loop in the CX register and every time it
  1200. reackes the loop statement it decrements CX (CX-1) and then does a short
  1201. jump to the label indicated. A short jum means that it can only 128 bytes
  1202. before or 127 bytes after the LOOP instuction.
  1203.  
  1204. Syntax:
  1205. Loop Label
  1206.  
  1207. Using graphics in mode 13h:
  1208.  
  1209. Mode 13h is only availible on VGA, MCGA cards and above. The reason  that  I
  1210. am talking about this card is that it is  very  easy  to  use  for  graphics
  1211. because of how the memory is arranged.
  1212.  
  1213. First check that mode 13h is possible:
  1214.  
  1215. It would be polite to tell the user if his computer cannot support mode  13h
  1216. instead of just crashing his computer without warning. This  is  how  it  is
  1217. done.
  1218.  
  1219. CheckMode13h:
  1220. ;Returns: DX=0 Not supported, DX=1 supported
  1221.       mov ax,1A00h           ;Request video info for VGA
  1222.       int 10h          ;Get Display Combination Code
  1223.       cmp al,1Ah             ;Is VGA or MCGA present?
  1224.       je Mode13hSupported ;mode 13h is supported
  1225.       xor dx,dx              ;mode 13h isnΓÇÖt supported dx=0
  1226. Mode13hSupported:
  1227.       mov dx,1               ;return mode13h supported
  1228.  
  1229. Just use this to check if mode 13h is supported at  the  beginning  of  your
  1230. program to make sure that you can go into that mode.
  1231.  
  1232. Note: I have not tested this on a computer that doesnΓÇÖt hav VGA as I donΓÇÖt
  1233. have any. In theory this should work but you should test this on computers
  1234. that donΓÇÖt have VGA and see if it works this out.
  1235.  
  1236. Setting the Video Mode:
  1237.  
  1238. It is very simple to set the mode. This is how it is done.
  1239.  
  1240.       mov  ax,13h            ;set mode 13h
  1241.       int  10h               ;call bios service
  1242.  
  1243. Once we are in mode 13h and have finished what we are doing we  need  to  we
  1244. need to set it to the video mode that it was in previously. This is done  in
  1245. two stages. Firstly we need to save the video mode  and  then  reset  it  to
  1246. that mode.
  1247.  
  1248. VideoMode db ?
  1249. ....
  1250.       mov ah,0Fh       ;function 0Fh - get current mode
  1251.       int 10h                ;Bios video service call
  1252.       mov VideoMode,al ;save current mode
  1253.  
  1254.       ;program code here
  1255.  
  1256.       mov al,VideoMode ;set previous video mode
  1257.       xor ah,ah              ;clear ah - set mode
  1258.       int 10h                ;call bios service
  1259.       mov ax,4C00h           ;exit to dos
  1260.       int 21h                ;call dos function
  1261.  
  1262. Now that we can get into mode 13h lets do something. Firstly lets  put  some
  1263. pixels on the screen.
  1264.  
  1265. Function 0Ch - Write Graphics Pixel
  1266.  
  1267. Makes a color dot on the screen at the specified graphics coordinates.
  1268.  
  1269. INPUT:
  1270.       AH = 0Ch
  1271.       AL = Color of the dot
  1272.       CX = Screen column (x coordinate)
  1273.       DX = Screen row (y coordinate)
  1274.  
  1275. OUTPUT:
  1276.       Nothing except pixel on screen.
  1277.  
  1278. Note: This function performes exclusive OR (XOR) with the  new  color  value
  1279. and the current context of the pixel of bit 7 of AL is set.
  1280.  
  1281.       mov ah,0Ch ;function 0Ch
  1282.       mov al,7         ;color 7
  1283.       mov cx,160 ;x position -160
  1284.       mov dx,100 ;y position -100
  1285.       int 10h          ;call bios service
  1286. This example puts a pixel into the middle of  the  screen  in  a  the  color
  1287. grey. The problem with this method is  that  calling  interrupts  is  really
  1288. slow and should be avoided in speed critical areas. With pixel  plotting  if
  1289. you wanted to display a picture the size of the screen  you  would  have  to
  1290. call this procedure 64,000 times (320 x 200).
  1291.  
  1292. Some optimizations:
  1293.  
  1294. This method isnΓÇÖt too fast and we could  make  it  a  lot  faster.  How?  By
  1295. writing direct to video memory. This is done quite easily.
  1296.  
  1297. The VGA memory starts at 0A000h. To work out where each pixel goes  you  use
  1298. this simple formula:
  1299.  
  1300.                  Location = 0A000h + Xposition + (Yposition x 320)
  1301.  
  1302. Location is the memory location which we want to put the pixel.
  1303.  
  1304. This procedure is quite a fast way to put a pixel onto  the  screen.  Thanks
  1305. go to Denthor of Asphyxia as I based this on his code.
  1306.  
  1307. PutPixel PROC
  1308. .286        ;enable 286 instructions for shifts remove if           ;you
  1309. have less than an 286.
  1310. ;========================================================
  1311. ;INPUT:     BX=X postion
  1312. ;           DX=Y position
  1313. ;           CL=colour
  1314. ;OUTPUT:  None
  1315. ;========================================================
  1316. ;this can be optimized by not pushing ax if you donΓÇÖt ;need to save it. For
  1317. A86 change push ds es ax to push ;ds,es,ax and do the same thing with pop.
  1318.       push ds es ax          ;save ds,es and ax
  1319.       mov ax,0A000h          ;ax contains address of video
  1320.       mov es,ax              ;es contains address of video
  1321.       mov di,bx              ;move x position into di
  1322.       mov bx,dx              ;mov y postion into bx
  1323.       shl dx,8               ;shift dx 8 places to the left
  1324.       shl bx,6               ;shift bx 6 places to the left
  1325.       add dx,bx              ;add dx and bx together
  1326.       add di,bx              ;add di and bx together
  1327.       mov al,cl              ;put colour in al
  1328.       stosb            ;transfer to video memory
  1329.       pop ax es ds           ;restore ds,es and ax
  1330.       ret
  1331. PutPixel ENDP
  1332.  
  1333. Thank you for reading. I hope that you have learnt something from this. If
  1334. you need any more help then email me.
  1335.  
  1336. Gavin Estey 19/2/95
  1337.  
  1338.