2012-08-24 2 views
3

나는 C로 프로그램을 작성하고 팔 어셈블리로 변환했다. 이제 어셈블리 코드에서 생성 된 일부 명령어를 이해하는 데 문제가있다. C 프로그램의 일부이다 : I는 GNU 팔 툴 체인을 사용하여 어셈블리 코드 아암이 C 코드로 변환 한C to arm assembly code conversion

#define MAX_DIGIT 1024 
int main() 
{ 
    int fd[MAX_DIGIT]; 
    int xLen = 0; 
    int sd[MAX_DIGIT]; 
    int yLen = 0; 

    int result[6*MAX_DIGIT]; 

    // Take input for two numbers 
    takeInput(fd, &xLen); 
    takeInput(sd, &yLen); 
     ... 
     ... 
     ... 
} 
... 
... 
... 

void takeInput(int digit[], int *length) 
{ 
    char c; 
    if((c=getchar()) != '\n' && *length <= MAX_DIGIT){ 
     takeInput(digit, length); 
     digit[*length] = c - '0'; 
     (*length)++; 
    }else return; 
} 

. 생성 된 어셈블리 코드의 일부는 다음과 같습니다.

main: 
    @ args = 0, pretend = 0, frame = 32788 
    @ frame_needed = 1, uses_anonymous_args = 0 
    mov ip, sp 
    stmfd sp!, {fp, ip, lr, pc} 
    sub fp, ip, #4 
    sub sp, sp, #32768 
    sub sp, sp, #20  @Why subtracted 20? 

    mvn r3, #4096 
    sub r3, r3, #3 
      @What r3 storing and Why took NOT of r3 and again subtract 3 from it? 
    mov r2, #0 
    sub r0, fp, #12 
    str r2, [r0, r3] 
    mvn r3, #8192 
    sub r3, r3, #7 
    mov r2, #0 
    sub r1, fp, #12 
    str r2, [r1, r3] 
    sub r2, fp, #4096 
    sub r2, r2, #12 
    sub r3, fp, #4096 
    sub r3, r3, #12 
    sub r3, r3, #4 
    mov r0, r2 
    mov r1, r3 
    bl takeInput 
    sub r2, fp, #8192 
    sub r2, r2, #12 
    sub r2, r2, #4 
    sub r3, fp, #8192 
    sub r3, r3, #12 
    sub r3, r3, #8 
    mov r0, r2 
    mov r1, r3 
    bl takeInput 
    mvn r3, #32768 
    sub r3, r3, #11 
    mov r2, #1 
    sub ip, fp, #12 
    str r2, [ip, r3] 

주석에 어셈블리 코드 자체를 표시했습니다. 감사.

답변

6

직접 변수 (명령어의 일부로 인코딩 된 상수)는 인코딩하는 필드가 몇 비트 밖에 없기 때문에 특정 값만 가질 수 있습니다. 컴파일러가 즉시 값으로 인코딩 할 수없는 값으로 레지스터를로드하려고하면 값의 일부를로드 한 다음 산술을 사용하여 값을 완료합니다.

다른 ARM 명령어에는 여러 가지 즉석 값의 인코딩이 있지만 여기에는 ARM 아키텍처 참조 문서, ARMv7-A 및 ARMv7-R 버전의 예제가 있습니다. "ARM 명령어의 수정 된 상수"는 12 비트로 인코딩됩니다. 4 비트는 회전을 지정하고 8 비트는 값의 리터럴 비트입니다. 4 비트는 2 진수 숫자를 형성하고 회전 수는 오른쪽 숫자의 2 배입니다. 예를 들어, 4 비트가 0011 인 경우 (즉, 3 인 경우), 회전 양은 6 비트입니다.

따라서 4 개의 회전 비트가 0011이고 8 개의 리터럴 비트가 10011101 인 경우 값은 10011101을 32 비트 필드 내에서 6 비트 오른쪽으로 회전하여 형성됩니다. 그래서 0000 0000 0000 0000 0000 0000 1001 1101은 오른쪽으로 6 비트 회전하여 0110 0100 0000 0000 0000 0000 0000 0010 또는 0x64000002를 생성합니다.

분명히 12 비트는 가능한 모든 32 비트 값을 인코딩 할 수 없습니다. 컴파일러가 원하는 값 중 하나는 32748이며 0x7fec입니다. 어느 위치에서든 8 비트에서 0x7fec을 생성 할 수는 없습니다 (또는 짝수 인덱싱 된 위치).

+0

여기에도 좋은 설명이 있습니다. http://www.davespace.co.uk/arm/introduction-to-arm/immediates.html –