Windows64가 x86-64의 다른 모든 OS와 다른 호출 규칙을 사용하는 이유는 무엇입니까?


110

AMD에는 x86-64에서 사용할 호출 규칙을 설명하는 ABI 사양이 있습니다. 자체 x86-64 호출 규칙이있는 Windows를 제외하고 모든 OS가이를 따릅니다. 왜?

이 차이에 대한 기술적, 역사적 또는 정치적 이유를 아는 사람이 있습니까? 아니면 순전히 NIHsyndrome의 문제입니까?

나는 OS마다 더 높은 수준의 요구 사항이 다를 수 있음을 이해하지만, 예를 들어 Windows에서 레지스터 매개 변수 전달 순서가 rcx - rdx - r8 - r9 - rest on stack다른 모든 사람들이 rdi - rsi - rdx - rcx - r8 - r9 - rest on stack.

추신 : 이러한 호출 규칙이 일반적으로 어떻게 다른지 알고 있으며 필요한 경우 세부 정보를 찾을 수있는 위치를 알고 있습니다. 내가 알고 싶은 것은 이유 입니다.

편집 : 방법은 wikipedia 항목 과 링크를 참조하십시오 .


2
음, 첫 번째 레지스터의 경우 : rcx : ecx는 msvc __thiscall x86 규칙의 "this"매개 변수였습니다. 따라서 컴파일러를 x64로 쉽게 이식하기 위해 rcx를 처음으로 시작했습니다. 다른 모든 것도 달라진다는 것은 초기 결정의 결과 일뿐입니다.
Chris Becke

@Chris : 아래에 AMD64 ABI 보충 문서에 대한 참조 (실제 내용에 대한 설명)를 추가했습니다.
FrankH.

1
나는 MS에서 이론적 근거를 발견하지 않았습니다하지만 몇 가지 토론을 찾을 여기
phuclv

답변:


81

x64에서 4 개의 인수 레지스터 선택 -UN * X / Win64에 공통

x86에 대해 기억해야 할 사항 중 하나는 "reg number"인코딩에 대한 레지스터 이름이 명확하지 않다는 것입니다. 명령어 인코딩 측면에서 ( MOD R / M 바이트, http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm 참조 ) 레지스터 번호 0 ... 7은-순서대로- ?AX, ?CX, ?DX, ?BX, ?SP, ?BP, ?SI, ?DI.

따라서 반환 값으로 A / C / D (regs 0..2)를 선택하고 처음 두 인수 ( "고전적인"32 비트 __fastcall규칙)를 선택하는 것은 논리적 선택입니다. 64 비트로가는 것에 관해서는 "상위"regs가 주문되고 Microsoft와 UN * X / Linux 둘 다 첫 번째로 R8/ R9를 사용했습니다.

염두에 유지, 마이크로 소프트의 선택 RAX(반환 값) 및 RCX, RDX, R8, R9(인수 [0..3])를 선택하면 이해할 수있는 선택입니다 사 개 인수 레지스터.

AMD64 UN * X ABI가 RDX이전에 선택한 이유를 모르겠습니다 RCX.

x64에서 6 개의 인수 레지스터 선택 -UN * X 특정

RISC 아키텍처에서 UN * X는 전통적으로 레지스터에 인수 전달을 수행했습니다. 특히 처음 6 개의 인수 (최소한 PPC, SPARC, MIPS에서 그렇습니다)에 대해. AMD64 (UN * X) ABI 디자이너가 해당 아키텍처에서도 6 개의 레지스터를 사용하기로 선택한 주요 이유 중 하나 일 수 있습니다.

그래서 당신이 원하는 경우 여섯 개 에 인수를 전달하는 레지스터, 그리고 그것을 선택하는 논리이다 RCX, RDX, R8그리고 R9그들 중 네, 당신은 두 개의 다른 어떤을 선택해야합니까?

"높은"regs는 선택하기 위해 추가 명령어 접두사 바이트가 필요하므로 명령어 크기가 더 커지므로 옵션이있는 경우 선택하고 싶지 않을 것입니다. 때문에에 고전 레지스터의 암시 의 의미 RBPRSP이 사용할 수 없으며, RBX전통적으로 겉으로 AMD64 ABI 디자이너가 불필요하게 호환되고 싶지 않았다 UN * X (전역 옵셋 테이블)에 대한 특별 사용이 있습니다.
Ergo, 유일한 선택RSI/ RDI.

따라서 RSI/ RDI를 인수 레지스터로 가져와야한다면 어떤 인수 여야합니까?

그들을 arg[0]만들고 arg[1]몇 가지 장점이 있습니다. cHao의 의견을 참조하십시오.
?SI그리고 ?DI문자열 명령어 소스 / 대상 피연산자이며 cHao가 언급했듯이 인수 레지스터로 사용한다는 것은 AMD64 UN * X 호출 규칙에서 가장 간단한 strcpy()함수가 예를 들어 repz movsb; ret소스 / 대상 이 두 개의 CPU 명령어로만 구성 된다는 것을 의미합니다. 호출자가 주소를 올바른 레지스터에 넣었습니다. 특히 저수준 및 컴파일러 생성 "접착제"코드에 있습니다 (예를 들어 일부 C ++ 힙 할당자는 생성시 개체를 0으로 채우거나 커널에서 힙 페이지를 0으로 채우는 경우).sbrk(), 또는 copy-on-write pagefaults) 막대한 양의 블록 복사 / 채우기를 수행하므로 소스 / 대상 주소 인수를로드하는 두 개 또는 세 개의 CPU 명령을 저장하는 데 자주 사용되는 코드에 유용합니다. "올바른"레지스터.

따라서 UN * X와 Win64는 UN * X가 의도적으로 선택한 RSI/ RDI레지스터 에서 두 개의 추가 인수 RCXRDX, R8및 에서 4 개의 인수를 자연스럽게 선택하는 것에 "앞에 추가"한다는 점에서만 다릅니다 R9.

그 너머 ...

UN * X와 Windows x64 ABI 사이에는 인수를 특정 레지스터에 매핑하는 것보다 더 많은 차이점이 있습니다. Win64에 대한 개요는 다음을 확인하십시오.

http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx

Win64 및 AMD64 UN * X는 스택 스페이스가 사용되는 방식에서도 현저하게 다릅니다. 예를 들어 Win64에서 호출자 인수 0 ... 3이 레지스터에 전달 되더라도 함수 인수에 대한 스택 공간을 할당 해야합니다 . 반면에 UN * X에서 리프 함수 (즉, 다른 함수를 호출하지 않는 함수)는 128 바이트 이하의 스택 스페이스를 할당하는 데 전혀 필요하지 않습니다 (예, 소유하고 사용할 수 있습니다. 할당하지 않고 일정량의 스택 ... 음, 커널 코드가 아니라면 멋진 버그의 원인). 이 모든 것은 특정 최적화 선택이며, 이에 대한 대부분의 이론적 근거는 원본 포스터의 위키피디아 참조가 가리키는 전체 ABI 참조에 설명되어 있습니다.


1
레지스터 이름 정보 : 접두사 바이트가 요인이 될 수 있습니다. 그러나 MS가 rcx-rdx-rdi-rsi를 인수 레지스터로 선택하는 것이 더 논리적입니다. 그러나 처음부터 ABI를 설계하는 경우 처음 8 개의 숫자 값이 안내 할 수 있지만 완벽하게 우수한 ABI가 이미 존재하는 경우이를 변경할 이유가 없으므로 더 많은 혼란을 초래할뿐입니다.
JanKanis 2010

2
RSI / RDI에서 : 이러한 명령어는 일반적으로 인라인되며이 경우 호출 규칙은 중요하지 않습니다. 그렇지 않으면 시스템 전체에 해당 함수의 복사본이 하나 (또는 ​​몇 개) 만 있으므로 바이트 수만 절약 됩니다. 그럴 가치가 없어. 다른 차이점 / 호출 스택 : 특정 선택의 유용성은 ABI 참조에 설명되어 있지만 비교하지는 않습니다. 다른 최적화가 선택되지 않은 이유를 설명하지 않습니다. 예를 들어 Windows에 128 바이트 레드 존이없는 이유와 AMD ABI에 인수를위한 추가 스택 슬롯이없는 이유는 무엇입니까?
JanKanis 2010

1
@cHao : 아니요. 그러나 그들은 어쨌든 그것을 변경했습니다. Win64 ABI는 Win32 ABI와 다르며 (호환되지 않음) AMD의 ABI 와도 다릅니다.
JanKanis 2010

7
@Somejan : Win64와 Win32 __fastcall는 32 비트 이하의 인수가 2 개 이하이고 32 비트 이하의 값을 반환하는 경우 100 % 동일합니다. 그것은 작은 클래스의 기능이 아닙니다. i386 / amd64 용 UN * X ABI간에 이러한 역 호환성은 전혀 불가능합니다.
FrankH.

2
@szx : 2000 년 11 월부터 관련 메일 링리스트 스레드를 찾았고 그 이유를 요약 한 답변을 게시했습니다. 그것의주의 memcpy즉, 그런 식으로하지 구현 될 수있다 strcpy.
Peter Cordes 2016

42

Windows가 그들이 한 일을 한 이유 IDK. 추측에 대해서는이 답변의 끝을 참조하십시오. SysV 호출 규칙이 어떻게 결정되었는지 궁금 해서 메일 링리스트 아카이브를 파헤쳐 서 깔끔한 것을 찾았습니다.

AMD 아키텍트가 활발하게 활동하고 있었기 때문에 AMD64 메일 링리스트에서 오래된 쓰레드 중 일부를 읽는 것은 흥미 롭습니다. 예를 들어 레지스터 이름을 선택하는 것은 어려운 부분 중 하나였습니다. AMD 는 원래 8 레지스터 r0-r7의 이름을 바꾸거나UAX .

또한, 커널의 피드백은 원래의 설계했다 확인 된 것들 DEVS syscallswapgs사용할 수를 . 이것이 AMD가 실제 칩을 출시하기 전에 이것을 분류하기 위해 지침업데이트 한 방법 입니다. 2000 년 후반 인텔이 AMD64를 채택하지 않을 것이라는 가정도 흥미 롭습니다.


SysV (Linux) 호출 규칙과 호출자 보존 대 호출자 저장에 대한 레지스터 수에 대한 결정은 2000 년 11 월 Jan Hubicka (gcc 개발자)에 의해 처음에 이루어졌습니다 . 그는 SPEC2000을 컴파일 하고 코드 크기와 명령어 수를 조사했습니다. 그 토론 스레드는이 SO 질문에 대한 답변 및 의견과 동일한 아이디어 중 일부를 중심으로 튀어 나옵니다. 두 번째 스레드에서 그는 현재 시퀀스를 최적이며 최종적으로 제안하여 일부 대안보다 작은 코드를 생성 합니다.

그는 "글로벌"이라는 용어를 사용하여 푸시 / 팝해야하는 호출 보존 레지스터를 의미합니다.

의 선택 rdi, rsi, rdx처음 세 인수에 의해 동기가되었을 때 :

  • memset인수에 대한 다른 C 문자열 함수를 호출하는 함수에서 코드 크기를 약간 절약 합니다 (여기서 gcc는 rep 문자열 작업을 인라인합니까?).
  • rbxREX 접두사 (rbx 및 rbp)없이 액세스 할 수있는 두 개의 호출 보존 된 reg를 갖는 것이 승리이기 때문에 호출 보존됩니다. 어떤 명령에서도 암시 적으로 사용되지 않는 유일한 다른 reg이기 때문에 아마도 선택되었을 것입니다. (rep string, shift count, mul / div outputs / inputs touch all other all).
  • 특별한 목적을 가진 레지스터는 호출 보존되지 않으므로 (이전 포인트 참조) rep 문자열 명령어 나 가변 카운트 시프트를 사용하려는 함수는 함수 인수를 다른 곳으로 이동해야 할 수 있지만 저장할 필요는 없습니다. 발신자의 가치를 회복하십시오.
  • RCX는 EAX와 같은 특수한 목적으로 일반적으로 사용되는 레지스터이므로 시퀀스에서 누락되는 동일한 목적을 가지고 있으므로 시퀀스 초기에 RCX를 피하려고합니다. 또한 syscall에 사용할 수 없으며 가능한 한 함수 호출 시퀀스와 일치하도록 syscall 시퀀스를 만들고 싶습니다.

    (배경 : syscall/ sysret불가피하게 rcx(with rip) 및 r11(with RFLAGS) 파괴 하므로 커널이 실행 rcx되었을 때 원래 있던 내용을 볼 수 없습니다 syscall.)

커널 시스템 호출 ABI는 r10대신을 제외하고 함수 호출 ABI와 일치하도록 선택 rcx되었으므로 libc 래퍼 mmap(2)mov %rcx, %r10/ mov $0x9, %eax/ 와 같은 기능을 수행 할 수 있습니다 syscall.


i386 Linux에서 사용하는 SysV 호출 규칙은 Window의 32 비트 __vectorcall에 비해 짜증이납니다. 스택의 모든 것을 전달 edx:eax하고 작은 구조체가 아닌 int64에 대해서만 반환 합니다 . 그것과의 호환성을 유지하기 위해 약간의 노력을 기울인 것은 놀라운 일이 아닙니다. 그렇게하지 않을 이유가 없을 때, 그들은 rbx원래 8 (REX 접두사가 필요하지 않음)에 다른 것을 갖는 것이 좋다고 결정했기 때문에 통화 보존을 유지하는 것과 같은 일 을했습니다.

ABI를 최적으로 만드는 것은 다른 고려 사항보다 장기적으로 훨씬 더 중요합니다. 나는 그들이 꽤 잘했다고 생각합니다. 다른 regs의 다른 필드 대신 레지스터에 압축 된 구조체를 반환하는 것에 대해 완전히 확신하지 못합니다. 필드에서 실제로 작동하지 않고 값별로 전달하는 코드가이 방법으로이기는 것 같지만, 압축을 푸는 추가 작업은 어리석은 것 같습니다. 그것들은 단지보다 더 많은 정수 리턴 레지스터를 가질 수 있었으므로, rdx:rax4 개의 멤버가있는 구조체를 리턴하면 rdi, rsi, rdx, rax 등으로 리턴 될 수 있습니다.

SSE2는 정수에서 작동 할 수 있기 때문에 벡터 regs에서 정수 전달을 고려했습니다. 다행히 그들은 그렇게하지 않았습니다. 정수는 포인터 오프셋으로 자주 사용되며 스택 메모리로의 왕복 비용은 매우 저렴 합니다. 또한 SSE2 명령어는 정수 명령어보다 더 많은 코드 바이트를 사용합니다.


나는 Windows ABI 디자이너가 asm을 한 곳에서 다른 곳으로 포팅해야하는 사람들의 이익을 위해 32 비트와 64 비트 사이의 차이를 최소화하는 것을 목표로했을 수도 #ifdef있고, 같은 소스를 더 쉽게 구축 할 수 있도록 일부 ASM에서 몇 s를 사용할 수 있다고 생각합니다. 32 비트 또는 64 비트 버전의 함수.

툴체인의 변경을 최소화하는 것은 불가능 해 보입니다. x86-64 컴파일러에는 레지스터가 무엇에 사용되며 호출 규칙이 무엇인지에 대한 별도의 테이블이 필요합니다. 32 비트와 약간 겹치는 부분은 도구 체인 코드 크기 / 복잡성을 크게 절감 할 수 없습니다.


1
저는 Raymond Chen의 블로그에서 MS 측에서 벤치마킹 한 후 이러한 레지스터를 선택하는 이유에 대해 읽은 것 같습니다.하지만 더 이상 찾을 수 없습니다. 그러나 homezone에 관한 몇 가지 이유가 여기에 설명되어 있습니다. blogs.msdn.microsoft.com/oldnewthing/20160623-00/?p=93735 blogs.msdn.microsoft.com/freik/2006/03/06/…
phuclv


@phuclv : ESP 아래에 쓰는 것이 유효합니까? . 내 대답에 대한 Raymond의 의견은 x86 32/64 Windows에 현재 사실상의 위험 영역이없는 이유를 설명하는 몇 가지 SEH 세부 정보를 지적했습니다. 그의 블로그 게시물에는 내가 그 대답에서 언급 한 동일한 코드 페이지 인 처리기 가능성에 대한 몇 가지 그럴듯한 사례가 있습니다 :) 그래서 예, Raymond는 내가 한 것보다 더 잘 설명했습니다 (당연히 Windows에 대해 거의 알지 못했기 때문에). x86 이외의 레드 존 크기 표는 정말 깔끔합니다.
Peter Cordes 2019

13

Microsoft는 IA64 아키텍처에서 Intel과 강력한 파트너 였기 때문에 처음에는 "초기 AMD64 노력에 대해 공식적으로 헌신하지 않았습니다"( Matthew Kerner와 Neil Padgett의 "현대 64 비트 컴퓨팅의 역사" 에서 )를 기억하십시오. 이것이 의미하는 바는 그들이 Unix와 Windows에서 모두 사용하기 위해 ABI에서 GCC 엔지니어들과 함께 일할 수 있었을지라도 그렇게하지 않았을 때 AMD64 노력을 공개적으로 지원한다는 것을 의미하기 때문이라고 생각합니다. 아직 공식적으로 그렇게했습니다 (그리고 아마도 인텔을 화나게했을 것입니다).

게다가 그 당시 마이크로 소프트는 오픈 소스 프로젝트에 대해 전혀 관심이 없었습니다. 확실히 Linux 나 GCC는 아닙니다.

그렇다면 왜 그들은 ABI에 협력했을까요? ABI는 단순히 거의 동시에 그리고 분리되어 설계 되었기 때문에 다르다고 생각합니다.

"현대 64 비트 컴퓨팅의 역사"의 또 다른 인용문 :

마이크로 소프트 협업과 병행하여 AMD는 칩을 준비하기 위해 오픈 소스 커뮤니티에 참여했습니다. AMD는 도구 체인 작업을 위해 Code Sorcery 및 SuSE와 계약했습니다 (Red Hat은 이미 IA64 도구 체인 포트에서 Intel에 의해 계약되었습니다). Russell은 SuSE가 C 및 FORTRAN 컴파일러를 생성하고 Code Sorcery가 Pascal 컴파일러를 생성했다고 설명했습니다. Weber는 회사가 Linux 포트를 준비하기 위해 Linux 커뮤니티와도 협력했다고 설명했습니다. 이 노력은 매우 중요했습니다. Microsoft가 AMD64 Windows 노력에 지속적으로 투자 할 수있는 인센티브 역할을했으며, 당시 중요한 OS가되었던 Linux를 칩이 출시되면 사용할 수 있도록 보장했습니다.

Weber는 Linux 작업이 AMD64의 성공에 절대적으로 중요하다고 말합니다. AMD가 필요한 경우 다른 회사의 도움 없이도 엔드 투 엔드 시스템을 생산할 수 있었기 때문입니다. 이 가능성은 다른 파트너가 물러나더라도 AMD가 최악의 생존 전략을 가지고 있음을 보장했으며, 결국 다른 파트너는 자신에게 뒤처 질 까봐 두려웠습니다.

이것은 AMD조차도 MS와 Unix 간의 협력이 반드시 가장 중요하다고 생각하지 않았지만 Unix / Linux 지원이 매우 중요하다는 것을 나타냅니다. 타협하거나 협력하도록 한쪽 또는 양쪽을 설득하려는 시도조차도 그들 중 하나를 짜증나게하는 노력이나 위험 (?)의 가치가 없었을까요? 아마도 AMD는 공통 ABI를 제안하는 것조차 단순히 칩이 준비되었을 때 소프트웨어 지원을 준비하는 더 중요한 목표를 지연 시키거나 탈선시킬 수 있다고 생각했을 것입니다.

제 생각에는 추측이지만 ABI가 다른 주된 이유는 MS와 유닉스 / 리눅스 측이 함께 작동하지 않았고 AMD가 그것을 문제로 보지 않은 정치적 이유 때문이라고 생각합니다.


정치에 대한 좋은 관점. AMD의 잘못이나 책임이 아니라는 데 동의합니다. 더 나쁜 호출 규칙을 선택한 것에 대해 Microsoft를 비난합니다. 그들의 호출 규칙이 더 나은 것으로 판명 되었다면 나는 약간의 동정심을 가질 것입니다. 그러나 그들은 초기 ABI 에서 스택을 __vectorcall넘기는 것이 좋지 않았기 때문에 변경해야했습니다 __m128. 일부 벡터 regs의 낮은 128b에 대해 호출 보존 의미 체계를 갖는 것도 이상합니다 (원래 SSE를 사용하여 확장 가능한 저장 / 복원 메커니즘을 설계하지 않았으나 AVX를 사용하지 않은 부분에 대한 인텔의 잘못입니다.)
Peter Cordes

1
저는 ABI가 얼마나 좋은지에 대한 전문 지식이나 지식이 없습니다. 가끔 어셈블리 수준에서 이해 / 디버그 할 수 있도록 그들이 무엇인지 알아야합니다.
마이클 버

1
좋은 ABI는 코드 크기와 명령어 수를 최소화하고 메모리를 통한 추가 왕복을 방지하여 종속성 체인의 지연 시간을 낮게 유지합니다. (args 또는 흘리거나 다시로드해야하는 지역의 경우). 장단점이 있습니다. SysV의 red-zone은 한곳 (커널의 신호 처리기 디스패처)에서 몇 가지 추가 명령을 사용하여 일부 스크래치 공간을 얻기 위해 스택 포인터를 조정할 필요가없는 리프 함수에 비교적 큰 이점을 제공합니다. 그래서 그것은 거의 제로에 가까운 하락세로 분명한 승리입니다. SysV 용으로 제안 된 후 거의 논의없이 채택되었습니다.
피터 코르

1
@dgnuff : 맞습니다. Why ca n't kernel code use a Red Zone에 대한 답변 입니다. 인터럽트는 CPU가 사용자 공간 코드를 실행할 때 도착하더라도 사용자 공간 스택이 아닌 커널 스택을 사용합니다. 커널은 사용자 공간 스택을 신뢰하지 않습니다. 동일한 사용자 공간 프로세스에있는 다른 스레드가이를 수정할 수 있으므로 커널을 제어 할 수 있습니다!
Peter Cordes 2018 년

1
@ DavidA.Gray : 네, ABI 당신이 말을하지 않는 최적화 된 코드는 일반적으로하지 않도록 프레임 포인터로 RBP을 사용 (기능을 제외하고 그 사용 alloca또는 약간 다른 경우). gcc -fomit-frame-pointerLinux에서 기본값으로 사용하는 데 익숙한 경우 이는 정상 입니다. ABI는 예외 처리가 계속 작동하도록 허용하는 스택 해제 메타 데이터를 정의합니다. (나는 그것이 GNU / Linux x86-64 System V의 CFI 물건과 같이 작동한다고 가정합니다 .eh_frame). gcc -fomit-frame-pointerx86-64에서 영원히 이후 기본값 (최적화 사용 가능)이었으며 다른 컴파일러 (예 : MSVC)도 동일한 작업을 수행합니다.
Peter Cordes

12

Win32는 ESI 및 EDI를 자체적으로 사용하며 수정하지 않아야합니다 (또는 적어도 API를 호출하기 전에 복원해야 함). 64 비트 코드가 RSI 및 RDI와 동일한 작업을 수행한다고 생각합니다. 따라서 함수 인수를 전달하는 데 사용되지 않는 이유가 설명됩니다.

하지만 RCX와 RDX가 왜 바뀌 었는지 말할 수 없었습니다.


1
모든 호출 규칙에는 일부 레지스터가 스크래치로 지정되고 일부는 Win64의 ESI / EDI 및 RSI / RDI와 같이 보존됩니다. 그러나 그것들은 범용 레지스터이며, 마이크로 소프트는 그것들을 다르게 사용하기 위해 문제없이 선택할 수있었습니다.
JanKanis 2010

1
@Somejan : 물론입니다. 전체 API를 다시 작성하고 두 개의 다른 OS를 갖고 싶다면. 그래도 "문제없이"라고 부르지는 않을 것입니다. 지금까지 수십 년 동안 MS는 x86 레지스터로 무엇을 할 것인지,하지 않을 것인지에 대해 확실한 약속을 해왔으며 그동안 어느 정도 일관성이 있고 호환이 가능했습니다. 그들은 AMD의 일부 칙령, 특히 "프로세서 구축"영역 밖에있는 임의의 칙령 때문에 모든 것을 창 밖으로 던지지 않을 것입니다.
cHao

5
@Somejan : AMD64 UN * X ABI는 항상 정확히 UNIX에 특화된 부분이었습니다. x86-64.org/documentation/abi.pdf 문서의 제목은 System V Application Binary Interface, AMD64 Architecture Processor Supplement 입니다. (공통) UNIX ABI (다중 볼륨 컬렉션, sco.com/developers/devspecs ) 는 특정 프로세서에 대한 함수 호출 규칙 및 데이터 레이아웃 규칙 인 프로세서 별 장 3- 부록 - 섹션을 남깁니다 .
FrankH.

7
@Somejan : Microsoft Windows는 특별히 UN * X에 가까워 지려고 한 적이 없으며 Windows를 x64 / AMD64로 이식 할 때 자체 __fastcall 호출 규칙 을 확장하기로 선택했습니다 . 당신은에서 Win32 / Win64를가 호환되지 않는 주장하지만, 자세히 보면 :받는 함수를 들어 두 개의 32 비트 인수 및 반환 32 비트를,의 Win64 및 Win32는 __fastcall실제로 있는 100 % 호환 (두 개의 32 비트 인수, 같은 반환 값을 전달하는 같은 사무 처리 규정). 일부 바이너리 (!) 코드도 두 작동 모드에서 모두 작동 할 수 있습니다. UNIX 측은 "오래된 방식"으로 완전히 무너졌습니다. 좋은 이유가 있지만 휴식은 휴식입니다.
FrankH.

2
@Olof : 단순한 컴파일러가 아닙니다. NASM에서 독립형 작업을 할 때 ESI와 EDI에 문제가있었습니다. Windows는 확실히 이러한 레지스터에 관심이 있습니다. 그러나 예, 저장하기 전에 저장하고 Windows에서 필요로하기 전에 복원하면 사용할 수 있습니다.
cHao
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.