home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
-
-
- *****************************************************************
- REGISTRATION
-
- Hey, Chuck, I'm no chump!
-
- I'm using your programs/manual, and I want to pay my fair share.
- Please make me a registered user of "The PC Assembler Tutor" and
- "The PC Assembler Helper". Enclosed is a check for $9.95 (plus
- 6.5% tax or $10.60 for California residents). Say, that's cheaper
- than a large pizza!
-
-
- Name_________________________________________________________
- Last First Initial
-
- Address______________________________________________________
- Street Address
-
- _______________________________________________________
- City, State, and Zip Code
-
- I got my copy from ___________________________________________
-
- Make checks payable to NELSOFT and send your registration to:
-
- NELSOFT
- P.O. Box 21389
- Oakland, CA 94620
-
- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- REGISTRATION BENEFITS
-
- As a registered user of "The PC Assembler Helper" and "The PC
- Assembler Tutor" you are entitled to:
-
- 1) Use asmhelp.obj and helpmem.com for personal use.
- 2) Make 1 (one) printer copy of "The PC Assembler Tutor".
- 3) Use all programs in "The PC Assembler Tutor" for personal use.
- 4) Make an archival copy of the disks.
- 5) Distribute UNALTERED disks to friends for their perusal.
- 6) Use any updates to either "The PC Assembler Helper" or "The PC
- Assembler Tutor" under the same registration conditions.
-
- Though copies of the disk may be given away if there is no
- charge, it is illegal to charge for redistribution of the disk or
- its contents without permission of the author. Under no
- circumstances may you distribute printed copies of "The PC
- Assembler Tutor". If you intend to charge for distributing the
- disk or its information, please read and sign the distribution
- agreement which is in INTRO1.DOC.
-
- *****************************************************************
-
-
-
- 31
-
- CHAPTER 5 - ADDITION AND SUBTRACTION
-
-
- The first arithmetic operations we will look at are addition and
- subtraction, but before we do that, we need to look at one
- instruction that controls program flow.
-
- LOOP
-
- We already have JMP which sends you to a label:
-
- jmp label3
-
- sends the program to label3, wherever that is in the code.
- Sometimes we want to repeat a section of code a specific number
- of times and then go on. For this, we have LOOP. LOOP decrements
- the CX register by 1. If CX is not zero after being decremented,
- LOOP jumps to the label indicated. If CX is zero after being
- decremented, LOOP falls through.
-
- The 8086 does not have general purpose registers. A general
- purpose register is a register that can be used for ALL
- instructions. There are a number of instructions on the 8086
- which must be done with specific registers, and LOOP is the first
- one we meet. LOOP always looks at the CX register.
-
-
- This first program lets you enter a number and then loops that
- many times so you can watch the CX register. As usual, you exit
- the program by hitting Control-C. We use temp2.asm.
-
- temp2.asm
- ; - - - - START CODE BELOW THIS LINE
- call show_regs ; initialize
-
- outer_loop:
- call get_unsigned
- mov cx, ax ; number to cx
-
- inner_loop:
- call show_regs_and_wait
- loop inner_loop
-
- jmp outer_loop
-
- ; - - - - END CODE ABOVE THIS LINE
-
- A very simple program. As always, link it with asmhelp.obj.
- Get_unsigned gets a two byte number (less than 65536) and puts it
- in AX. We put that number in CX, and then watch the program loop.
- Make sure you use show_regs_and_wait, or everything will happen
- too fast for you to see. Try entering 0. On the first pass, loop
- will decrement CX from 0 to 65535. If CX is 0 when you enter, you
-
- ______________________
-
- The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
-
-
-
-
- The PC Assembler Tutor 32
- ______________________
-
- have to repeat the loop 65536 times before you exit the loop. Hit
- Control-C now to exit.
-
- Throughout the book, I will use label names that end in '_loop'
- to indicate that they are the destination of a jump or loop
- instruction. The single word "loop" is a reserved word and may
- not be used as a label - it can only be used as an instruction.
-
- The addition program will have 4 sections and LOOP will give us
- the ability to do each section a limited number of times before
- going on to the next section.
-
-
- ADDITION
-
- If you read the introductory section on numbers carefully, you
- know that it is the same instruction for both signed and unsigned
- addition. The 8086 sets the flags correctly for both signed and
- unsigned addition. For signed addition, the following flags are
- set:
-
- OF the overflow flag is set (1) if the result is too
- negative or too positive, that is, if the result in the
- register does not show the correct result of the addition.
- It is cleared (0) otherwise.
-
- ZF the zero flag is 1 if the result is zero, and is
- cleared (0) if the result is non-zero.
-
- SF the sign flag is set (1) if the result is NEGATIVE and
- is cleared (0) if the result is POSITIVE. Zero is considered
- a positive number.
-
- For unsigned addition, the following flags are set:
-
- CF the carry flag is set (1) if the result is too large
- (over 255 for byte and over 65535 for word operations). It
- is cleared (0) otherwise.
-
- ZF the zero flag is the same as above.
-
- In addition, there are two more flags (PF the parity flag and AF
- the auxillary flag) which will be set or cleared; we will learn
- about them later.
-
- Show_regs shows all the flags. The setting for each flag is
- underneath its name. For the flags OF, ZF and CF, there is an 'X'
- if the flag is set and a blank if the flag is cleared. SF, the
- sign flag, is '-' if the flag is set and '+' if the flag is
- cleared.
-
- The addition program is fairly long because there are four things
- to look at - unsigned word addition, unsigned byte addition,
- signed word addition and signed byte addition. For that reason,
- it has already been typed in for you. It is called ADD1.ASM and
- its pathname is \XTRAFILE\ADD1.ASM. Print out a copy of it.
-
-
-
-
-
- Chapter 5 - Addition and Subtraction 33
- ____________________________________
-
- There are four blocks of code which are almost identical except
- the calls are a little different and two blocks refer to whole
- registers while the other two refer to half registers. At the
- head of each block is code to set the appropriate register styles
- for show_regs. SI, DI, and BP are not used and are set to 0 to
- make the screen easier to read. Here is the first block of code,
- which is typical.
-
- ; - - - CODE
- ; UNSIGNED WORD ADDITION
- mov ax_byte, 2 ; ax, bx, dx unsigned
- mov bx_byte, 2
- mov dx_byte, 2
- lea ax, ax_byte ; call set_reg_style
- call set_reg_style
-
- mov cx, 3 ; 3 iterations
- unsigned_loop:
- mov ax, 0 ; clear the registers for visibility
- mov bx, 0
- mov dx, 0
- call show_regs
- call get_unsigned ; first number to ax
- call show_regs
- push ax ; temporarily save ax
- call get_unsigned ; second number to bx
- mov bx, ax
- pop ax ; get ax back
- mov dx, ax ; copy of ax to dx
- add dx, bx ; dx (=ax) + bx
- call show_regs_and_wait
- loop unsigned_loop
-
- ; - - - CODE
-
- First, we set AX, BX, and DX for the appropriate register style.
- Here it is unsigned full register. We then put 3 in CX so we can
- have 3 iterations with loop. Upon entering the loop, AX, BX, and
- DX are cleared for reasons of visibility. We don't want the
- screen cluttered up with numbers. Get_unsigned gets a two byte
- unsigned number and returns it in AX. We want the first number to
- be visually on the top (which is AX), but there is a problem
- here. In order to get the second number we need to call
- get_unsigned again, and it is going to put another number in AX.
- We need to temporarily store the first number while we bring in
- the second number and transfer it to bx.
-
- There is a special 8086 instruction to do this, it is called
- PUSH. Push temporarily stores a word. The word can be either a
- full register or a word (two bytes) in memory. You can have
- either:
-
- variable1 dw 10000
-
- push ax
- push variable1
-
-
-
-
-
- The PC Assembler Tutor 34
- ______________________
-
- These are stored in a special place called the stack which we
- will talk about much later. When you want it back, you use the
- instruction POP. POP gets back the LAST thing that you pushed
- onto the stack. Things come off the stack in REVERSE order of how
- they were put on.
-
- push variable1
- push variable2
- push variable3
- push variable4
- pop variable4
- pop variable3
- pop variable2
- pop variable1
-
- is the correct order. This is used for temporary storage only,
- and the only thing which is accessable is the last thing which
- you PUSHed on the stack.
-
- We push AX to store it temporarily, call get_unsigned again and
- transfer the number to BX. We then pop AX to get the number back.
- The situation now is: the first number is in AX, the second
- number is in BX. For the actual addition, we transfer AX to DX
- and then add DX and BX. AX and BX contain the two numbers, and DX
- contains the result. Then you must press ENTER to continue. LOOP
- will jump to 'unsigned_loop' two times. The third time it will
- fall through to the next section of code.
-
- This program illustrates a hallmark of assembler code. It
- normally takes scads of code just to do something simple.
-
- Assemble add1.asm and link it with asmhelp.obj. Run it:
-
- ******************** SCREEN SHOT ******************************
-
- AX 17428 SI 00000
- BX 19755 DI 00000
- CX 00003 BP 00000
- DX 37183 SP 00508
-
- CS 0AA5H DS 0A55H ES 0A25H SS 0A35H IP 004DH
-
- OF DF IEF TF SF ZF AF PF CF
- x + x - E COUNT 00004
- ----------------------------------------------------------------
-
- The PC Assembler Helper Version 1.0
- Copyright (C) 1989 Chuck Nelson All rights reserved.
- Enter a number from 0 to 65535 17428
- Enter a number from 0 to 65535 19755
- Press ENTER to continue
-
- *****************************************************************
-
- This is the screen after the first addition. I have added 17428
- (AX) and 19755 (BX). The result 37183 is in DX. CX is still 3
- because it hasn't LOOPed yet.
-
-
-
-
- Chapter 5 - Addition and Subtraction 35
- ____________________________________
-
-
- Notice that even though it is the same assembler instruction:
-
- add
-
- in all four blocks of code, it is doing both signed and unsigned
- addition correctly. When you are doing signed addition, you want
- to look at OF, the overflow flag, SF, the sign flag, and ZF, the
- zero flag after each addition to see how they are set. When you
- do unsigned addition, you want to look at CF, the carry flag, and
- ZF, the zero flag to see how they are set. Play around with this
- for a while, and then it is time for the next program.
-
- As in all 8086 instructions, the order is:
-
- add destination, source
-
- We add both numbers, and put the result in the destination, the
- thing on the left.
-
-
- There are five different types of addition you can do, (just as
- there are five different types of moves). They are:
-
- 1. add two registers
- 2. add a register to a variable (memory)
- 3. add a variable (memory) to a register
- 4. add a constant to a variable (memory)
- 5. add a constant to a register
-
- Here's a program that does all 5 things. Use template.asm to make
- this program. template.asm is almost the same as the other ones
- we have used. It has a few changes. First, it now lists ALL the
- subroutines you can call in asmhelp.obj.{1} Appendix 1
- (\APPENDIX\APP1.DOC) contains a description of all the
- subroutines, what they do, and how they are called. Second, the
- size of STACKSEG is larger. We don't need this large of a stack
- now; it is for later. Finally, there is a section:
-
- ; + + + + + + + + + + PUT SUBROUTINES BELOW THIS LINE
-
- ; + + + + + + + + + + PUT SUBROUTINES ABOVE THIS LINE
-
- for subroutines. Ignore this. This is for later.
-
-
- From now on, we will always use template.asm unless it is
- explicitly stated that something else is being used. Here's the
- program:
-
- template.asm
- ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE
- ____________________
-
- 1 This does not change the size of the .EXE file by even
- one byte, but it adds a lot of information to the .OBJ file, so
- they are much larger.
-
-
-
-
- The PC Assembler Tutor 36
- ______________________
-
- variable1 dw ?
- variable2 dw ?
- ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE
-
- ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE
- call show_regs
- outer_loop:
- call get_unsigned ; first number to ax
- push ax ; store ax
- call get_unsigned ; second number to bx
- mov bx, ax
- pop ax ; restore ax
- mov variable1, ax ; first number to variable1
- mov variable2, bx ; second number to variable2
- ; add 2 registers
- mov cx, ax ; cx + bx
- add cx, bx
- ; add register to memory
- add variable1, bx
- mov dx, variable1 ; put in dx for display
- ; add memory to register
- mov si, ax
- add si, variable2
- ; add a constant to memory
- add variable2, 25
- mov di, variable2 ; put in di for display
- ; add a constant to a register
- mov bp, bx
- add bp, 25
- call show_regs
- jmp outer_loop
-
- ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE
-
-
- The program puts the first number in AX and the second number in
- BX. It then proceeds to do the same addition (first number plus
- second number) three times. These are:
-
- 1. CX = add two registers (CX + BX)
- 2. DX = add a register to memory (variable1 + BX)
- 3. SI = add memory to a register (SI + variable2)
-
- Finally it adds a constant (second number + 25). These are:
-
- 4. DI = add a constant to memory (variable2 + 25)
- 5. BP = add a constant to a register (BP + 25)
-
-
- On the 8086, it is not possible to add two things in memory. That
- is:
-
- add variable1, variable2
-
- is an illegal instruction. Instead, you need to write:
-
- mov ax, variable2
-
-
-
-
- Chapter 5 - Addition and Subtraction 37
- ____________________________________
-
- add variable1, ax
-
-
- SUBTRACTION
-
- It is now time to do some subtraction. The instruction is SUB:
-
- sub destination, source
-
- subtracts source from destination and stores it in destination,
- the thing on the left.
-
- sub ax, cx ; (ax - cx) -> ax
-
- In order to do subtraction we are going to modify add1.asm, so
- make a copy and call it sub1.asm:
-
- >copy add1.asm sub1.asm
-
- How many instructions do we need to change to modify the program?
- Four.
-
- add dx, bx -> sub dx, bx
- add dl, bl -> sub dl, bl
-
- Each of these is changed twice, and we are ready to roll.
- Assemble it, link it, and run it. Once again we want to look at
- the flags at the end of each subtraction. For unsigned
- subtraction, look at ZF, the zero flag, and CF, the carry flag.
- This time, CF will be set if the result is below zero. For signed
- subtraction, look at OF, the overflow flag, SF, the sign flag,
- and ZF, the zero flag. As with addition, subtraction changes PF,
- the parity flag and AF the auxillary flag. They don't concern us.
-
- As with addition, there are five possibilities for subtraction.
- They are:
-
- 1. subtract one register from another
- 2. subtract a register from a variable (memory)
- 3. subtract a variable (memory) from a register
- 4. subtract a constant from a variable (memory)
- 5. subtract a constant from a register
-
- the code for these is:
-
- sub cx, bx ; (cx - bx) -> cx
- sub variable1, bx ; (variable1 - bx) -> variable1
- sub si, variable2 ; (si - variable2) -> si
- sub variable2, 25 ; (variable2 - 25) -> variable2
- sub bp, 25 ; (bp - 25) -> bp
-
- You can copy add2.asm to sub2.asm if you want and change the five
- ADD instructions to SUB instructions. It will then do those five
- types of subtraction.
-
-
-
-
-
- The PC Assembler Tutor 38
- ______________________
-
- SIGNED AND UNSIGNED NUMBERS
-
- What should you do if you are doing unsigned addition or
- subtraction and the carry flag gets set? It depends. Sometimes it
- makes a difference, sometimes it doesn't. If you have an error
- handling routine, then you can call it with the following code:
-
- add ax, bx
- jnc go_on
- call error_handler
- go_on:
-
- JC and JNC are conditional jump instructions. JC (jump on carry)
- jumps if the carry flag is set (1) and JNC (jump on not carry)
- jumps if the carry flag is not set (0). Using reverse logic here,
- we skip the error handler if everything is ok.
-
- For signed numbers, it is certainly an error if there is
- overflow. You are making mathematical calculations and you now
- have invalid data. One possibility is to do the same as above but
- with the overflow flag.
-
- add ax, bx
- jno go_on
- call error_handler
- go_on:
-
- JO and JNO are two more conditional jump instructions. JO (jump
- on overflow) jumps if the overflow flag is set (1) and JNO (jump
- on not overflow) jumps if the overflow flag is not set (0). We
- use the same logic here.
-
- However, there is one special instruction for signed numbers, and
- that is INTO (interrupt on overflow). It is possible to have an
- error handler external to your program. It sits permanantly in
- memory. When you make a signed arithmetic error, INTO interrupts
- your program and goes to the external error handler. The code
- looks like this:
-
- add ax, bx
- into
-
- You probably don't have an error handler in your computer right
- now. In that case, INTO simply goes looking for it and returns
- when it can't find it.
-
- Let's find out if you have an error handler installed. Once
- again, use template.asm
-
- ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE
- mov ax_byte, 1 ; signed register style
- mov bx_byte, 1
- mov cx_byte, 1
- lea ax, ax_byte
- call set_reg_style
- call show_regs
-
-
-
- Chapter 5 - Addition and Subtraction 39
- ____________________________________
-
- outer_loop:
- call get_signed
- push ax
- call get_signed
- mov bx, ax
- pop ax
- mov cx, ax
- add cx, bx
- into
- call show_regs
- jmp outer_loop
- ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE
-
- This is basically the same thing as before, but using AX, BX, and
- CX. They are set for signed style, and then we get two signed
- numbers and add them. The result is in CX. Right after the
- addition instruction is INTO. If the result is too positive or
- too negative, OF will be set and INTO will look for the error
- handler.
-
- Assemble this program and link it with asmhelp.obj. Try both
- numbers that do not set the overflow flag and numbers that do set
- the overflow flag. Did anything different happen when the
- overflow flag was set? If nothing different happened, you don't
- have an error handler for INTO.
-
- Included on the disks is an error handler. It is called INTO.COM,
- and it's pathname is \XTRAFILE\INTO.COM. When you run it:
-
- >into
-
- it will install itself and then return to the command prompt:
-
- >
-
- INTO.COM will stay in memory until you reboot or shut off the
- machine. INTO.COM provides the type of sophisticated error
- handling that you might want to use in a real program. Install
- (run) INTO.COM, and then try the previous program again, both
- with numbers that cause an overflow and numbers that don't cause
- an overflow.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The PC Assembler Tutor 40
- ______________________
-
- SUMMARY
-
-
- ADD performs both signed and unsigned addition. It can:
-
- 1. add two registers
- 2. add a register to a variable (memory)
- 3. add a variable (memory) to a register
- 4. add a constant to a variable (memory)
- 5. add a constant to a register
-
-
- SUB performs both signed and unsigned subtraction. It can:
-
- 1. subtract one register from another
- 2. subtract a register from a variable (memory)
- 3. subtract a variable (memory) from a register
- 4. subtract a constant from a variable (memory)
- 5. subtract a constant from a register
-
-
- The flags affected by both ADD and SUB are:
-
- CF the carry flag (for unsigned). Set if the 0/65535
- (0/255) border was crossed.
-
- ZF the zero flag (for signed and unsigned). Set if the
- result is 0.
-
- SF the sign flag (for signed). Set if the result is
- negative.
-
- OF the overflow flag (for signed). Set if the result was
- too negative or too positive.
-
- PF the parity flag and AF, the auxillary flag
-
- The following jump instructions are conditional on the setting of
- the flags:
-
- JC jump on carry, JNC, jump on not carry
- JO jump on overflow. JNO, jump on not overflow
-
- LOOP
- LOOP decrements cx by 1. If cx is then not zero, it jumps to
- the named label. If cx is zero, it falls through to the next
- instruction.
-
- INTO
- If the overflow flag is set, INTO (interrupt on overflow)
- interrupts the program and goes to an external error handler
- if one exists. It returns immediately if one doesn't exist.
-
- PUSH and POP
- PUSH stores either a register or a word (in memory) in a
- temporary storage area. POP retrieves the last word PUSHed.
-
-