micheller
micheller

Reputation: 173

Converting Hexadecimal/Decimal numbers (Assemly-TASM)

I am trying to print the numbers simply in the sequence i.e

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

using Loop, First i converted each number into Hexa printed it reset it to the decimal increment by 1 and then print the next until the number is equal to 9, When the number is equal to 9 i used DAA to simply the number and after rotating and shifting the number i eventually stored the result in the string.

The output is just fine till the 16, but after 16 the sequence repeats itself,

Desired output:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

Current Output 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,11,12,13,14,15

Why does it happens so ???

Here is my Code,

MOV CX,20 ;Number of Iterations


MOV DX,1



L1:
    PUSH DX
    ADD DX,30H  
    MOV AH,02H        ;PRINT Content of DX
    INT 21H
    POP DX
    ADD DX,1
    CMP DX,09d        ;If number is Greater than 9 jump to L2   
    JA L2
LOOP L1


    L2: 
        PUSH DX
        MOV AX,DX
        DAA           ;Convert to the Decimal
        XOR AH,AH         ;SET AH to 0000


        ROR AX,1    
        ROR AX,1    
        ROR AX,1    
        ROR AX,1    

        SHR AH,1
        SHR AH,1
        SHR AH,1
        SHR AH,1

        ADC AX,3030h
        MOV BX,OFFSET Result
        MOV byte ptr[BX],5           ; Length of the String
        MOV byte ptr[BX+4],'$'       ;5th position of string , $=Terminator
        MOV byte ptr[BX+3],AH        ;2nd Number onto 4th position
        MOV byte ptr[BX+2],AL        ;3rd number onto 3rd Position 

        MOV DX,BX
        ADD DX,02     ;1st 2 positions of String are type of string and    
                                  length respectively 
        MOV AH,09H ;to print the string
        INT 21H         

        POP DX      
        ADD DX,1

    LOOP L2

MOV AH,4CH  ;Return control to the DOS
INT 21H

P.S: I took help from this chart in understanding the numbers.

http://www.cheat-sheets.org/saved-copy/ascii.png

Upvotes: 3

Views: 10129

Answers (3)

AKM
AKM

Reputation: 1

.model small  
 .stack 100  
 .code  
      mov ax, 0ffffh            ; hex number to find it's bcd  
      mov      bx, 0000  
      mov      dh, 0  
 l9 :     cmp     ax, 10000     ; if ax>10000  
      jb      l2  
      sub      ax, 10000        ; subtract 10000  
      inc      dh               ; add 1 to dh  
      jmp      l9  
 l2 :     cmp      ax, 1000     ; if ax>1000  
      jb      l4  
      sub      ax, 1000  
      add      bx, 1000h        ; add 1000h to result  
      jmp      l2  
 l4 :     cmp      ax, 100      ; if ax>100  
      jb      l6  
      sub      ax, 100  
      add      bx, 100h         ; add 100h to result  
      jmp      l4  
 l6 :     cmp      ax, 10       ; if ax>10  
      jb      l8  
      sub      ax, 10  
      add      bx, 10h          ; add 10h to result  
      jmp      l6  
 l8 :     add      bx, ax       ; add remainder   
                                ; to result  
      mov      ah, 02            
      mov      cx, 0204h        ; Count to display   
                                ; 2 digits  
      go:      rol dh, cl  
      mov      dl, dh  
      and      dl, 0fh  
      add      dl, 30h          ; display 2 msb digits       
      int      21h  
      dec      ch  
      jnz      go  
      mov      ch, 04h          ; Count of digits to be   
                                ; displayed  
      mov      cl, 04h          ; Count to roll by 4 bits  
 l12:     rol      bx, cl       ; roll bl so that msb   
                                ; comes to lsb                  
      mov      dl, bl           ; load dl with data to be   
                                ; displayed  
      and      dl, 0fH          ; get only lsb  
      cmp      dl, 09           ; check if digit is 0-9 or letter A-F      
      jbe      l14  
      add      dl, 07           ; if letter add 37H else only add 30H  
 l14:     add      dl, 30H  
      mov      ah, 02           ; Function 2 under INT 21H      (Display character)  
      int      21H  
      dec      ch               ; Decrement Count  
      jnz      l12  
      mov      ah, 4cH          ;  Terminate Program  
      int      21H  
 end

Upvotes: 0

Frank Kotler
Frank Kotler

Reputation: 1452

8086 code only allowed an immediate of 1 (or cl) for a count on shifts and rotates. To enable 286 code, tell Tasm ".286" at the top of your file. That's a guess.

The way I remember I used to print a two-digit number in al:

aam
add ax, 3030h
xchg al, ah
int 29h
mov al, ah
int 29h

Upvotes: 4

IdiotFromOutOfNowhere
IdiotFromOutOfNowhere

Reputation: 459

Just giving it a try, though I'm not sure, and I can't quickly test this.

But instead of using two loops I'd recommend using one for the whole bunch of numbers.

Furthermore I have the feeling that the problem has to do with the DAA instruction, which I'm not used to, since it is not supported in 64 bit mode.

Anyway, here's what I'd do:

      mov  cx,20
      mov   al,1
      mov   bl,10      ; divisor
      mov   bp,offset Result ; no need to load this in the loop!!!

L1:   mov   dx,ax      ; save to register, not to stack
      cmp   ax,09d
      ja    L2         ; number has two digits
      add   al,30h     ; ASCII addend

      ; insert your output code here

      jmp   L3         ; jump over the two digit code
L2:   xor   ah,ah
      div   bl         ; divides AX by ten (no rotate or shift needed)
                       ; quotient in AL, remainder in AH (correct order for little endian)
      add   ax,3030h

      ; insert your output code here (note that the buffer/string address is loaded to BP)

L3:   mov   ax,dx
      inc   ax
      loop  L1

      ; done

If you wouldn't mind if one-digit numbers had a leading zero, it'd be even easier.

The div instruction is probably more expensive than daa plus ror plus shr, but your quad-rotate/shift will be even worse :-/

(As I said, I could not try it... leaving this open to you... if it doesn't work, just ask back.)

[update:

Another approach, especially to spare the div in this trivial case of digit separation, would be to add 6 to numbers greater nine (i. e. 10d = 0ah --(+6)--> 16d = 10h; this is what daa also does), then you can get along with the rotate/shift combination you used before.

Even better were to add 246, then to AX, after which you can simply use ror ax,8 (or rol — doesn't matter in this case), i. e. 10d = 0ah --(+246)--> 256d = 100h, as well 15d = 0fh --(+246)--> 261 = 105h. Rotate it to be 0001h or 0501h respectively, add 3030h, and you're done.

/update]

[update level="2"

What the fun... I actually intended to write it in the first level update, but forgot it somehow: instead of rolling by 8, or — if your TASM really doesn't support rolling by immediate — eight times rolling by one, you can of course also make use of the xchg instruction, which swaps values between registers, in this case

  xchg al,ah

would do the job of swapping the contents of those two registers.

There's also a bswap instruction for reversing the byte order within a register, but it's obviously only available for registers of 32+ bits width.

/update]

Upvotes: 3

Related Questions