assemblyx86-16masmemu8086

8086 how to reverse decimal digits of a byte in a register


How can I reverse a register value at byte level?

mov al,12  -----> how can i reverse al value
to 21

Here's what I have tried :

mov bx,4321      ;i want to make bx 1234
mov cl,04          ;cl for rotation value
xchg bh,bl          ; now bx will 2143  
mov al,bh         ;moving 21 to al
rol al,cl             ; rotate al 4 times  to left now al is 12`
mov bh,al      ; bh is 12 setuped ,time for bl

;---------------------------
mov al,bl   ;moving lower byte  43 to al
rol al,cl     ; rotate 4 times to left now al will 34
mov bl,al      ; moving 34 to bl  

Now bx must contain a reversed number 1234; the problem was the number is in hex that is 10e1h or 4321.

When I reverse it is 1e01h but this value is not expressing 1234.

1234 is 04d2. The value I am getting is 7681d.


Solution

  • While the other answers are giving you a direct solution to your problem, I'd like to write something about the theory because I think it will help you next time:

    As you have already written, the decimal number 1234 is written as 4D2 in hexadecimal system and 4321 is written as 10E1.

    This means that the operation "reverting a number" leads to different results in different numeral systems:

    In decimal system "reverting" 1234 leads to 4321. In hexadecimal system "reverting" 4D2 leads to 2D4. Using a fixed length of 4 hexadecimal digits (16-bit registers!) however "reverting" 04D2 will lead to 2D40...

    If some operation only works in a certain base(*), you have to consider the following:

    Using a computer working with bytes you can easily perform operations in base-256: xchg bh,bl will "revert" the two digits of the number in base-256 system.

    Performing operations in a base 2^N (such as binary, octal or hexadecimal) are possible using shifting and rotating.

    However operations on other bases (such as decimal) you will require to calculate the single digits, perform the operation and calculate the (binary) number from the digits.

    For reverting a decimal number the following pseudo-code might work:

      A = input (here: 1234)
      B = 0
    mainLoop:
      digit =  A mod 10  (get the right digit of A)
      A = A/10           (remove the right digit from A)
      B = 10*B + digit   (append the digit to B)
      if A>0: jump to mainLoop
    

    In assembler the code could look like this:

        mov ax,1234   ; ax = "A" in the pseudo-code
        mov cx,0      ; cx = "B" in the pseudo-code
        mov bx,10     ; The base we are working in
    mainLoop:
        xchg ax,cx    ; "mul" can only work with ax
        mul bx        ; Results: ax = "10*B"
                      ;          dx = overflow (typically 0)
        xchg ax,cx    ; Change ax and cx back: cx="10*B"
        mov dx,0      ; Prepare dx for "div"
        div bx        ; Perform division and modulo
                      ; Result:
                      ;   ax = "A/10"
                      ;   dx = "A MOD 10" = "digit"
        add cx,dx     ; "B = 10*B+digit"
        cmp ax,0
        ja mainLoop
                      ; Here cx will contain the "reverted" number
    

    (*) The operation you want to perform is not "reverting a number" but "reverting a decimal number".