簡體   English   中英

如何正確測試條件:je或jge

[英]how to test condition properly: je or jge

有時我會使用這種模式來迭代一些數組:

    mov [rsp+.r12], r12 ; Choose a register that calls inside the loop won't modify
    mov r12, -1
.i:
    inc r12
    cmp r12, [rbp-.array_size]
    je .end_i
    ; ... program logic ...
    jmp .i
.end_i:
    mov r12, [rsp+.r12]

我知道測試平等就足夠了,但是不應該對“更大或更平等”進行“安全”測試(防止出現這種情況)。

在這種情況下,應該使用je還是jge?

我問的是可以減少引入錯誤的可能性的具體技巧。

我一直很喜歡測試一個范圍而不是僅僅為了相等的想法,以防萬一意外翻轉或其他原因。 但是在x86 asm中,請記住, cmp/jge不能在Core2上進行 cmp/jge (在32位模式下),而cmp/je可以。 在我檢查了Agner Fog的microarch pdf文件並發現只有Core2而不是Nehalem之前,我認為這將更有意義,因為在2004年的64位模式下宏融合根本不起作用,核心2。 (后來的微體系結構沒有該限制,並且可以對越來越多的組合進行宏融合。)

根據計數器的不同,您通常可以完全不使用CMP進行遞減計數(dec / jnz)。 通常,您知道它不需要是64位的,因此可以使用dec esi / jnz或其他任何方式。 dec esi / jge可以用於簽名計數器,但是dec沒有設置CF,因此您不能(有用)使用JA。

您的循環結構中間有一個if() break ,結尾有一個jmp,對於asm來說不是慣用的。 正常情況是:

mov ecx, 100

.loop:             ; do{
    ;; stuff
    dec ecx
    jge .loop      ; }while(--ecx >= 0)

您可以使用jg僅使用正ecx重新啟動循環,即從100..1而不是100..0開始循環。

在循環中具有未采用的條件分支和未采用的無條件分支效率較低。


擴展討論中有關保存/恢復r12的注釋的討論:通常,您會執行以下操作:

my_func:
    ; push rbp
    ; mov  rbp, rsp      ; optional: make a stack frame

    push   rbx           ; save the caller's value so we can use it
    sub    rsp, 32       ; reserve some space

    imul   edi, esi, 11   ; calculate something that we want to pass as an arg to foo
    mov    ebx, edi       ; and save it in ebx
    call   foo
    add    eax, ebx       ; and use value.  If we don't need the value in rbx anymore, we can use the register for something else later.

    ...  ;; calculate an array size in ecx

    test   ecx, ecx                ; test for the special case of zero iterations *outside* the loop, instead of adding stuff inside.  We can skip some of the loop setup/cleanup as well.
    jz    .skip_the_loop

    ; now use rbx as a loop counter
    mov    ebx, ecx
.loop:
    lea    edi, [rbx + rbx*4 + 10]
    call   bar                     ; bar(5*ebx+10);
    ; do something with the return value?  In real code, you would usually want at least one more call-preserved register, but let's keep the example simple
    dec    ebx
    jnz    .loop
.skip_the_loop:

    add   rsp, 32         ; epilogue
    pop   rbx

    ;pop  rbp             ; pointless to use LEAVE; rsp had to already be pointing to the right place for POP RBX
    ret

請注意,我們是如何在功能內使用rbx的,但只保存/恢復一次。

暫無
暫無

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

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