3

我试图简单地按顺序打印数字,即

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

使用循环,首先我将每个数字转换为 Hexa 打印,将其重置为十进制增量 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”。这是一个猜测。

我记得我曾经在 al 中打印两位数的方式:

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

只是试一试,虽然我不确定,我不能快速测试这个。

但我建议不要使用两个循环,而是对整个数字使用一个循环。

此外,我觉得问题与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

如果您不介意一位数字是否有前导零,那就更容易了。

div指令可能比daaplus rorplus更昂贵shr,但您的四轮旋转/移位会更糟:-/

(正如我所说,我无法尝试......把这个留给你......如果它不起作用,只是问回来。)

[更新:

另一种方法,尤其是div在这种简单的数字分隔情况下,将 6 添加到大于 9 的数字(即 10d = 0ah --(+6)--> 16d = 10h;这daa也是这样做的),然后您可以使用之前使用的旋转/移位组合。

更好的是添加 246,然后添加到AX,之后您可以简单地使用ror ax,8(或rol- 在这种情况下无关紧要),即 10d = 0ah --(+246)--> 256d = 100h,以及 15d = 0fh --(+246)--> 261 = 105h。分别旋转为0001h或0501h,加上3030h,就大功告成了。

/更新]

[更新级别=“2”

多么有趣...我实际上打算在第一级更新中编写它,但不知何故忘记了:而不是rolling by 8,或者 - 如果你的 TASM 真的不支持rolling by immediate - 八倍滚动一个,你当然也可以使用xchg在寄存器之间交换值的指令,在这种情况下

  xchg al,ah

将完成交换这两个寄存器的内容的工作。

还有一条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 回答