while汇编语言循环

scd*_*dmb 3 c++ assembly

C++中有这样的代码:

#include <iostream>

int main(){
  int a = 4;
  while(a--){
    std::cout << (a + 1) << '\n';
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

以及g ++生成的汇编代码中主函数的相应代码:

.globl main
    .type   main, @function
main:
.LFB957:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    movl    $4, 28(%esp)    # int a = 4;
    jmp .L2
.L3:
    movl    28(%esp), %eax     # std::cout << (a + 1) << '\n';
    addl    $1, %eax
    movl    %eax, 4(%esp)
    movl    $_ZSt4cout, (%esp)
    call    _ZNSolsEi
    movl    $10, 4(%esp)
    movl    %eax, (%esp)
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c
.L2:
    cmpl    $0, 28(%esp)
    setne   %al
    subl    $1, 28(%esp)    # a = a - 1
    testb   %al, %al
    jne .L3
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE957:
    .size   main, .-main
Run Code Online (Sandbox Code Playgroud)

在下面的片段中使用了什么指令setne和testb?

 .L2:
        cmpl    $0, 28(%esp)
        setne   %al
        subl    $1, 28(%esp)    # a = a - 1
        testb   %al, %al
        jne .L3
Run Code Online (Sandbox Code Playgroud)

难道不是这样在循环中检查是否a不是零并跳转?

Jam*_*nze 5

while条件正式相当于:

while ( a -- != 0 )
Run Code Online (Sandbox Code Playgroud)

(省略比较是合法的混淆.)

编译器生成的代码进行比较a0,结果保存在寄存器中al,然后再递减a,然后测试该保存的结果.

  • @Tinctorius只是看代码,我假设没有优化.(通过优化,我希望变量`a`完全消失,它的值保存在寄存器中.并且肯定有更聪明的方法来生成代码:类似`sub a,1; jc`的想法.) (3认同)