2010-02-27 3 views
2

다시 한 번 MinGW 인라인 어셈블리로 작업합니다.MinGW 인라인 어셈블리의 "오류 : 알 수없는 레이블로 역방향 참조 ..."

#include <stdio.h> 

int foobar(int); 

int main(){ 
int n = 0; 
printf("Number: "); 
scanf("%d", &n); 
printf("\n%d",foobar(n)); 
return 0; 
} 

int foobar(int num){ 
int result = 0; 
asm(".intel_syntax noprefix\n"); 
asm("mov eax, num\n"); 
asm("add eax, 110b\n"); 
asm("sub eax, 2\n"); 
    asm("mov result, eax\n"); 
return result; 
} 

그것을 컴파일

C:\Users\Andre\Codes>gcc asmtest.c -o asmtest -masm=intel

아야, 오류가 : 여기에 잘못된 무엇

C:\Users\Andre\AppData\Local\Temp\ccqny4yb.s: Assembler messages: C:\Users\Andre\AppData\Local\Temp\ccqny4yb.s:53: Error: backward ref to unknown label "110:"

? 내 코드가 이미 유효하다고 생각해?

+0

알 수없는 경우 어떻게 이전 버전인지 어떻게 알 수 있습니까? – bmargulies

답변

1

GCC는 AT & T 스타일 어셈블리에서 가장 잘 작동하며 GAS는 모든 Intel 구문을 구현하지 않습니다. 귀하의 즉각적인 문제는 숫자로 해석되지 않는 110b에서 오는 것이지만 그 전부는 아닙니다.

GCC의 인라인 어셈블러 구문에서 직접 변수를 참조 할 수 없습니다. 당신은 (기본 -masm=att 사용)처럼 작성해야 :

int foobar(int num) { 
    int result; 
    asm("mov %1, %%eax\n\t" 
     "add $6, %%eax\n\t" 
     "sub $2, %%eax\n\t" 
     "mov %%eax, %0" 
     : "=g" (result) 
     : "g" (num) 
     : "eax", "cc"); 
    return result; 
} 

를 첫 번째 콜론 출력 피연산자의 쉼표로 구분 된 목록이 후. "=g" (result)이 첫 번째 제약이므로 result은 별칭 %0을 얻습니다. "=g"은 GCC에 %0이 범용 레지스터 또는 메모리가 될 수 있음을 나타냅니다. (= 대신에 대신에 GCC는 동일한 목적으로 여러 레지스터를 재사용하기로 결정할 수 있으므로 모든 방법이 사용되는 방식을 정확하게 알려야합니다.)

두 번째 콜론 뒤에는 쉼표로 구분 된 입력 피연산자 목록 "g" (num)이 두 번째 제약 조건이므로 num은 별칭 %1을 얻습니다. "g"은 읽기 전용임을 의미합니다.

세 번째 콜론 뒤에는 쉼표로 구분 된 clobbers 목록이 있습니다. 이것은 GCC가 인라인 어셈블리를 통해 유지하고있는 정보를 다시로드해야하므로 인라인 어셈블리가 이러한 레지스터/메모리를 입력 또는 출력하지 않아도 변경할 수 있음을 GCC에 알려줍니다. 여기서 우리는 분명히 %eax을 변경하고 조건 코드 (플래그) 레지스터는 add/sub의 영향을받습니다. 컴파일러가 생성 조립체에

룩은 :

 
$ cc -S -o- -m32 asmtest.c | sed -n /globl.foobar/,/-foobar/p 
.globl foobar 
     .type foobar, @function 
foobar: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $16, %esp 
#APP 
# 15 "asmtest.c" 1 
     mov 8(%ebp), %eax 
     add $6, %eax 
     sub $2, %eax 
     mov %eax, -4(%ebp) 
# 0 "" 2 
#NO_APP 
     movl -4(%ebp), %eax 
     leave 
     ret 
     .size foobar, .-foobar 

컴파일러는 직접 numresult의 적층 위치를 사용하기로 결정 하였다. :"=g":"g" (레지스터 또는 메모리 위치를 허용) 대신 :"=r":"r" 제약 조건 (레지스터 만 허용 함)을 사용하면 컴파일러는 인라인 어셈블리 전후에 레지스터간에/레지스터를 복사합니다. 당신이 정말로, 인텔 구문을 사용하여 별도의 .s 소스 파일에 넣어 NASM 독립적를 조립하려면

 
$ cc -S -o- -m32 asmtest.c | sed -n /globl.foobar/,/-foobar/p 
.globl foobar 
     .type foobar, @function 
foobar: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $16, %esp 
     movl 8(%ebp), %edx 
#APP 
# 15 "asmtest.c" 1 
     mov %edx, %eax 
     add $6, %eax 
     sub $2, %eax 
     mov %eax, %edx 
# 0 "" 2 
#NO_APP 
     movl %edx, -4(%ebp) 
     movl -4(%ebp), %eax 
     leave 
     ret 
     .size foobar, .-foobar 

후 함께 개체를 연결합니다.

 
$ cat asmtest.c 
#include <stdio.h> 

int foobar(int); 
/* int foobar(int) __attribute__((fastcall)); */ 

int main() { 
    int n = 0; 
    printf("Number: "); 
    scanf("%d", &n); 
    printf("%d\n", foobar(n)); 
    return 0; 
} 
$ cat foobar.s 
global foobar 
foobar: 
     mov eax,[esp+4] # take this line out if C prototype is marked fastcall 
     sub eax,110b 
     add eax,2 
     ret 
$ nasm -f elf foobar.s 
$ cc -m32 asmtest.c foobar.o 
$ ./a.out 
Number: 30 
26 

(-f elf Windows 용 정확하지 않지만. 어쩌면 -f win32? 그리고 때문에 윈도우의 어리 석음에, 당신은 어셈블리의 이름 _foobar을 사용 할 수 있습니다.)

+0

많은 감사. 그거야. 이제 GCC가 % 0이 결과의 별칭임을 알 수 있으며 % 1은 num의 별칭입니다. 나는 아직도 그것을 얻지 않는다. 그런데이 세 줄은 무엇을 의미합니까? : "= g"(결과) : "g"(숫자) : "eax"); – anta40

+0

@ anta40 추가 세부 정보가 추가되었습니다. 하지만 실제로는 GCC 매뉴얼의 전체 http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html 섹션을 읽어야합니다. – ephemient