簡體   English   中英

根據偶數/奇數 popcount 向右/左移動

[英]Shift right/left based on an even/odd popcount

我的代碼應該檢查一個變量是否有奇數或偶數位打開,然后右移打開的位數,如果數量是偶數,或者如果它是奇數,則向左移動那么多次。

這是我的代碼:

IDEAL
MODEL small
STACK 100h
DATASEG
TAV db 00001001b
t_copy db 00001001b

CODESEG
start:

    xor cx,cx
    mov cx,8
    xor al,al
    L1:
        shr [t_copy],1
        jnc nc
        inc al
        nc:
        
        dec cx
        jnz L1
    mov cl,al
    and al,00000001h
    
    cmp al,0h
    jz even_               
    jnz odd
    
    
    odd:
        shl [TAV],cl
        jmp exit
    even_:
        shr [TAV],cl
    
exit:
    mov ax, 4c00h
    int 21h
END start

當我運行代碼時,它不會移動,也不會更改變量的值。 我認為它將變量的值更改為 memory 中的索引。您知道我該如何解決嗎?

當您運行 TASM 為您創建的 .EXE 時,執行從代碼段中的 label開始,CS 段寄存器指向它。 為了讓你的程序正確到function,同樣DS段寄存器應該指向你程序的數據段。 遺憾的是,默認情況下並非如此,因為 DS 指向程序段前綴 PSP。 您必須使用以下代碼自行設置 DS:

mov  ax, @data
mov  ds, ax

如果您選擇MODEL tiny (而不是MODEL small ),那么問題就不會出現,因為所有 4 個段寄存器都將彼此相等。


 xor cx,cx mov cx,8

在加載寄存器之前將寄存器清零是不必要的操作。

 jnc nc inc al nc:

盡管這個構造是正確的,但如果設置了進位,則遞增 AL 可以通過adc al, 0簡單得多。 如果進位標志清零,則不添加任何內容,如果進位標志已設置,則添加 1。

 and al,00000001h cmp al,0h

檢查一個值是否是偶數/奇數是通過查看你做得好的最低有效位來完成的。 重點是,您之后不需要cmp ,因為and指令已經定義了要用於分支的零標志。
更好的是,如果您使用test而不是and ,您將收到相同的零標志並且根本不會修改寄存器。 編寫test cl, 1將使您免於使用額外的寄存器。

 jz even_ jnz odd odd:

這個jnz條件跳轉沒有任何用處。 如果條件滿足則執行跳轉到奇數label,如果條件不滿足則執行跳轉到奇數label

 shr [t_copy],1

您可以通過處理來自寄存器而不是來自 memory 的數據來改進您的解決方案。您也不需要副本。

CODESEG
start:
    mov  ax, @data
    mov  ds, ax

    xor  cx, cx     ; CL is popcount, CH is a convenient 0
    mov  al, [TAV]
L1:
    shr  al, 1      ; The bit that comes out of AL
    adc  cl, ch     ;   is added to CL
    test al, al     ; If AL got empty, further adding would be useless
    jnz  L1
    test cl, 1      ; Non-destructive checking of the least significant bit
    jnz  ON
    shr  [TAV], cl  ; Shift right if popcount is EVEN
    jmp  exit               
ON:
    shl  [TAV], cl  ; Shift left if popcount is ODD
exit:

編輯:下面描述的這個錯誤實際上並不存在,我誤讀了代碼。

你很接近,但這里有一個小錯誤。 當您執行and al,1時,您實際上已經更改了al並且原始人口計數現在丟失了。 幸運的是,有一種簡單的方法可以解決這個問題,使用test al,1代替。 這會以and al,1相同的方式影響零標志,除了al保持與test之前相同。 所以試試這個,看看它是否有幫助:

    mov cl,al
    test al,1
    
    ;cmp al,0h ;this line is redundant.
    jz even_               
    ;jnz odd   ;this line is redundant.
    odd:
        shl [TAV],cl
        jmp exit
    even_:
        shr [TAV],cl

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM