汇编代码 - 循环中的 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)
对c
和b
的最低有效位执行异或,将结果存储在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$
我有这个汇编代码,其中有一个 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)
对c
和b
的最低有效位执行异或,将结果存储在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$