【问题标题】:Converting Hexadecimal/Decimal numbers (Assemly-TASM)转换十六进制/十进制数 (Assembly-TASM)
【发布时间】:2012-09-14 05:41:12
【问题描述】:

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

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

P.S:我从这张图表中得到了帮助来理解这些数字。

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

【问题讨论】:

  • 你应该压缩你的代码,例如。 G。使用一次ror ax,4 而不是四次ror ax,1。此外,不是每个人都知道中断调用的作用(我从未在 DOS 下进行过汇编),如果您在这样的行中编写简短的 cmets,则更容易知道代码的作用。 -- 并且请尽可能多地删除空行。空行非常适合可读性,可以分隔代码的逻辑块,但是多个后续的空行只会过多地拉伸列表。
  • 我在 x64 中使用 DosBox,我认为这就是为什么我不能直接使用 ROR,4 或 SHR,4 ,我必须单独使用它们。并添加了评论
  • IIRC,您使用的是 TASM,对吗?可能是那个汇编程序的一个缺陷,因为我的英特尔手册说,立即旋转/移位也可以在 16 位模式下工作。不管怎样,mov word ptr [BX+2],AX 怎么样——这行得通吗? ;-)

标签: assembly x86 tasm


【解决方案1】:

8086 代码仅允许立即数为 1(或 cl)来计算移位和旋转。要启用 286 代码,请在文件顶部告诉 Tasm“.286”。这是一个猜测。

我记得我以前在 al 中打印两位数的方式:

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

【讨论】:

    【解决方案2】:

    只是试一试,虽然我不确定,但我无法快速测试。

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

    此外,我感觉问题与 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 指令可能比daa 加上ror 加上shr 更昂贵,但你的四次旋转/移位会更糟:-/

    (正如我所说的,我无法尝试...让这个开放给您...如果它不起作用,请回复。)

    [更新:

    另一种方法,特别是在这种简单的数字分隔情况下避免div,是将6添加到大于9的数字(即10d = 0ah --(+6)--> 16d = 10h;这是daa 也做了什么),那么你就可以和你之前使用的旋转/移位组合相处了。

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

    /更新]

    [更新级别=“2”

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

      xchg al,ah
    

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

    还有一个 bswap 指令用于反转寄存器中的字节顺序,但它显然只适用于 32 位以上宽度的寄存器。

    /更新]

    【讨论】:

    • 这不适用于第 20 位,;20d = 14h --(+6)--> 26d = 1Ah
    • yes :) 但我真的很感谢你的努力,我用这种方式简化了它,对于从 0A 到 19th 的每个值,我们必须添加 6d ,类似地,对于接下来的 10 个值,我们不需要添加6d 而不是我们必须添加 12d,对于接下来的 10 个值,我们必须添加 18d 等等 :) 给你 :) ;10d = 0ah --(+6)--> 16d = 10h ;20d = 14h --(+ 12)--> 32d = 20h ;30d = 1Eh --(+18)--> 48h = 30h
    【解决方案3】:
    .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
    

    【讨论】:

    • 欢迎来到 StackOverflow,在此之前您可能需要阅读 how to post a good answer。提供一些上下文来解释您发布该代码的原因以及它的作用,还可以考虑花时间格式化您的答案以便读者易于理解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    相关资源
    最近更新 更多