汇编代码 - 循环中的 xor 如何工作?

Assembly Code - How does xor in a loop works?

我有这个汇编代码,其中有一个 for 循环,我要将其改回 C 代码。但是,我注意到循环中有一个 xor。

.L3:
        movq    -8(%rbp), %rax      
        andl    , %eax    
        xorl    %eax, -12(%rbp)     
        sarq    -8(%rbp)        
.L2:
        cmpq    [=10=], -8(%rbp)        
        jg      .L3         

所以我知道一个for循环只要大于0,每次循环除以2,就会一直循环下去。但我遇到的麻烦是 andl 和 xorl。我知道它会检查 1 和 eax 以及 and 和 returns 1 或 0,具体取决于它们的值,但是 xor 将如何被循环更改?

假设局部变量 b 位于 -8(%rbp),局部变量 c 位于 -12(%rbp)

.L3:    movq    -8(%rbp), %rax
        andl    , %eax

eax的值设置为b的最低有效位的值。

xorl    %eax, -12(%rbp) 

cb的最低有效位执行异或,将结果存储在c中。

sarq    -8(%rbp)

b 除以 2

cmpq    [=13=], -8(%rbp)
jg      .L3

如果 b 大于 0 则返回循环开始,否则继续。

所以对应的C代码为:

do {
    c ^= (b & 1);
    b /= 2;           //  Or: b >>= 1;
} while ( b > 0 );

虽然 .L2 标签的存在表明紧接在前面可能有一个 jmp .L2,但您没有向我们展示,在这种情况下它将是一个 while 循环:

while ( b > 0 ) {
    c ^= (b & 1);
    b /= 2;           //  Or: b >>= 1;
}

工作演示(在 OS X 上使用 gas 汇编程序):

asm_func.S:

.globl  _asm_func

.text

_asm_func:
    push    %rbp
    mov     %rsp, %rbp
    sub     , %rsp

    movq    %rdi, -8(%rbp)
    movl    %esi, -12(%rbp)

    jmp     .L2

.L3:
    movq    -8(%rbp), %rax
    andl    , %eax
    xorl    %eax, -12(%rbp)
    sarq    -8(%rbp)

.L2:
    cmpq    [=16=], -8(%rbp)
    jg      .L3

    movl    -12(%rbp), %eax

    leave
    ret 

main.c:

#include <stdio.h>

int asm_func(int b, int c);

int c_func(int b, int c)
{
    while ( b > 0 ) {
        c ^= (b & 1);
        b >>= 1;
    }
    return c;
}

int main(void)
{
    for ( int i = 112; i < 127; i += 7 ) {
        for ( int j = 203; j > 182; j -= 9 ) {
            printf("C function  (%d, %d): %d\n", i, j, c_func(i, j));
            printf("Asm function(%d, %d): %d\n", i, j, asm_func(i, j));
        }
    }
    return 0;
}

Makefile:

prog: main.o asm_func.o
    cc -o prog main.o asm_func.o

main.o: main.c
    cc -o main.o main.c -c -std=c99 -pedantic -Wall -Wextra

asm_func.o: asm_func.S
    as -o asm_func.o asm_func.S

输出:

paul@horus:~/src/sandbox/so_asm$ ./prog
C function  (112, 203): 202
Asm function(112, 203): 202
C function  (112, 194): 195
Asm function(112, 194): 195
C function  (112, 185): 184
Asm function(112, 185): 184
C function  (119, 203): 203
Asm function(119, 203): 203
C function  (119, 194): 194
Asm function(119, 194): 194
C function  (119, 185): 185
Asm function(119, 185): 185
C function  (126, 203): 203
Asm function(126, 203): 203
C function  (126, 194): 194
Asm function(126, 194): 194
C function  (126, 185): 185
Asm function(126, 185): 185
paul@horus:~/src/sandbox/so_asm$