home *** CD-ROM | disk | FTP | other *** search
/ The Party 1994: Try This At Home / disk_image.bin / source / asmtuttx / asmtut.txt
Text File  |  1995-02-19  |  48KB  |  1,439 lines

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