Thông báo

Collapse
No announcement yet.

Hỏi về cách đếm bit chẵn, lẻ.

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Hỏi về cách đếm bit chẵn, lẻ.

    Tôi chưa tìm ra cách nào hay về việc kiểm tra trong một thanh ghi 8 bit/16 bit có số bit 1/0 là chẵn hay lẻ. vd:01110010 > số bit 1 là 4 ( chẵn)... bằng asm. Không biết ai có cách gì hay không, xin chỉ giáo.

  • #2
    Nguyên văn bởi avr Xem bài viết
    Tôi chưa tìm ra cách nào hay về việc kiểm tra trong một thanh ghi 8 bit/16 bit có số bit 1/0 là chẵn hay lẻ. vd:01110010 > số bit 1 là 4 ( chẵn)... bằng asm. Không biết ai có cách gì hay không, xin chỉ giáo.
    bạn chỉ cần kiểm tra bit 0, nếu bit0=0 là số chẳn (even), nếu bít 0=1 thì là lẽ (odd).
    dễ ụi vậy mà không nghĩ ra à.
    Mãi đi tìm vàng.

    Comment


    • #3
      Nguyên văn bởi KVLV Xem bài viết
      bạn chỉ cần kiểm tra bit 0, nếu bit0=0 là số chẳn (even), nếu bít 0=1 thì là lẽ (odd).
      dễ ụi vậy mà không nghĩ ra à.
      Bạn ấy hỏi về việc đếm số bít 1 hoặc 0 trong 1 thanh ghi mà... Có phải kiểm tra giá trị thanh ghi là chẵn hay lẻ đâu.

      Nguyên văn bởi avr Xem bài viết
      Tôi chưa tìm ra cách nào hay về việc kiểm tra trong một thanh ghi 8 bit/16 bit có số bit 1/0 là chẵn hay lẻ. vd:01110010 > số bit 1 là 4 ( chẵn)... bằng asm. Không biết ai có cách gì hay không, xin chỉ giáo.
      Cách thì rõ ràng là có nhiều cách.
      Nhưng bạn dùng tiêu chí nào để gọi là Cách hay???
      Thường thì dân lập trình quan tâm tới 3 tiêu chí:
      - Chương trình gọn gàng, dễ đọc dễ kiểm soát.
      - Thực thi nhiệm vụ nhanh.
      - Tiết kiệm tài nguyên phần cứng (ROM, RAM...)
      Tiếc là 3 tiêu chí này ít khi đạt được cùng lúc.
      Hôm nay trời nắng chang chang.
      Mèo con đi học chẳng mang thứ gì.
      Chỉ mang một cái bút chì.
      Và mang một mẩu bánh mì con con.

      Comment


      • #4
        Nguyên văn bởi KVLV Xem bài viết
        bạn chỉ cần kiểm tra bit 0, nếu bit0=0 là số chẳn (even), nếu bít 0=1 thì là lẽ (odd).
        dễ ụi vậy mà không nghĩ ra à.
        Anh đang nói về việc kiểm tra một số lưu trong thanh ghi là chẵn/lẻ cũng được vì nó cũng là cách làm cho cái kia, nhưng anh nói rõ hơn được không?
        Vd: trong r16 đang lưu số 17 (thập phân). Kiểm tra thế nào với asm vì nó cũng hạn chế với các phép toán.

        Comment


        • #5
          Nguyên văn bởi Acxen_lupine Xem bài viết
          Bạn ấy hỏi về việc đếm số bít 1 hoặc 0 trong 1 thanh ghi mà... Có phải kiểm tra giá trị thanh ghi là chẵn hay lẻ đâu.


          Cách thì rõ ràng là có nhiều cách.
          Nhưng bạn dùng tiêu chí nào để gọi là Cách hay???
          Thường thì dân lập trình quan tâm tới 3 tiêu chí:
          - Chương trình gọn gàng, dễ đọc dễ kiểm soát.
          - Thực thi nhiệm vụ nhanh.
          - Tiết kiệm tài nguyên phần cứng (ROM, RAM...)
          Tiếc là 3 tiêu chí này ít khi đạt được cùng lúc.
          Anh làm theo tùy chọn 3 đi.

          Comment


          • #6
            Bạn đâng dùng vi điều khiển loại nào. Nếu với 8051 thì chỉ cần MOV nó vào thanh ghi A là được

            Comment


            • #7
              cách hay thì cũng không biết ... mà asm thì càng chẳng muốn nghĩ

              ở đây mình có 1 cái test thử trên 89 ... 1 đoạn code = C ( bác xem tự hiểu )

              bài toán của mình : cho 1 biến ( gọi là number ) ... đếm số 1 trong đó ... nếu được kết quả 2,4,6,8 ( chẵn ) thì bộ đệm buff=0; ( chẵn ) và buff=1; ( lẻ ) ... Mình để nguyên view asm !

              Code:
              _main:
                  MOV SP+0, #128
              ;89c51_test.c,3 ::         void main()
              ;89c51_test.c,6 ::         cnt=0;
                  MOV _cnt+0, #0
              ;89c51_test.c,7 ::         for(i=0;i<8;i++)
                  MOV _i+0, #0
              L_main0:
                  CLR C
                  MOV A, _i+0
                  SUBB A, #8
                  JNC L_main1
              ;89c51_test.c,9 ::         if((number & 0x80)==0x80)cnt++;
                  MOV A, _number+0
                  ANL A, #128
                  MOV R1, A
                  XRL A, #128
                  JNZ L_main3
                  INC _cnt+0
              L_main3:
              ;89c51_test.c,10 ::         number= number<<1;
                  MOV R0, #1
                  MOV A, _number+0
                  INC R0
                  SJMP L__main9
              L__main10:
                  CLR C
                  RLC A
              L__main9:
                  DJNZ R0, L__main10
                  MOV _number+0, A
              ;89c51_test.c,7 ::         for(i=0;i<8;i++)
                  INC _i+0
              ;89c51_test.c,11 ::         }
                  SJMP L_main0
              L_main1:
              ;89c51_test.c,12 ::         if((cnt==2)||(cnt==4) || (cnt==6) || (cnt==8))buff=0;  // chan
                  MOV A, _cnt+0
                  XRL A, #2
                  JZ L__main8
                  MOV A, _cnt+0
                  XRL A, #4
                  JZ L__main8
                  MOV A, _cnt+0
                  XRL A, #6
                  JZ L__main8
                  MOV A, _cnt+0
                  XRL A, #8
                  JZ L__main8
                  SJMP L_main6
              L__main8:
                  MOV _buff+0, #0
                  SJMP L_main7
              L_main6:
              ;89c51_test.c,13 ::         else buff=1;   // le
                  MOV _buff+0, #1
              L_main7:
              ;89c51_test.c,16 ::         }
                  SJMP #254
              ; end of _main
              Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

              Comment


              • #8
                cũng bài tương tự nhưng với AVR ... có tác động R16, R27
                Code:
                _main:
                        LDI        R27, 255
                        OUT        SPL+0, R27
                        LDI        R27, 0
                        OUT        SPL+1, R27
                
                ;MyProject.c,3 ::                 void main()
                ;MyProject.c,6 ::                 cnt=0;
                        LDI        R27, 0
                        STS        _cnt+0, R27
                ;MyProject.c,7 ::                 for(i=0;i<8;i++)
                        LDI        R27, 0
                        STS        _i+0, R27
                L_main0:
                        LDS        R16, _i+0
                        CPI        R16, 8
                        BRLO       L__main14
                        JMP        L_main1
                L__main14:
                ;MyProject.c,9 ::                 if((number & 0x80)==0x80)cnt++;
                        LDS        R16, _number+0
                        ANDI       R16, 128
                        CPI        R16, 128
                        BREQ       L__main15
                        JMP        L_main3
                L__main15:
                        LDS        R16, _cnt+0
                        SUBI       R16, 255
                        STS        _cnt+0, R16
                L_main3:
                ;MyProject.c,10 ::                 number= number<<1;
                        LDS        R16, _number+0
                        LSL        R16
                        STS        _number+0, R16
                ;MyProject.c,7 ::                 for(i=0;i<8;i++)
                        LDS        R16, _i+0
                        SUBI       R16, 255
                        STS        _i+0, R16
                ;MyProject.c,11 ::                 }
                        JMP        L_main0
                L_main1:
                ;MyProject.c,12 ::                 if((cnt==2)||(cnt==4) || (cnt==6) || (cnt==8))buff=0;  // chan
                        LDS        R16, _cnt+0
                        CPI        R16, 2
                        BRNE       L__main16
                        JMP        L__main12
                L__main16:
                        LDS        R16, _cnt+0
                        CPI        R16, 4
                        BRNE       L__main17
                        JMP        L__main11
                L__main17:
                        LDS        R16, _cnt+0
                        CPI        R16, 6
                        BRNE       L__main18
                        JMP        L__main10
                L__main18:
                        LDS        R16, _cnt+0
                        CPI        R16, 8
                        BRNE       L__main19
                        JMP        L__main9
                L__main19:
                        JMP        L_main6
                L__main12:
                L__main11:
                L__main10:
                L__main9:
                        LDI        R27, 0
                        STS        _buff+0, R27
                        JMP        L_main7
                L_main6:
                ;MyProject.c,13 ::                 else buff=1;   // le
                        LDI        R27, 1
                        STS        _buff+0, R27
                L_main7:
                ;MyProject.c,16 ::                 }
                L_end_main:
                L__main_end_loop:
                        JMP        L__main_end_loop
                ; end of _main
                Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

                Comment


                • #9
                  Nguyên văn bởi avr Xem bài viết
                  Anh đang nói về việc kiểm tra một số lưu trong thanh ghi là chẵn/lẻ cũng được vì nó cũng là cách làm cho cái kia, nhưng anh nói rõ hơn được không?
                  Vd: trong r16 đang lưu số 17 (thập phân). Kiểm tra thế nào với asm vì nó cũng hạn chế với các phép toán.
                  tôi xem lại câu hỏi đầu tiên của bạn, giờ mới hiểu bạn hỏi gì.
                  cách của tôi thì dùng luật toán rotate bit left hoặc rotate bit right, kiểm tra carry bit (CY). trong loop kiểm tra CY đếm xem bao nhiêu CY=1, bao nhiêu CY=0, nếu số đếm có bit0=0 thì chẳn, bit0=1 thì là lẽ . nếu 8 bit thì rotate 8x, 16 bit thì rotate 16x.

                  à cái này là áp dụng cho asm. tôi không học AVR nên không biết dùng lệnh nào, tôi gợi ý, bạn viết code nha.
                  Mãi đi tìm vàng.

                  Comment


                  • #10
                    Nguyên văn bởi queduong Xem bài viết
                    cách hay thì cũng không biết ... mà asm thì càng chẳng muốn nghĩ

                    ở đây mình có 1 cái test thử trên 89 ... 1 đoạn code = C ( bác xem tự hiểu )

                    bài toán của mình : cho 1 biến ( gọi là number ) ... đếm số 1 trong đó ... nếu được kết quả 2,4,6,8 ( chẵn ) thì bộ đệm buff=0; ( chẵn ) và buff=1; ( lẻ ) ... Mình để nguyên view asm !

                    Code:
                    _main:
                        MOV SP+0, #128
                    ;89c51_test.c,3 ::         void main()
                    ;89c51_test.c,6 ::         cnt=0;
                        MOV _cnt+0, #0
                    ;89c51_test.c,7 ::         for(i=0;i<8;i++)
                        MOV _i+0, #0
                    L_main0:
                        CLR C
                        MOV A, _i+0
                        SUBB A, #8
                        JNC L_main1
                    ;89c51_test.c,9 ::         if((number & 0x80)==0x80)cnt++;
                        MOV A, _number+0
                        ANL A, #128
                        MOV R1, A
                        XRL A, #128
                        JNZ L_main3
                        INC _cnt+0
                    L_main3:
                    ;89c51_test.c,10 ::         number= number<<1;
                        MOV R0, #1
                        MOV A, _number+0
                        INC R0
                        SJMP L__main9
                    L__main10:
                        CLR C
                        RLC A
                    L__main9:
                        DJNZ R0, L__main10
                        MOV _number+0, A
                    ;89c51_test.c,7 ::         for(i=0;i<8;i++)
                        INC _i+0
                    ;89c51_test.c,11 ::         }
                        SJMP L_main0
                    L_main1:
                    ;89c51_test.c,12 ::         if((cnt==2)||(cnt==4) || (cnt==6) || (cnt==8))buff=0;  // chan
                        MOV A, _cnt+0
                        XRL A, #2
                        JZ L__main8
                        MOV A, _cnt+0
                        XRL A, #4
                        JZ L__main8
                        MOV A, _cnt+0
                        XRL A, #6
                        JZ L__main8
                        MOV A, _cnt+0
                        XRL A, #8
                        JZ L__main8
                        SJMP L_main6
                    L__main8:
                        MOV _buff+0, #0
                        SJMP L_main7
                    L_main6:
                    ;89c51_test.c,13 ::         else buff=1;   // le
                        MOV _buff+0, #1
                    L_main7:
                    ;89c51_test.c,16 ::         }
                        SJMP #254
                    ; end of _main
                    Cách này của bác hay. Nhưng có vẻ như là "Dùng búa tạ đập ruồi". Xin lỗi vì đã chê bác nhé.
                    Giả sử bạn có một byte dữ liệu cần kiểm tra dữ liệu cần kiểm tra chứa trong thanh ghi trong R0
                    Bạn chỉ cần MOV nó vào thanh ghi A bằng lệnh
                    Code:
                    MOV A, R0
                    Ngay sau lênh này thì bit số 0 trong thanh ghi PSW chuyển thành party lẻ rùi (Bit 0 trong thanh ghi PSW kí hiệu là P)
                    Khi đã có party lẻ rùi mà muốn sử dụng Party chẵn thì bác lại thực hiện 2 lện sau
                    Code:
                    MOV C,P //Chuyển Bit party vào cờ nhớ C
                    CPL C // Đảo ngược cờ nhớ C
                    Ngay sau lệnh này thì ta đã có party chẵn.
                    Vậy với 1 byte dữ liệu:
                    --1 lệnh ta sẽ có được party lẻ
                    --3 lệnh ta sẽ có được party chẵn

                    Với 2 byte dữ liệu( 16bit) thì làm thế nào??: ta đặc các trường hợp như sau
                    16 bit có party là chẵn
                    16 bit có party là lẻ
                    TRường hợp 1: 16bit có party chẵn
                    các khả năng xảy ra : Mỗi byte có trong 2 byte đều đồng thời có party chẵn, hoặc mỗi byte trong 2 byte đó đều có 1 party lẻ
                    Trường hợp 2: 16bit có party lẻ
                    Chỉ có 1 khả năng duy nhất xảy ra là 1 trong 2 byte đó là party lẻ, byte còn lại là party chẵn

                    Như vậy: Ta có thể thực hiện phép XOR để thực hiện phép tính với 16bit
                    Bước 1: Thực hiện party 8 bit vói byte cao ta được bit party là PH
                    Bước 2: Thực hiện party 8 bit với byte thấp ta được bit party là PL
                    Bước 3: Thực hiên XOR với PH và PL ta thu được Party 16bit

                    Chú ý: Cách này thực hiện với 8051 nhé

                    Comment


                    • #11
                      Nguyên văn bởi KVLV Xem bài viết
                      tôi xem lại câu hỏi đầu tiên của bạn, giờ mới hiểu bạn hỏi gì.
                      cách của tôi thì dùng luật toán rotate bit left hoặc rotate bit right, kiểm tra carry bit (CY). trong loop kiểm tra CY đếm xem bao nhiêu CY=1, bao nhiêu CY=0, nếu số đếm có bit0=0 thì chẳn, bit0=1 thì là lẽ . nếu 8 bit thì rotate 8x, 16 bit thì rotate 16x.

                      à cái này là áp dụng cho asm. tôi không học AVR nên không biết dùng lệnh nào, tôi gợi ý, bạn viết code nha.
                      Xét với AVR
                      Theo mình thì không cần đếm: Chỉ cần quay qua cờ nhớ 8 hoặc 16 lần thôi. Nếu như R16 của bạn đang lưu cái số bạn cần kiểm tra. ban đầu bạn gán thanh ghi R1 bằng 0 nếu như bạn muốn tính party lẻ
                      Quay qua cờ nhớ. Cứ khi nào cờ nhớ là bit 1 thì bạn NOT R1 = FF là được.
                      Nếu byte đó có 1 số 1 (số lẻ bit 1) thì bạn sẽ NOT 1 lần sau 8 trong đó có 7 lần là số 0 nên không bị NOT nên sẽ thu được byte cuối cùng thu được là R1=FF
                      Nếu byte đó có 2 số 1 (số chẵn bít 1)thì bạn sẽ NOT R1 hai lần kết quả sẽ thu được byte cuối cùng là R1= 00 tương ứng.

                      Tương tự với việc tính party chẵn

                      Comment


                      • #12
                        Nguyên văn bởi congbinh1989 Xem bài viết
                        Cách này của bác hay. Nhưng có vẻ như là "Dùng búa tạ đập ruồi". Xin lỗi vì đã chê bác nhé.
                        Giả sử bạn có một byte dữ liệu cần kiểm tra dữ liệu cần kiểm tra chứa trong thanh ghi trong R0
                        Bạn chỉ cần MOV nó vào thanh ghi A bằng lệnh
                        Code:
                        MOV A, R0
                        Ngay sau lênh này thì bit số 0 trong thanh ghi PSW chuyển thành party lẻ rùi (Bit 0 trong thanh ghi PSW kí hiệu là P)
                        Khi đã có party lẻ rùi mà muốn sử dụng Party chẵn thì bác lại thực hiện 2 lện sau
                        Code:
                        MOV C,P //Chuyển Bit party vào cờ nhớ C
                        CPL C // Đảo ngược cờ nhớ C
                        Ngay sau lệnh này thì ta đã có party chẵn.
                        Vậy với 1 byte dữ liệu:
                        --1 lệnh ta sẽ có được party lẻ
                        --3 lệnh ta sẽ có được party chẵn

                        Với 2 byte dữ liệu( 16bit) thì làm thế nào??: ta đặc các trường hợp như sau
                        16 bit có party là chẵn
                        16 bit có party là lẻ
                        TRường hợp 1: 16bit có party chẵn
                        các khả năng xảy ra : Mỗi byte có trong 2 byte đều đồng thời có party chẵn, hoặc mỗi byte trong 2 byte đó đều có 1 party lẻ
                        Trường hợp 2: 16bit có party lẻ
                        Chỉ có 1 khả năng duy nhất xảy ra là 1 trong 2 byte đó là party lẻ, byte còn lại là party chẵn

                        Như vậy: Ta có thể thực hiện phép XOR để thực hiện phép tính với 16bit
                        Bước 1: Thực hiện party 8 bit vói byte cao ta được bit party là PH
                        Bước 2: Thực hiện party 8 bit với byte thấp ta được bit party là PL
                        Bước 3: Thực hiên XOR với PH và PL ta thu được Party 16bit

                        Chú ý: Cách này thực hiện với 8051 nhé
                        Đúng vậy , làm cách của bạn trong 8051 là đơn giản hơn rất nhiều . Ở trên " chủ thớt " có hỏi về AVR ... mình chỉ đưa 2 đoạn mã ( cùng 1 chương trình ) ... 1 cái cho 8051 và 1 cái cho AVR để chủ thớt tự so sánh.
                        Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

                        Comment


                        • #13
                          Nguyên văn bởi queduong Xem bài viết
                          Đúng vậy , làm cách của bạn trong 8051 là đơn giản hơn rất nhiều . Ở trên " chủ thớt " có hỏi về AVR ... mình chỉ đưa 2 đoạn mã ( cùng 1 chương trình ) ... 1 cái cho 8051 và 1 cái cho AVR để chủ thớt tự so sánh.
                          Mình cũng trả lời với AVR rùi đó

                          Comment


                          • #14
                            Vậy có thể có vài cách:
                            -Đếm số bít 1/0 bằng cách rotate ra cờ C ( theo KLVL) rồi:
                            So sánh thủ công với 2,4,6....,16 như anh Dương đưa ra, cái này đã có 1 admin khác chỉ tôi vài dòng C rồi thôi, ko hiểu.
                            So sánh như anh KVLV thì có thể là một cách của asm nhưng tôi cũng ko hiểu lắm cho con avr.
                            - Theo congbinh1989 thì chắc chỉ được cho 89Cxx, có vẻ như cách của bạn là xor tất cả các bit 1 trong thanh ghi nếu kết quả là 0/1 thì biết chẵn, lẻ.

                            Tóm lại, là những cách quen thuộc nhưng chắc chắn.
                            Cảm ơn các bạn nhé.

                            Comment


                            • #15
                              Nguyên văn bởi congbinh1989 Xem bài viết
                              Xét với AVR
                              Theo mình thì không cần đếm: Chỉ cần quay qua cờ nhớ 8 hoặc 16 lần thôi. Nếu như R16 của bạn đang lưu cái số bạn cần kiểm tra. ban đầu bạn gán thanh ghi R1 bằng 0 nếu như bạn muốn tính party lẻ
                              Quay qua cờ nhớ. Cứ khi nào cờ nhớ là bit 1 thì bạn NOT R1 = FF là được.
                              Nếu byte đó có 1 số 1 (số lẻ bit 1) thì bạn sẽ NOT 1 lần sau 8 trong đó có 7 lần là số 0 nên không bị NOT nên sẽ thu được byte cuối cùng thu được là R1=FF
                              Nếu byte đó có 2 số 1 (số chẵn bít 1)thì bạn sẽ NOT R1 hai lần kết quả sẽ thu được byte cuối cùng là R1= 00 tương ứng.

                              Tương tự với việc tính party chẵn
                              Nguyên văn bởi avr Xem bài viết
                              Vậy có thể có vài cách:
                              -Đếm số bít 1/0 bằng cách rotate ra cờ C ( theo KLVL) rồi:
                              So sánh thủ công với 2,4,6....,16 như anh Dương đưa ra, cái này đã có 1 admin khác chỉ tôi vài dòng C rồi thôi, ko hiểu.
                              So sánh như anh KVLV thì có thể là một cách của asm nhưng tôi cũng ko hiểu lắm cho con avr.
                              - Theo congbinh1989 thì chắc chỉ được cho 89Cxx, có vẻ như cách của bạn là xor tất cả các bit 1 trong thanh ghi nếu kết quả là 0/1 thì biết chẵn, lẻ.

                              Tóm lại, là những cách quen thuộc nhưng chắc chắn.
                              Cảm ơn các bạn nhé.
                              Cách mà bạn congbinh1989 đưa ra cho 8051 là cách "siêu hay", Cho AVR được gọi là cách hay.
                              Cách của bác Queduong là cách cơ bản, an toàn.
                              Hôm nay trời nắng chang chang.
                              Mèo con đi học chẳng mang thứ gì.
                              Chỉ mang một cái bút chì.
                              Và mang một mẩu bánh mì con con.

                              Comment

                              Về tác giả

                              Collapse

                              avr Tìm hiểu thêm về avr

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X