home *** CD-ROM | disk | FTP | other *** search
-
-
-
- 240
-
- The first thing to talk about is the 8086 mnemonics. The four
- instructions for unpacked BCD numbers are:
-
- AAA ASCII adjust for addition
- AAD ASCII adjust for division
- AAM ASCII adjust for multiplication
- AAS ASCII adjust for subtraction.
-
-
- Even though all four instructions have ASCII as part of their
- mnemonic, they have NOTHING to do with ASCII numbers. These
- instructions operate on unpacked BCD numbers. They always give
- results which are unpacked BCD numbers. Because of side effects
- of the 8086 microcode, the add and subtract instructions do
- something unusual, but this will be covered a little later.
-
- Just like the packed BCD instructions, these four unpacked
- instructions use the normal arithmetic operations and adjust the
- results to compensate for their being unpacked BCD numbers. Let's
- start with addition. The following program is like the BCD
- program except that we use AAA (ascii adjust for addition)
- instead of DAA (decimal adjust for addition).
-
- ; - - - - - - - - - - START CODE BELOW THIS LINE
- mov ax_byte, 0C4h ; half registers, hex, hex
- mov bx_byte, 94h ; half regs, signed, hex
- mov dx_byte, 91h ; half regs, signed, signed
- lea ax, ax_byte
- call set_reg_style
-
- mov cx, 0 ; clear cx for clarity
- outer_loop:
- mov ax, 0 ; clear the registers
- mov bx, 0
- mov dx, 0
- call set_count
- call show_regs
-
- call get_hex_byte ; byte for al
- mov dx, ax ; copy for dx
- push ax ; save al
- call get_hex_byte ; byte for bl
- mov bl, al
- mov bh, bl ; copy to bh
- pop ax ; restore al
- call show_regs_and_wait
- add al, bl ; normal add
- mov dx, ax ; copy to dx
- call show_regs_and_wait
- aaa ; make adjustment
- mov dx, ax ; copy to dx
- call show_regs_and_wait
- jmp outer_loop
- ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE
-
- ______________________
-
- The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
-
-
-
-
- Chapter 22 - BCD Numbers 241
- ________________________
-
-
- Since this is a mixture of unpacked BCD instructions and normal
- integer instructions, a copy of AX (which is showing hex) is
- moved to DX (which is showing signed) each time AX is changed.
- Also, a copy of BL is put in BH.
-
- For the rest of this chapter, I will refer to the one's digit,
- the ten's digit and the hundred's digit. In the number 346, 3 is
- the hundred's digit, 4 is the ten's digit, and 6 is the one's
- digit. In the number 928, 9 is the hundred's digit, 2 is the
- ten's digit, and 8 is the one's digit.
-
- If two valid unpacked BCD numbers are added, the result will be
- between 0 and 18. This result MUST be in AL. AAA sets CF if this
- result is greater than 9 ( i.e. there was a carry). AAA leaves
- the one's digit in AL and adds the ten's digit to AH. (The ten's
- digit can only be 0 for 0 - 9 or 1 for 10 - 18).
-
- Run this. The standard input should be hex numbers between 00h
- and 09h. When you feel comfortable with this, stop for a minute
- and read on.
-
- We now come to the peculiarity of this instruction. It isn't
- operating on the whole byte, only the lower half byte.
- Technically, if the LOWER HALF BYTE of each of the two numbers
- which are added is a legitimate BCD digit, then at the end of AAA
- the above results will be true and the UPPER HALF BYTE of AL will
- be set to 0. If you put anything in the upper half byte, it will
- be added by ADD, but will be blanked out (zeroed) by AAA.{1}
-
-
- As a side effect of blanking out (zeroing) the upper half byte,
- it is possible to use the ASCII numbers '0' (30h) to '9' (39h) as
- addends. The result (after AAA) will still be a number between
- 00h and 09h with the carry flag either set or cleared, and AH
- incremented if appropriate. Don't use it this way. The
- multiplication and division instructions REQUIRE that the numbers
- be between 00h and 09h, so all numbers should be changed into
- unpacked BCD on data entry. Here is a partial list of things you
- can add to get the result 07h:
-
- 03h + 04h 'c' + 'd' '+' + 't'
- '3' + '4' 's' + 't' 'c' + '4'
- 'C' + 'D' '#' + '$' 'S' + '$'
-
- As you can see, the addition instruction is pretty indiscriminate
- about what kind of data you can put in and still get a legitimate
- unpacked number out. It is your job to make sure that you have
- ____________________
-
- 1. They used the same microcode as for the beginning of DAA.
- If the low half byte of AL is greater than 9, or if there was a
- carry out of the low half byte (if AF, the auxillary flag was
- set), then the 8086 adds 6 to AL, which shifts the excess out of
- the low half byte. It then zeros the high half byte, sets the
- carry flag, and increments AH. If you don't understand this, go
- back and give the footnote on DAA a try.
-
-
-
-
- The PC Assembler Tutor 242
- ______________________
-
- legitimate unpacked data upon data entry.
-
- If this is just a side effect of blanking the upper half byte,
- why did they name the instruction "ascii adjust for addition"?
- It's just that impish sense of humor of those Intel engineers. If
- you think of these instructions as having anything to do with
- ASCII numbers, you will only confuse yourself. These are
- instructions on unpacked BCD numbers, period.
-
- The other thing to notice is that this instruction increments the
- AH register if there is a carry, so whenever you use AAA, it is
- going to trash the AH register. Count on it. If AH contains
- important data, store it somewhere else.
-
-
- SUBTRACTION
-
- When you have gotten used to how this works, look at subtraction.
- The subtraction routine is the same as the addition routine
- except that (1) ADD is replaced by SUB and (2) AAA is replaced by
- AAS (ascii adjust for subtraction). If you generate a borrow, the
- carry flag will be set and AH will be decremented by 1.
-
- If you have two legitimate unpacked BCD numbers, then after
- subtraction the result will be from +9 to -9. This result must be
- in AL. After AAS (ascii adjust for subtraction), (1) if AL was
- from 0 to +9, it will stay the same and CF will be cleared (CF=0)
- or (2) if AL was -1 to -9, AAF will borrow 1 from AH (considering
- it a ten's digit), and add 10 to AL. This will give a number from
- +1 to +9. It will also set the carry flag (CF=1) to signal a
- borrow. This is what you do with pencil and paper except that you
- always do the borrow BEFORE the subtraction and AAS always does
- the borrow AFTER the subtraction. Once again, this operates on
- the LOW HALF BYTE, so what is in the upper half byte of the
- numbers is irrelevant. It will be zeroed by AAS.
-
- There is all sorts of data which will generate a legitimate
- unpacked result; some of it is actually legitimate input. It too
- trashes the AH register, so beware. Run this program till you see
- what is going on with individual numbers.
-
-
- MULTIPLICATION
-
- There is also an instruction for multiplication. It assumes that
- AL contains the result of the multiplication of two unpacked BCD
- numbers. That is, 0 <= AL <= 81. After AAM (ascii adjust for
- multiplication), AH will contain the 10's digit and AL will
- contain the 1's digit. If AL is 75, then after AAM, AH will be 7
- and AL will be 5. If AL is 48, then after AAM, AH will be 4 and
- AL will be 8. (If AL is 183, an illegal result, then after AAM,
- AH will be 18 and AL will be 3).
-
- We are going to use a similar program for multiplication, but AX
- and BL will be half byte unsigned; BH and DX will be half byte
- hex. Every time we change AX, we will copy it to DX. Here is the
- program:
-
-
-
-
- Chapter 22 - BCD Numbers 243
- ________________________
-
-
- ; - - - - - - - - - - START CODE BELOW THIS LINE
- mov ax_byte, 0A2h ; half registers, unsigned
- mov bx_byte, 0C2h ; half regs, hex, unsigned
- mov dx_byte, 0C4h ; half regs, hex
- lea ax, ax_byte
- call set_reg_style
-
- mov cx, 0 ; clear cx for clarity
- outer_loop:
- mov ax, 0 ; clear the registers
- mov bx, 0
- mov dx, 0
- call set_count
- call show_regs
-
- call get_hex_byte ; byte for al
- mov dx, ax ; copy to dx
- push ax ; save al
- call get_hex_byte ; byte for bl
- mov bl, al
- mov bh, bl ; copy to bh
- pop ax ; restore al
- call show_regs_and_wait
- mul bl ; unsigned multiplication
- mov dx, ax ; copy to dx
- call show_regs_and_wait
- aam ; make adjustment
- mov dx, ax ; copy to dx
- call show_regs_and_wait
- jmp outer_loop
- ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE
-
- All you need to change from the addition program is the register
- style, ADD -> MUL and AAA -> AAM.
-
- Try this out. Notice that after MUL, what we get in DX is
- garbage. This number is a pure unsigned number, not a BCD number.
- Just to underline how important it is to have legitimate unpacked
- BCD data, try a few multiplications where the upper half byte is
- non-zero and see what happens.
-
-
- DIVISION
-
- AAD (ascii adjust for division) is slightly different. What we
- want to do is divide a number from 0 - 99 by a number from 1 to 9
- (0 gives a zero divide interrupt). Therefore, AAD multiplies what
- is in AH by 10 and adds it to what is in AL. It clears AH for the
- coming unsigned division.{2} If AH contains 7 and AL contains 2,
- then after AAD, AL will be 72 and AH will be 0. If AH is 4 and AL
- is 6, then after AAD, AL will be 46 and AH will be 0. (If AH is
- 14 and AL is 7 - an illegal situation - then after AAD, AL will
- ____________________
-
- 2. Remember that for unsigned byte division, we set AH to 0.
- This was back in the first chapter on division.
-
-
-
-
- The PC Assembler Tutor 244
- ______________________
-
- be 147 and AH will be 0)
-
- After you have done AAD, you are ready for regular unsigned
- division. After division, the quotient will be in AL and the
- remainder will be in AH. Here's the program:
-
- ; - - - - - - - - - - START CODE BELOW THIS LINE
- mov ax_byte, 0A2h ; half registers, unsigned
- mov bx_byte, 0C2h ; half regs, hex, unsigned
- mov dx_byte, 0C4h ; half regs, hex
- lea ax, ax_byte
- call set_reg_style
-
- mov cx, 0 ; clear cx for clarity
- outer_loop:
- mov ax, 0 ; clear the registers
- mov bx, 0
- mov dx, 0
- call set_count
- call show_regs
-
- call get_hex ; word
- mov dx, ax ; copy to dx
- push ax ; save al for later
- call get_hex_byte ; byte for bl
- mov bl, al
- mov bh, bl ; copy to bh
- pop ax ; get back al
- call show_regs_and_wait
- aad ; adjust for division
- mov dx, ax ; copy to dx
- call show_regs_and_wait
- div bl ; unsigned division
- mov dx, ax ; copy to dx
- call show_regs_and_wait
- jmp outer_loop
-
- ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE
-
- The differences from the multiplication routine are (1) we get a
- TWO byte hex number for the dividend and (2) AAD comes first,
- then DIV. That's all.
-
- We need to enter a TWO byte unpacked BCD number in order to get
- grist for the mill. 87 is 0807h, 93 is 0903h, 42 is 0402h. This
- will give us two unpacked digits so we have something to put in
- AH.
-
- Run this program and enter legitimate (and if you want,
- illegitimate) data. Notice that even with legitimate data, it is
- possible to get a quotient that is larger than 9. (47 / 3 is 15,
- remainder 2). Don't worry about this. We will avoid this problem
- in the real program.
-
-
- PACKING AND UNPACKING
-
-
-
-
-
- Chapter 22 - BCD Numbers 245
- ________________________
-
- Making an i/o routine is such a bother that we will enter data
- with 'get_bcd' and output data with 'print_bcd'. To do this, we
- need to pack and unpack the data. The calls in C would be:
-
- unpack_bcd (&packed_number, &unpacked_number) ;
- pack_bcd (&unpacked_number, &packed_number) ;{3}
-
- The thing to be operated on is the first variable and the result
- is the second variable. First, here's the unpacking routine:
-
- ; - - - - - - - - - -
- unpack_bcd proc near
-
- UNPACK_UNPACKED_ADDRESS EQU [bp + 6]
- UNPACK_BCD_ADDRESS EQU [bp + 4]
-
-
- push bp
- mov bp, sp
- PUSHREGS ax, bx, cx, si, di
-
- mov si, UNPACK_BCD_ADDRESS
- mov di, UNPACK_UNPACKED_ADDRESS
-
- ; start at top to unpack
- add si, 9 ; bcd sign
- add di, 18 ; unpacked sign
- mov al, [si] ; move sign to unpacked
- mov [di], al
- dec si ; move down to next byte
- dec di
-
- mov cx, 9 ; 9 bcd data bytes
- ; unpack high byte first, then low byte
- unpack_loop:
- push cx ; save counter
- mov al, [si] ; bcd byte to al
- mov bl, al ; copy to bl
- mov cl, 4
- ror al, cl ; high half byte to low half
- and al, 0Fh ; blank upper half byte
- mov [di], al ; al is high half of bcd byte
- dec di ; result pointer
- and bl, 0Fh ; blank upper half byte
- mov [di], bl ; bl is low half bcd byte
- dec di ; result pointer
- dec si ; source pointer
- pop cx ; restore counter
- loop unpack_loop
-
- POPREGS ax, bx, cx, si, di
- pop bp
- ret
- ____________________
-
- 3. That '&' means that we are passing the addresses, not the
- values.
-
-
-
-
- The PC Assembler Tutor 246
- ______________________
-
-
- unpack_bcd endp
- ; - - - - - - - - - - - - - - - -
-
- This is pretty straightforward. First it moves the sign. Then,
- taking a BCD byte, the routine divides it in two parts, rotating
- the high half byte to the proper position, storing it,
- DECREMENTING the pointer and storing the low half byte. The upper
- half byte of each unpacked byte is zeroed. Notice that by
- starting at the top, it is possible to unpack a number in place.
- Diagram what is happening to make sure you believe that.
-
- Here's the packing routine:
-
- ; - - - - - - - - - - - - - - - -
- pack_bcd proc near
-
- PACK_BCD_ADDRESS EQU [bp + 6]
- PACK_UNPACKED_ADDRESS EQU [bp + 4]
-
- push bp
- mov bp, sp
- PUSHREGS ax, bx, cx, si, di
-
- mov si, PACK_UNPACKED_ADDRESS
- mov di, PACK_BCD_ADDRESS
-
- ; start at bottom to pack
- mov cx, 9 ; 9 bytes of bcd data
- pack_loop:
- push cx ; save counter
- mov al, [si + 1] ; high unpacked byte
- mov cl, 4
- ror al, cl ; move to high half byte
- or al, [si] ; OR low half with high half
- mov [di], al ; move to BCD
- inc di ; adjust pointers
- add si, 2
- pop cx ; restore counter
- loop pack_loop
-
- ; si and di are now in the right place for the sign
- mov al, [si]
- mov [di], al
-
- POPREGS ax, bx, cx, si, di
- pop bp
- ret
-
- pack_bcd endp
- ; - - - - - - - -
-
- This does the reverse process, rotating the high byte to the
- proper place, then ORing the two together to form a packed BCD
- byte. Notice that by starting at the BOTTOM it is possible to
- pack a number in place. Diagram the action to make sure you
- believe this.
-
-
-
-
- Chapter 22 - BCD Numbers 247
- ________________________
-
-
- These two routines allow us to use 19 byte unpacked BCD numbers.
- Here's the multiplication routine for a 19 byte (18 data bytes
- and 1 sign byte) unpacked number by a 1 byte unpacked number:
-
- ; - - - - -
- unpacked_multiply proc near
-
- PUSHREGS ax, bx, cx, dx, si, di
- mov si, offset multiplicand
- mov di, offset result
- mov dh, 0 ; clear dh for carry
- mov bl, multiplier_copy
- mov cx, 18 ; 18 data bytes
-
- mult_loop:
- mov al, [si] ; multiplicand to al
- mul bl ; multiply
- add al, dh ; add old carry
- aam ; adjust al
- mov [di], al ; partial result
- mov dh, ah ; save carry
- inc si ; adjust pointers
- inc di
- loop mult_loop
-
- mov extra_byte, ah ; extra byte
- POPREGS ax, bx, cx, dx, si, di
- ret
-
- unpacked_multiply endp
- ; - - - - -
-
- This is a clone of what we had in the chapter on multiple word
- multiplication but is byte multiplication instead of word
- multiplication. Refer back to that chapter to understand the
- mechanics of the process. We store the partial result and save
- the high byte for addition with the next multiplication. At the
- end we save the 19th byte for printout.
-
- We are cheating a little. we have:
-
- mul bl ; multiply
- add al, dh ; add old carry
- aam ; adjust al
-
- when we should have:
-
- mul bl ; multiply
- aam ; adjust al
- add al, dh ; add old carry
- aaa ; adjust al
-
- The reason this works is that the maximum multiplication is
- 9X9=81. The maximum addition is 81+9 = 90. AAM will work
- correctly with any number 99 or less, so we save a step; we do
- one adjustment instead of two.
-
-
-
-
- The PC Assembler Tutor 248
- ______________________
-
-
- Now, let's look at the driver for the program:
-
- ; + + + + + START DATA BELOW THIS LINE
- multiplier_message db "Enter a number from -9 to +9", 0
- bcd_in dt ?
- bcd_out dt ?
- multiplicand db 19 dup (?)
- multiplier db ?
- multiplier_copy db ?
- result db 19 dup (?)
- extra_byte db ?
- result_sign db ?
- ; + + + + + END DATA ABOVE THIS LINE
-
-
- ; + + + + + START CODE BELOW THIS LINE
- outer_loop:
- mov ax, offset bcd_in
- call get_bcd
- call print_bcd ; reprint for clarity
- lea cx, multiplicand
- push cx ; unpacked address
- push ax ; bcd_in address
- call unpack_bcd
- add sp, 4 ; adjust the stack
- mov al, multiplicand + 18 ; sign byte
- mov result_sign, al ; either 00h or 80h
-
- enter_multiplier:
- lea ax, multiplier_message
- call print_string
- call get_signed_byte
- ; check for valid multiplier
- cmp al, 9 ; > +9 ?
- jg enter_multiplier
- cmp al, -9 ; < -9?
- jl enter_multiplier
-
- ; adjust multiplier sign
- mov multiplier, al
- mov multiplier_copy, al
- and al, 80h ; sign bit set?
- jz do_the_multiplication
- ; negative multiplier, so adjust
- neg multiplier_copy ; make positive
- xor result_sign, 80h ; reverse sign of result
-
- do_the_multiplication:
- call unpacked_multiply
-
- mov al, result_sign ; transfer sign to result
- mov result + 18, al
-
- ; pack the result
- mov ax, offset bcd_out ; bcd number
- push ax
-
-
-
-
- Chapter 22 - BCD Numbers 249
- ________________________
-
- mov ax, offset result ; unpacked number
- push ax
- call pack_bcd
- add sp, 4 ; adjust the stack
-
- ; print multiplicand, multiplier, extra byte and result
- mov ax, offset bcd_in
- call print_bcd
- mov al, multiplier
- call print_signed_byte
- mov al, extra_byte
- call print_hex_byte
- mov ax, offset bcd_out
- call print_bcd
-
- jmp outer_loop
- ; - - - - - END CODE ABOVE THIS LINE
-
- We enter a multiplicand, unpack it, enter a number from -9 to +9
- and save a copy of its absolute value as well as the sign the
- result will be. We adjust the sign of the result after the
- multiplication. No matter what you enter, the sign will be
- correct, and if you put the 19th byte in front of the BCD number
- which you have printed, the absolute value will be correct. We
- are multiplying with a COPY of the multiplier, so we can reprint
- the actual multiplier; it hasn't changed. At the end we pack the
- result and print everything. The order of printout is
- multiplicand, multiplier, extra byte and result.
-
- Notice that we are not passing the parameters for
- unpacked_multiply on the stack. This is pure whim. A rule for
- when to pass on the stack is (1) If the subroutine doesn't know
- where the parameters will be located in memory, you MUST pass
- them on the stack but (2) if the subroutine knows for certain
- where the parameters will be, it can fetch them itself.
-
- DIVISION
-
- Here is the division routine for 19 byte unpacked numbers:
-
- ; - - - - - - - -
- unpacked_divide proc near
-
- PUSHREGS ax, bx, cx, si, di
-
- mov bl, divisor_copy
- mov si, offset dividend + 17 ; start at the top
- mov di, offset quotient + 17
- mov cx, 18 ; 18 numeric bytes
- mov ah, 0 ; clear ah for division
-
- div_loop:
- mov al, [si] ; dividend byte to al
- aad ; adjust for unpacked number
- div bl ; bl is divisor
- mov [di], al ; move partial quotient
- dec si ; decrement pointers
-
-
-
-
- The PC Assembler Tutor 250
- ______________________
-
- dec di
- loop div_loop
-
- mov remainder, ah ; final remainder
-
- POPREGS ax, bx, cx, si, di
- ret
-
- unpacked_divide endp
- ; - - - - -
-
- It is pretty simple; it too is a clone of the multiple word
- division process. Go back to multiple word division if you don't
- understand it. We keep the previous remainder for the next
- division. Here is the driver:
-
- ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE
- divisor_message db "Enter a number from -9 to +9 (but not 0).",0
- bcd_in dt ?
- bcd_out dt ?
- quotient_sign db ?
- remainder_sign db ?
- divisor db ?
- divisor_copy db ?
- dividend db 19 dup (?)
- quotient db 19 dup (?)
- remainder db ?
- ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE
-
- ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE
- outer_loop:
- mov ax, offset bcd_in
- call get_bcd
- call print_bcd ; reprint for clarity
- lea cx, dividend
- push cx ; unpacked address
- push ax ; bcd_in address
- call unpack_bcd
- add sp, 4 ; adjust the stack
- mov al, dividend + 18 ; sign byte
- mov quotient_sign, al ; either 00h or 80h
- mov remainder_sign, al ; ditto
-
- enter_divisor:
- lea ax, divisor_message
- call print_string
- call get_signed_byte
- ; check for valid divisor
- cmp al, 0 ; 0?
- je enter_divisor
- cmp al, 9 ; > +9 ?
- jg enter_divisor
- cmp al, -9 ; < -9?
- jl enter_divisor
-
- ; adjust divisor, quotient sign
- mov divisor, al
-
-
-
-
- Chapter 22 - BCD Numbers 251
- ________________________
-
- mov divisor_copy, al
- and al, 80h ; sign bit set?
- jz do_the_division
- ; negative divisor, so adjust
- neg divisor_copy ; make positive
- xor quotient_sign, 80h ; reverse sign of quotient
-
- do_the_division:
- call unpacked_divide
-
- mov al, quotient_sign ; transfer sign to quotient
- mov quotient + 18, al
- test remainder_sign, 0FFh ; positive or negative?
- jz pack_the_quotient
- neg remainder ; make the remainder negative
-
- pack_the_quotient:
- mov ax, offset bcd_out ; bcd number
- push ax
- mov ax, offset quotient ; unpacked number
- push ax
- call pack_bcd
- add sp, 4 ; adjust the stack
-
- ; print dividend, divisor, quotient and remainder
- mov ax, offset bcd_in
- call print_bcd
- mov al, divisor
- call print_signed_byte
- mov ax, offset bcd_out
- call print_bcd
- mov al, remainder
- call print_signed_byte
-
- jmp outer_loop
- ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE
-
- Enter a BCD number, unpack it. Enter a signed number, do range
- checking, and if it is ok, store it (along with a copy, which we
- make sure is positive). Calculate the sign of the quotient and
- remainder. Do the division, then print the dividend, divisor,
- quotient and remainder. (which have been sign adjusted). The
- remainder is a signed byte.
-
- Like unpacked_multiply, unpacked_divide fetches the parameters
- directly from memory rather than from the stack.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The PC Assembler Tutor 252
- ______________________
-
- SUMMARY
-
-
-
- PACKED BCD INSTRUCTIONS
-
- DAA (decimal adjust for addition) adjusts AL, assuming that it
- contains the result of a legitimate packed BCD addition. It
- treats AL as two independent half-bytes. If the result of the
- lower half-byte is 10 or over, it subtracts 10 from the lower
- half-byte and adds the carry to the upper half byte. It then
- looks at the upper half byte. If its result is 10 or over, DAA
- subtracts 10 from the upper half byte and sets the carry flag.
- Otherwise the carry flag is cleared.
-
- DAS (decimal adjust for subtraction) adjusts AL, assuming that it
- contains the result of a legitimate packed BCD subtraction.It
- treats AL as two independent half-bytes. If the result of the
- lower half-byte is -1 or less, it adds 10 to the lower half-byte
- and borrows 1 from the upper half byte. It then looks at the
- upper half byte. If its result is -1 or less, DAS adds 10 to the
- upper half byte and sets the carry flag to indicate a borrow.
- Otherwise the carry flag is cleared.
-
-
- UNPACKED BCD INSTRUCTIONS
-
- AAA (ascii adjust for addition) adjusts AL, assuming that it
- contains the result of a legitimate unpacked BCD addition. If the
- lower half-byte has generated a result 10 or over, it subtracts
- 10, carries 1 to AH, and sets the carry flag. If the result is 9
- or less, it clears CF. In either case it zeroes the upper
- half-byte of AL.
-
- AAD (ascii adjust for division) PREPARES AL and AH for division.
- It assumes that AH contains the 10's digit and AL contains the
- 1's digit of a two byte unpacked BCD number. It multiplies AH by
- 10 and adds it to AL, thus making a single integer between 0 and
- 99. It zeroes AH in preparation for division.
-
- AAM (ascii adjust for multiplication) adjusts AL, assuming that
- it contains the result of a legitimate BCD multiplication. It
- divides the result by 10, putting the quotient in AH and the
- remainder in AL.
-
- AAS (ascii adjust for subtraction) adjusts AL, assuming that it
- contains the result of a legitimate unpacked BCD subtraction. If
- the lower half-byte has generated a result -1 or less, it borrows
- 1 from AH, adds 10 to AL, and sets the carry flag. If the result
- is 0 or more, it clears CF. In either case it zeroes the upper
- half-byte of AL
-
-