2016-09-28 13 views
0

루아 코드를 gcc를 사용하여 C의 인라인 어셈블리로 변환하여 교육용으로 최소한의 루아 컴파일러를 작성했습니다."asm '에서 30 개 이상의 피연산자를 gcc로 인라인으로 assesmbly 사용하는 방법

잠시 후에 생성 된 출력이 C에서 선언 된 변수와 함수에 대한 피연산자가 더 길어지기 시작하면이 오류가 발생하기 시작했습니다.

test.c: In function ‘int main()’: 
test.c:100:6: error: more than 30 operands in ‘asm’ 
    ); 

내가 볼 수있는 유일한 정보를 인터넷 검색을

some gcc mailing list from 2008했지만, 그들은 (내가 관심이 아니에요)의 gcc를 재 컴파일을 제외하고 수정이 없었다고 말했다.

아이러니하게도 종종 30 피연산자가 없기 때문에이 오류가 발생합니다.

여기

// Standard functions 
void io_read(){} 
void io_write(){} 
void print(){} 
int main(){ 
    // Working vars decl 
    long _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7, _t8; 
    long factorial, i, n, x; 
    // Strings decl 
    const char* _s0 = "enter a number:"; 
    const char* _s1 = "*number"; 
    const char* _s2 = "factorial of "; 
    const char* _s3 = " is "; 
    asm("" // My inline asm code 
    : // Output symbols 
     [_s0] "+g" (_s0), 
     [_s1] "+g" (_s1), 
     [_s2] "+g" (_s2), 
     [_s3] "+g" (_s3), 
     [_t0] "+g" (_t0), 
     [_t1] "+g" (_t1), 
     [_t3] "+g" (_t3), 
     [_t4] "+g" (_t4), 
     [_t5] "+g" (_t5), 
     [_t6] "+g" (_t6), 
     [_t7] "+g" (_t7), 
     [_t8] "+g" (_t8), 
     [factorial] "+g" (factorial), 
     [i] "+g" (i), 
     [n] "+g" (n), 
     [x] "+g" (x) 
    : // Input symbols 
     [io_read] "r" (io_read), 
     [io_write] "r" (io_write), 
     [print] "r" (print) 
    : // Clobbers 
     "cc", "rax", "rbx", "rcx", "rdx" 
    ); 
} 

내 GCC 버전은 사전에 6.2.1 20160830

감사 인 (19 피연산자가 아직도 나에게 그 오류를 제공)을 최소한의 예입니다!

+1

변수를 다시 사용하거나 테이블 (배열)을 만들고이 배열에 오프셋을 사용하여 변수 (컴파일러에서 어셈블리 코드에 삽입 됨)를 가져옵니다. –

+2

인라인 조립품 대신 적절한 조립품을 방출하십시오. gcc는 인라인 어셈블리에 대해 30 개의 피연산자로 제한되며 그 제한을 제거하지 않을 계획입니다. – fuz

+6

C 코드를 생성하는 것이 디버그가 훨씬 쉽고 간단하지 않습니까? 그리고 Assmbler 파일을 직접 생성하지 않으시겠습니까? 불쾌감은 없지만 중급 C 단계는 나에게 헛소리처럼 보입니다. – Olaf

답변

1

문제에 대한 직접적인 해결책을 찾지 못했지만 Ross Ridge 덕분에 문제를 해결할 수있었습니다.

내가 처음 시도한 것은 가능하면 "g"를 "g"로 변경하는 것이 었습니다. 분명히 "+ g"는 두 개의 피연산자로 계산됩니다. 왜냐하면 읽기 + 쓰기가 가능하기 때문에 가능한 한 onces를 "g"로만 바꿀 수 있기 때문입니다.

또한 전역 범위로 이동 한 다음 "% [print] 호출"대신 "call print"로 직접 호출하여 피연산자로 함수를 완전히 제거 할 수있었습니다. 그러나 인라인 C에서만 작동하며 인라인 C++에서는 작동하지 않습니다.

나 같은 컴파일러를 작성하는 경우 인라인 어셈블리를 사용하지 않는 것이 좋습니다. 더 많은 문제가있는 것처럼 보입니다. 간단히 어셈블러에서 C 함수를 호출하는 것이 더 쉬울 것입니다. 인라인 C를 사용하여 더 큰 규모로 컴파일러를 만들지는 않을 것입니다.

EDIT : "m"과 "+ m"을 강요하기 시작했습니다. "g"를 사용하는 대신 스택에 강제로 변수가 잘 작동하는 것처럼 보입니다.

+0

' "= g"'는 쓰기 전용입니다. ' "g"'는 읽기 전용입니다. IDK 왜 당신은 인라인 asm을 전혀 출력하고 싶지. 그것은 끔찍한 생각처럼 보입니다. 순수한 C 나 순수한 asm을'main'을 정의하는'.s'에 출력하십시오. 내부 영역 asm에서 함수 호출을하는 것은 안전하지 않습니다. 왜냐하면 gcc에게 빨간색 영역을 clobber한다고 말할 수 없기 때문입니다. 함수 포인터를 인라인 asm에 대한 입력으로 사용하는 것은 실제 함수 포인터를 통해 레지스터 또는 메모리 간접 호출을하기 때문에 정말 끔찍한 일입니다. –

+0

''= m "'또는'"g = "'에 대한 언급을 빠뜨리지 만 출력은 쓰기 전용 일 때 사용해야합니다. gcc가 허용하는만큼 많은 +/= /'g' 피연산자를 사용하고 나머지는 +/= /'m'을 사용하는 것이 좋습니다. 왜냐하면 모든 것을 강제로 스택에 넣으면 쓰레기 asm이 생기기 때문입니다. (만약 당신이 이미 모든 레지스터를 clobber하고 할당을 스스로 등록한다면, 당신은'addl mem, mem' 또는 기타를 생성하는 것을 피할 필요가 있기 때문에 모든 것이 어쨌든 스택에있게 될 것입니다. 즉각적인 상수는 제외됩니다. 그래서 당신은 입력을 위해 여전히'g'를 사용하여 즉시를 허용해야합니다.) –