로컬 변수 b
이 -8(%rbp)
이고 로컬 변수 c
이 -12(%rbp)
이라고 가정 해 봅시다.
.L3: movq -8(%rbp), %rax
andl $1, %eax
는
b
의 최하위 비트의 값으로
eax
의 값을 설정합니다.
xorl %eax, -12(%rbp)
수행 배타적 또는 c
의 결과를 저장하고 c
b
의 최하위 비트와. 2
에 의해
sarq -8(%rbp)
나누기 b
.
cmpq $0, -8(%rbp)
jg .L3
것은 b
이 0
보다 큰 경우 그렇지 않은 경우, 루프의 시작 계속 돌아갑니다.
그래서 해당하는 C 코드는 다음 .L2
라벨의 존재를 알 수
do {
c ^= (b & 1);
b /= 2; // Or: b >>= 1;
} while (b > 0);
있지만 jmp .L2
가있을 수 있습니다 직전, 당신은 어떤 경우에이 while
이 될 것입니다, 저희에게 표시되지중인 루프 :
while (b > 0) {
c ^= (b & 1);
b /= 2; // Or: b >>= 1;
}
작업 증명 (OS X에 사용하는 가스 어셈블러)
012 3,:
.globl _asm_func
.text
_asm_func:
push %rbp
mov %rsp, %rbp
sub $16, %rsp
movq %rdi, -8(%rbp)
movl %esi, -12(%rbp)
jmp .L2
.L3:
movq -8(%rbp), %rax
andl $1, %eax
xorl %eax, -12(%rbp)
sarq -8(%rbp)
.L2:
cmpq $0, -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
출력 :
[email protected]:~/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
[email protected]:~/src/sandbox/so_asm$
[논리 게이트 AND/OR/XOR/NOT/... ] (http://whatis.techtarget.com/defini 로직 - 게이트 - AND - OR - XOR - NOT - NAND - NOR - 및 - XNOR) ... 그래서 x86'mov al, 0b1010''xor al, 0b0011'은'al' ='0b1001' . ... 그리고 al, 0b0011'은 xor 대신'al' ='0b0010'을 생성합니다. '또는 al, 0b0011'은'al' ='0b1011'을 생성합니다. 'not '은'al' ='0b11110101'으로 끝날 것입니다. (다른 예제에서는 더 높은 4 비트의 0을 쓰지 않았지만'not'도 뒤집 힙니다.) (더 나은보기를 위해 서로 위에 값을 쓰고 "gate"기사와 비교하십시오) – Ped7g
Eww, 왜 모든 메모리 피연산자입니까?RBP의 포인터 증가가 보이지 않기 때문에 IDK는 모든 코드에 레지스터를 사용하지 않습니다. 'gcc -O0'에서 온 것으로 가정합니다 : ( –