C++에서 16 비트 (말장난 의도) 코드를 작성하고 G ++로 컴파일합니다. 여기에서 컴파일하는 컨텍스트에 대한 자세한 내용 : Force GCC to push arguments on the stack before calling function (using PUSH instruction)GCC에서 레지스터를 밀어 넣기 전에 레지스터에 GCC를 묻습니다.
현재 직면하고있는 문제는 내 개체 파일을 연결할 때 LD가 throw되는 오류와 관련되어 있습니다. (작성 어셈블리의 관련 부분)이 번역 할 -S와 -mno-축적 출사-인수 옵션 G ++와 어셈블리 코드에서
asm(".code16gcc\n");
void f(const char*);
int main(){
f("A constant string put in section .rodata at link-time");
}
void f(const char* s){ }
: : 특히, 여기에 코드 상황이다
/APP
.code16gcc
.section .rodata
.LC0:
.string "A constant string put in section .rodata at link-time"
main:
.LFB0:
/* here would be main's prologue, not put because it ain't relevant */
// THIS IS THE CALL f("A constant string put in section .rodata at link-time");
push OFFSET FLAT:.LC0
call _Z1fPKc
이 응용 프로그램은 내가 개발중인 OS의 일부입니다. 특히 부트 로더는이 코드를 BIOS 메모리의 주소 0x70D00에로드합니다. 그러면 .rodata의 주소가 0x70D00보다 커집니다. GCC에는 순수한 16 비트 코드에 대한 지원 기능이 내장되어 있지 않으므로 'OFFSET FLAT : .LC0'을 실행하면 PURE 16 비트 조건에서 단어를 푸시한다는 것을 알 수 없습니다. 즉, .rodata의 주소가 - 0x70DAA 인 경우 명령은 'push 0x70DAA'가됩니다. 링커가 오류가 발생 이유입니다 : 기능에서
main': relocation truncated to fit: R_386_16 against
.rodata '
/APP
.code16gcc
.section .rodata
.LC0:
.string "A constant string put in section .rodata at link-time"
main:
.LFB0:
/* here would be main's prologue, not put because it ain't relevant */
// THIS IS THE CALL f("A constant string put in section .rodata at link-time"); , now using EAX before pushing the string literal's offset in .rodata
mov eax, OFFSET FLAT:.LC0 // move in eax instead
push eax // and push eax!
call _Z1fPKc
일부 상황에서는 MSVC이 최적화됩니다. 나는 GCC가 똑같은 일을하도록 강제하는 방법이 있는지 궁금해서 ... 분명히 작동 할 수있는 대안 중 하나는 속성 ((regparm (N)))을 함수 f에 연결하는 것입니다. 하지만 이것은 실제로 좋은 대안이 아닙니다. 스택의 레지스터를 f에서 직접 사용하는 것이 아니라 실제로 레지스터를 푸시하는 것이 아니므로 모든 기능에 대해이 작업을 수행 할 수 없습니다. 당신은 짧은 구글 검색을 수행하여 이것에 대해 더 많은 것을 알 수 있으며 필요한 경우이 옵션이 무엇을하는지 정확히 게시하고 왜 실제로는 효과가 없는지 게시 할 것입니다. 그러나이 질문 - 포스트는 너무 길어지기 시작합니다.
간단히 말해서, 내 질문은 : GCC에게 MOV로 함수에 전달 된 인수를 푸시하기 전에 레지스터에 요청할 수 있습니까?
미리 감사드립니다.