3

On an 8085 processor, an efficient algorithm for dividing a BCD by 2 comes in handy when converting a BCD to binary representation. You might think of recursive subtraction or multiplying by 0.5, however these algorithms require lengthy arithmetics.

Therefore, I would like to share with you the following code (in 8085 assembler) that does it more efficiently. The code has been thoroughly tested on GNUSim8085 and ASM80 emulators. If this code was helpful to you, please share your experience with me.

Before running the code, put the BCD in register A. Set the carry flag if there is a remainder to be received from a more significant byte (worth 50). After execution, register A will contain the result. The carry flag is used to pass the remainder, if any, to the next less significant byte.

The algorithm uses DAA instruction after manipulating C and AC flags in a very special way thus taking into account that any remainder passed down to the next nibble (i.e. half-octet) is worth 5 instead of 8.

;Division of BCD by 2 on an 8085 processor

;Set initial values.
;Register A contains a two-digit BCD. Carry flag contains remainder.
stc
cmc
mvi a, 85H

;Do modified decimal adjust before division.
cmc
cma
rar
adc a
cma
daa
cmc

;Divide by 2.
rar

;Save quotient and remainder to registers B and C.
mov b, a
mvi a, 00H
rar
mov c, a

;Continue working on decimal adjust.
mov a, b
sui 33H
mov b, a
mov a, c
ral
mov a, b

hlt
  • it can be done more easily with lesser amount of code as hown [here](https://stackoverflow.com/a/68130523/11155208) – codeR Jun 25 '21 at 11:49

1 Answers1

0

Suppose a two digit BCD number is represented as:

D7D6D5D4 D3D2D1D0
For a division by 2, for binary (or hex), simply right shift the number by one place. If there is an overflow then remainder is 1, and 0 othwerwise. The same things applies to two digit (8-bit) BCD numbers when D4 is 0, i.e. there is no effective bit shift from higher order four bits. Now if D4 is 1 (before the shift), then shifting will introduce a 8 (1000) in the lower order four bits, which apparantly jeopardizes this process. Observe that in BCD the bit shift should introduce 10/2 = 5 not 16/2 = 8. Thus we can simply adjust by subtrating 8-5 = 3 from the lower order four bits, i.e. 03H from the entire number. The following code summarizes this strategy. We assume accumulator holds the data, and after the division the result is kept in the accumulator and remainder is kept in the register B.
      MVI B,00H ; remainder = 0

      STC
      CMC       ; clear the carry flag
      RAR       ; right shift the data

      JNC SKIP
      INR B     ; CY=1 so, remainder = 1

SKIP: MOV D,A   ; backup
      ANI 08H   ; if get D3 after the shift (or D4 before the shift)
      MOV A,D   ; get the data from backup
      JZ FIN    ; if D4 before the shift was 0
      SUI 03H   ; adjustment for the shift

FIN:  HLT       ; A has the result, B has the remainder
codeR
  • 165
  • 1
  • 1
  • 13
  • Thanks for your code example. May I point out two aspects that may need improvement. First: If multi-digit BCDs have to be handled, there may be a remainder coming down from the more significant byte which is worth 50. Your code does not account for that. Second: With my code I tried to avoid jumps, which are expensive with respect to the number of processor cycles they use. – user3609959 Jun 27 '21 at 12:31
  • Thanks @user3609959 for pointing this out. 1. yes my my code cannot handle multibyte BCD numbers, it assumes the BCD number is of 2 digits as per question. Although it is esay to extend the same logic for handling more than two digits. 2. yes you are right, jumps are expensive! I will try to come-up with a jump free solution (if possible) and update the post – codeR Jun 28 '21 at 12:23