【问题标题】:Check if a number is odd or even (mathematical parity)检查一个数字是奇数还是偶数(数学奇偶校验)
【发布时间】:2015-05-31 07:05:28
【问题描述】:

对于一位数,我想知道它是奇数还是偶数(2 的倍数)。例如,给定 9,打印它是一个奇数。

(即检查mathematical parity,而不是计算parity。)

这就是我所拥有的:

   assume cs:cseg,ds:dseg,ss:sseg
    cseg segment
    start:  
    mov ax, dseg
    mov ds, ax  
    
    mov ah, 01h ; Here, im adding a number
    int 21h 
    
    
    
    jp even
    jnp odd  
    
    even: 
    mov ah,09
    lea dx,par
    int 21h  
    jmp exit
    odd: 
    mov ah,09
    lea dx,odd1 
    int 21h   
    jmp salir
    salir:
    mov ax,4C00h
    int 21h
    
    cseg ends 
    
    dseg segment byte         
    even Db 'Even number$'
    odd11 Db 'Odd number$'
    dseg ends  
    
    sseg segment stack
    db 100h dup(?)
    sseg ends

end start

【问题讨论】:

    标签: assembly x86-16 parity


    【解决方案1】:

    我找到了解决办法!

    只需在 jp 上面加上“and al,00000001”

    assume cs:cseg,ds:dseg,ss:sseg
        cseg segment
        start:  
        mov ax, dseg
        mov ds, ax  
    
        mov ah, 01h ; Here, im adding a number
        int 21h 
    
    and al,00000001
    
        jp even
        jnp odd  
    
        even: 
        mov ah,09
        lea dx,par
        int 21h  
        jmp exit
        odd: 
        mov ah,09
        lea dx,odd1 
        int 21h   
        jmp salir
        salir:
        mov ax,4C00h
        int 21h
    
        cseg ends 
    
        dseg segment byte         
        even Db 'Even number$'
        odd11 Db 'Odd number$'
        dseg ends  
    
        sseg segment stack
        db 100h dup(?)
        sseg ends
    
    end start
    

    【讨论】:

    • 1 - 0000_0001 奇数,奇偶校验。 2 - 0000_0010 偶数,奇偶校验。 3 - 0000_0011 奇数,奇偶校验。你到底想做什么?
    • 更好:test al, 1 而不是 and al,1。相同的指令长度,但可以在现代 CPU 上与 jcc 进行宏融合。 (即使jp,虽然单个位的奇偶校验与测试是否为零相同,这将更容易理解并且同样快速,尽管这确实有效。)
    【解决方案2】:

    要测试一个数字是奇数还是偶数,只需将其右移一次并检查进位标志:

        mov     al, 09
        shr     al       ; shifts all bits right 1, lowest bit to carry flag
        jc      _odd     ; carry set - there was a bit in lowest position
    _even:
        ; Do something with even numbers and exit
    _odd:
        ; Do something with odd numbers and exit
    

    了解进位标志对于各种编码技巧都非常有用。例如,“奇偶校验”是计算数字中的总位数,我们可以使用类似的技巧:

        mov    ah, 09
        xor    al, al    ; al = 0
    _loop:
        shr    ah        ; lower bit into carry flag
        adc    al, 0     ; Add 0 + carry flag to al
        and    ah, ah    ; sets Z flag if ah is zero
        bne    _loop
        ;  al now contains the total number of bits contained in ah
    

    【讨论】:

    • 减去“只需将其右移一次并检查进位标志”,这会破坏正在检查的数据
    • 他只是想知道它是奇数还是偶数,而不是重复使用它。 1 个指令字节并且没有内存访问开销是检查 if 您不会再次使用该值(他不在他的代码中)的最有效方法。
    • @Mike: test al,1 / jnz _odd 比轮班明显更有效率。在自 Core2 以来的 Intel 和自 Bulldozer 以来的 AMD 上,它可以宏融合成单个测试和分支微指令。 shr altest al,1 都是 2 字节指令。您的循环也比它可能的效率低。首先test ah,ah 会比and 更好。其次,您可以安排它,以便按照shr 的设置在 ZF 上进行分支。 (例如adc al,0/shr ah/jnz _loop/adc al,0。在第一次迭代中,adc al,0 是空操作,因为xor al,al 清除了 CF。退出循环后,添加最后一位CF。
    • 查看agner.org/optimizex86 tag wiki 中的其他x86 性能链接
    • @Mike:您声称shr al 是 1 个指令字节(在 8088 上会更快)。 2字节,与test al,1相同;对于移位没有特殊情况 AL / AX no-modrm 编码,只有其他实际采用立即数的指令,如test。 (可变计数移位在 186 中是新的,并且也不存在它们的短格式,但如果有的话,它仍然是 2 个总字节。)
    【解决方案3】:

    要测试一个数字是奇数还是偶数,您检查该数字的第 0 位。如果设置了 bit0,则该数字为奇数。没有其他的。 不要混淆 PF(奇偶校验标志)和 JP/JNP 条件。 Parity Flag 显示在最低有效字节中设置的位数是偶数还是奇数。

    来自文档:

    PF (bit 2) Parity flag — 如果结果的最低有效字节包含偶数个 1,则设置; 否则清除。

    数字 1 - 奇数,00000001b PF 被清除,因为只有一位设置
    数字 2 - 偶数,00000010b,但 PF 再次被清除!因为只有一位设置
    数字 3 - 奇数,00000011b,但 PF 已设置!因为设置了两个位

    【讨论】:

    • @TheLogicGuy: test eax, 1
    • 或者更好,test al, 1,因为没有test r32, imm8编码,所以通过读取al只读取eax的低字节更短。 (写部分寄存器不好,读就好。)
    【解决方案4】:

    虽然 Alexander Zhak 的回答指出了您的代码检查奇偶校验标志的缺陷,但以非破坏性方式检查 al 中数字奇偶校验的最快方法是:

            test al,1
            jz even
    odd:    ...
    even:   ...
    

    【讨论】:

      【解决方案5】:
          .MODEL SMALL
       .STACK 100H
      
       .DATA
         PROMPT_1  DB  'Enter a number: $'
         PROMPT_2  DB  0DH,0AH,'The given number in binary is: $'
         PROMPT_3  DB  0DH,0AH,'$' 
         MSG1 DB 10,13,’Number is Odd $’
         MSG2 DB 10,13,’Number is Even $’
      
       .CODE
         MAIN PROC
           MOV AX, @DATA                
           MOV DS, AX
      
           LEA DX, PROMPT_1                
           MOV AH, 9
           INT 21H
      
           XOR BL, BL                  
           MOV CX, 8                   
           MOV AH, 1                   
      
           @INPUT:                     
             INT 21H                   
             CMP AL, 0DH                
             JE @END                   
             AND AL, 0FH                
             SHL BL, 4                 
             OR BL, AL                  
           LOOP @INPUT                  
      
           @END:                        
      
           MOV AL, BL                   
           MOV CX, 8                    
      
           @LOOP:                       
             SHR AL, 1                  
             RCL BL, 0                  
           LOOP @LOOP                   
      
           LEA DX, PROMPT_2             
           MOV AH, 9
           INT 21H
      
           MOV CX, 8                    
           MOV AH, 2                    
      
           @OUTPUT:                     
             SHL BL, 1                  
      
             JNC @ZERO                  
               MOV DL, 31H              
               JMP @DISPLAY             
      
             @ZERO:                     
               MOV DL, 30H              
      
             @DISPLAY:                  
               INT 21H                  
           LOOP @OUTPUT                      
      
      
      
      MOV AH,01H
      INT 21H 
      
      mov ah,01h
      
      
      SAR AL,01h
      JC ODD
      
      
      LEA SI,MSG1
      CALL PRINT
      
      JMP TERMINATE
      
      ODD:
      LEA SI,MSG2
      CALL PRINT
      
      
      TERMINATE:
      MOV AH,4CH
      INT 21H
      
      PRINT PROC
      MOV DX,SI
      MOV AH,09H
      INT 21H
      
      
      
      
           MOV AH, 4CH                 
           INT 21H
      
       END MAIN
      

      【讨论】:

      • 这是做什么的,为什么它是这个问题的有用答案? shr al,1 / rcl bl, 0 / loop 是否应该位反转 AL?它没有; rcl 计数为零是一个昂贵的空操作,并且在 8086 上不受支持。rcl bl, 1 在 8086 上工作,并且会进行正确的位反转循环。无论如何,您只需要查看多位数字的最后一位十进制数字即可确定它是奇数还是偶数,因此您将其复杂化了(无论如何...)
      猜你喜欢
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-03
      • 1970-01-01
      • 1970-01-01
      • 2023-01-20
      • 2011-09-06
      相关资源
      最近更新 更多