2016-09-12 2 views
0

나는이 어셈블리 코드에 for 루프가있어서 C 코드로 다시 변경해야한다. 그러나 루프에 xor가 있음을 알았습니다.어셈블리 코드 - 루프의 xor는 어떻게 작동합니까?

.L3: 
     movq -8(%rbp), %rax  
     andl $1, %eax  
     xorl %eax, -12(%rbp)  
     sarq -8(%rbp)   
.L2: 
     cmpq $0, -8(%rbp)   
     jg  .L3   

그래서 for 루프는 0보다 크고 모든 루프마다 2로 나누는 루프입니다. 하지만 내가 겪고있는 것은 andl과 xorl입니다. 나는 그것들이 1을 체크하고, eax가 and를 가지고 그것들의 값에 따라 1이나 0을 반환한다는 것을 알지만, 루프에 의해 xor가 어떻게 변경 될 것인가?

+0

[논리 게이트 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

+0

Eww, 왜 모든 메모리 피연산자입니까?RBP의 포인터 증가가 보이지 않기 때문에 IDK는 모든 코드에 레지스터를 사용하지 않습니다. 'gcc -O0'에서 온 것으로 가정합니다 : ( –

답변

2

로컬 변수 b-8(%rbp)이고 로컬 변수 c-12(%rbp)이라고 가정 해 봅시다.

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

b의 최하위 비트의 값으로 eax의 값을 설정합니다.

xorl %eax, -12(%rbp) 

수행 배타적 또는 c의 결과를 저장하고 cb의 최하위 비트와. 2에 의해

sarq -8(%rbp) 

나누기 b.

cmpq $0, -8(%rbp) 
jg  .L3 

것은 b0보다 큰 경우 그렇지 않은 경우, 루프의 시작 계속 돌아갑니다.

그래서 해당하는 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$ 
+0

불필요한 코드를 포함하지 말라는 말을 들었 기 때문에 처음에는 포함시키지 않았다고 말했지만, 메인에서 L2로 점프하라는 요청이있었습니다. 어떻게 b % 1이 작동합니까? ? 그냥 작은 비트를 비교할 것입니까? –

+0

'b & 1'은 그냥 일반적인 비트 단위 AND이고'b'는 홀수,'b'는 짝수이면'0'이됩니다. –

+0

예를 들어 주셔서 감사합니다 ! –

관련 문제