3

数字を単純に順番に印刷しようとしています。

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

ループを使用して、最初に各数値をヘキサに変換して印刷し、10進数のインクリメントに1ずつリセットしてから、数値が9に等しくなるまで次を印刷します。数値が9に等しい場合、DAAを使用して単純に数値を回転させた後数値をシフトして、最終的に結果を文字列に格納しました。

出力は 16 までは問題ありませんが、16 以降はシーケンスが繰り返されます。

望ましい出力:

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

電流出力 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,11,12,13,14,15

どうしてこうなるの???

これが私のコードです。

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

PS: 数字を理解するには、このチャートを参考にしました。

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

4

3 に答える 3

4

8086 コードでは、シフトと回転のカウントに 1 (または cl) の即値のみが許可されていました。286 コードを有効にするには、Tasm にファイルの先頭に「.286」と指定します。それは推測です。

私が覚えている方法は、以前は 2 桁の数字を印刷していたものです。

aam
add ax, 3030h
xchg al, ah
int 29h
mov al, ah
int 29h
于 2012-09-22T08:26:22.553 に答える
3

よくわかりませんが、試してみるだけです。これをすぐにテストすることはできません。

ただし、2 つのループを使用する代わりに、一連の数値全体に対して 1 つのループを使用することをお勧めします。

DAAさらに、64ビットモードではサポートされていないため、慣れていない命令に問題があると感じています。

とにかく、これが私がすることです:

      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

1 桁の数字の先頭に 0 が付いていてもかまわない場合は、さらに簡単になります。

命令はおそらくplus plusdivよりも高価ですが、クワッド回転/シフトはさらに悪化します:-/daarorshr

(私が言ったように、私はそれを試すことができませんでした...これはあなたに公開しておいてください...うまくいかない場合は、戻って聞いてください。)

[アップデート:

別のアプローチとして、特にdivこの些細な桁区切りのケースで を節約するために、9 より大きい数字に 6 を足すという方法があります (つまり、10d = 0ah --(+6)--> 16d = 10h; これdaaも同様です)。以前に使用した回転/シフトの組み合わせに慣れることができます。

さらに良いのは、 に 246 を追加しAXた後、単純に使用できますror ax,8(またはrol— この場合は問題ではありません)。 --(+246)--> 261 = 105h. それぞれ 0001h または 0501h になるように回転させ、3030h を追加すれば完了です。

/アップデート]

[更新レベル="2"

なんて楽しい...最初のレベルの更新で実際にそれを書くつもりだったのですが、どういうわけか忘れていましたrol:rolもちろんxchg、この場合、レジスタ間で値を交換する命令を利用することもできます

  xchg al,ah

これらの 2 つのレジスタの内容を交換するジョブを実行します。

レジスタ内のバイト順を逆にする命令もありbswapますが、明らかに 32 ビット幅以上のレジスタでしか使用できません。

/アップデート]

于 2012-09-21T21:29:08.447 に答える
0
.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
于 2016-03-29T20:31:18.120 に答える