Tại sao Windows64 sử dụng quy ước gọi khác với tất cả các hệ điều hành khác trên x86-64?


110

AMD có đặc tả ABI mô tả quy ước gọi để sử dụng trên x86-64. Tất cả các hệ điều hành đều tuân theo nó, ngoại trừ Windows có quy ước gọi x86-64 riêng. Tại sao?

Có ai biết lý do kỹ thuật, lịch sử hoặc chính trị cho sự khác biệt này hay đó hoàn toàn là vấn đề của Hội chứng NIH?

Tôi hiểu rằng các hệ điều hành khác nhau có thể có nhu cầu khác nhau cho những thứ cấp cao hơn, nhưng điều đó không giải thích tại sao ví dụ: thứ tự truyền tham số đăng ký trên Windows rcx - rdx - r8 - r9 - rest on stacktrong khi mọi người khác sử dụng rdi - rsi - rdx - rcx - r8 - r9 - rest on stack.

Tái bút Tôi biết các quy ước gọi điện này nói chung khác nhau như thế nào và tôi biết tìm thông tin chi tiết ở đâu nếu cần. Điều tôi muốn biết là tại sao .

Chỉnh sửa: để biết cách thực hiện, xem ví dụ: mục nhập wikipedia và các liên kết từ đó.


2
Chà, chỉ cho đăng ký đầu tiên: rcx: ecx là tham số "this" cho quy ước msvc __thiscall x86. Vì vậy, có lẽ chỉ để dễ dàng chuyển trình biên dịch của họ sang x64, họ đã bắt đầu với rcx làm đầu tiên. Rằng mọi thứ khác sau đó cũng sẽ khác chỉ là hệ quả của quyết định ban đầu đó.
Chris Becke

@Chris: Tôi đã thêm tham chiếu vào tài liệu bổ sung AMD64 ABI (và một số giải thích nó thực sự là gì) bên dưới.
FrankH.

1
Tôi đã không tìm thấy một lý do từ MS nhưng tôi tìm thấy một số cuộc thảo luận ở đây
phuclv

Câu trả lời:


81

Chọn bốn thanh ghi đối số trên x64 - chung cho UN * X / Win64

Một trong những điều cần lưu ý về x86 là tên đăng ký để mã hóa "số đăng ký" không rõ ràng; về mã hóa lệnh ( byte MOD R / M , xem http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm ), số đăng ký 0 ... 7 - theo thứ tự đó - ?AX, ?CX, ?DX, ?BX, ?SP, ?BP, ?SI, ?DI.

Do đó, việc chọn A / C / D (regs 0..2) cho giá trị trả về và hai đối số đầu tiên (là __fastcallquy ước 32bit "cổ điển" ) là một lựa chọn hợp lý. Liên quan đến việc chuyển sang 64bit, các reg "cao hơn" được sắp xếp theo thứ tự, và cả Microsoft và UN * X / Linux đều chọn R8/ R9là những người đầu tiên.

Giữ ý nghĩ đó, lựa chọn của Microsoft RAX(giá trị trả về) và RCX, RDX, R8, R9(arg [0..3]) là một lựa chọn dễ hiểu nếu bạn chọn Bốn thanh ghi cho các đối số.

Tôi không biết tại sao AMD64 UN * X ABI lại chọn RDXtrước đây RCX.

Chọn sáu thanh ghi đối số trên x64 - UN * X cụ thể

UN * X, trên các kiến ​​trúc RISC, theo truyền thống thực hiện truyền đối số trong các thanh ghi - cụ thể là đối với sáu đối số đầu tiên (ít nhất là như vậy trên PPC, SPARC, MIPS). Đó có thể là một trong những lý do chính tại sao các nhà thiết kế AMD64 (UN * X) ABI cũng chọn sử dụng sáu thanh ghi trên kiến ​​trúc đó.

Vì vậy, nếu bạn muốn Sáu thanh ghi để vượt qua đối số trong, và đó là logic để lựa chọn RCX, RDX, R8R9cho bốn người trong số họ, mà khác hai bạn nên chọn?

Các reg "cao hơn" yêu cầu thêm byte tiền tố lệnh để chọn chúng và do đó có kích thước lệnh lớn hơn, vì vậy bạn sẽ không muốn chọn bất kỳ lệnh nào trong số đó nếu bạn có tùy chọn. Trong số các thanh ghi cổ điển, do ý nghĩa ẩn của RBPRSPchúng không có sẵn, và RBXtheo truyền thống có một công dụng đặc biệt trên UN * X (bảng bù toàn cục) mà dường như các nhà thiết kế AMD64 ABI không muốn trở nên không tương thích với.
Ergo, sự lựa chọn duy nhấtRSI/ RDI.

Vì vậy, nếu bạn phải lấy RSI/ RDIlàm thanh ghi đối số, chúng sẽ là đối số nào?

Làm cho chúng arg[0]arg[1]có một số lợi thế. Xem bình luận của cHao.
?SI?DIlà các toán hạng nguồn / đích của lệnh chuỗi và như cHao đã đề cập, việc sử dụng chúng làm thanh ghi đối số có nghĩa là với các quy ước gọi AMD64 UN * X strcpy(), ví dụ, hàm đơn giản nhất có thể chỉ bao gồm hai lệnh CPU repz movsb; retvì nguồn / đích địa chỉ đã được người gọi đưa vào đúng thanh ghi. Có, đặc biệt là trong mã "keo" cấp thấp và do trình biên dịch tạo ra (ví dụ: một số trình phân bổ heap C ++ có các đối tượng không lấp đầy trên cấu trúc hoặc các trang heap không lấp đầy hạt nhân trênsbrk()hoặc mặc định trang copy-on-write) một lượng lớn bản sao / điền khối, do đó nó sẽ hữu ích cho mã thường được sử dụng để lưu hai hoặc ba lệnh CPU mà nếu không sẽ tải các đối số địa chỉ nguồn / đích như vậy vào thanh ghi "đúng".

Vì vậy, trong một cách, UN * X và Win64 chỉ khác nhau ở chỗ UN * X "prepends" hai đối số bổ sung, trong mục đích lựa chọn RSI/ RDIđăng ký, với sự lựa chọn tự nhiên của bốn đối số trong RCX, RDX, R8R9.

Ngoài ra ...

Có nhiều sự khác biệt giữa ABI UN * X và Windows x64 hơn là chỉ ánh xạ các đối số tới các thanh ghi cụ thể. Để biết tổng quan về Win64, hãy kiểm tra:

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

Win64 và AMD64 UN * X cũng có sự khác biệt đáng kể về cách sử dụng không gian ngăn xếp; trên Win64, ví dụ, người gọi phải cấp phát không gian ngăn xếp cho các đối số của hàm mặc dù các args 0 ... 3 được chuyển vào các thanh ghi. Mặt khác, trên UN * X, một hàm lá (tức là một hàm không gọi các hàm khác) thậm chí không cần phải cấp phát không gian ngăn xếp nếu nó cần không quá 128 Byte (vâng, bạn sở hữu và có thể sử dụng một số lượng ngăn xếp nhất định mà không phân bổ nó ... tốt, trừ khi bạn là mã hạt nhân, một nguồn của các lỗi tiện lợi). Tất cả những lựa chọn này đều là những lựa chọn tối ưu hóa cụ thể, hầu hết lý do của những điều đó được giải thích trong tài liệu tham khảo ABI đầy đủ mà tham chiếu wikipedia của người đăng ban đầu trỏ đến.


1
Về tên thanh ghi: Byte tiền tố đó có thể là một yếu tố. Nhưng sau đó sẽ hợp lý hơn khi MS chọn rcx - rdx - rdi - rsi làm thanh ghi đối số. Nhưng giá trị số của tám giá trị đầu tiên có thể hướng dẫn bạn nếu bạn đang thiết kế ABI từ đầu, nhưng không có lý do gì để thay đổi chúng nếu ABI hoàn toàn tốt đã tồn tại, điều đó chỉ dẫn đến nhiều nhầm lẫn hơn.
JanKanis

2
Trên RSI / RDI: Các hướng dẫn này thường sẽ được đặt trong dòng, trong trường hợp đó quy ước gọi không quan trọng. Nếu không, chỉ có một bản sao (hoặc có thể là một vài) của hàm đó trên toàn hệ thống, do đó, nó chỉ tiết kiệm được tổng số byte . Không đáng. Về sự khác biệt khác / ngăn xếp cuộc gọi: Tính hữu dụng của các lựa chọn cụ thể được giải thích trong tài liệu tham khảo ABI, nhưng chúng không đưa ra so sánh. Họ không cho biết tại sao các tối ưu hóa khác không được chọn - ví dụ: tại sao Windows không có vùng màu đỏ 128 byte và tại sao AMD ABI không có các khe ngăn xếp bổ sung cho các đối số?
JanKanis

1
@cHao: không. Nhưng họ đã thay đổi nó bằng cách nào. Win64 ABI khác với Win32 (và không tương thích) và cũng khác với ABI của AMD.
JanKanis

7
@Somejan: Win64 và Win32 __fastcallgiống nhau 100% đối với trường hợp có không quá hai đối số không lớn hơn 32bit và trả về giá trị không lớn hơn 32bit. Đó không phải là một lớp hàm nhỏ. Không có khả năng tương thích ngược như vậy giữa các UN * X ABI cho i386 / amd64.
FrankH.

2
@szx: Tôi vừa tìm thấy chuỗi danh sách gửi thư có liên quan từ tháng 11 năm 2000 và đăng một câu trả lời tóm tắt lý do. Lưu ý rằng nó memcpycó thể được thực hiện theo cách đó, không phải strcpy.
Peter Cordes

42

IDK tại sao Windows đã làm những gì họ đã làm. Xem phần cuối của câu trả lời này để đoán. Tôi tò mò về cách quy ước gọi SysV được quyết định, vì vậy tôi đã đào vào kho lưu trữ danh sách gửi thư và tìm thấy một số thứ gọn gàng.

Thật thú vị khi đọc một số chuỗi cũ đó trong danh sách gửi thư AMD64, vì các kiến ​​trúc sư AMD đã hoạt động trên đó. Ví dụ: Chọn tên thanh ghi là một trong những phần khó: AMD đã xem xét đổi tên 8 thanh ghi ban đầu là r0-r7, hoặc gọi các thanh ghi mới như vậyUAX .

Ngoài ra, thông tin phản hồi từ kernel devs điều được xác định mà thực hiện các thiết kế ban đầu của syscallswapgskhông sử dụng được . Đó là cách AMD cập nhật hướng dẫn để giải quyết vấn đề này trước khi phát hành bất kỳ chip thực tế nào. Điều thú vị là vào cuối năm 2000, giả định rằng Intel có thể sẽ không áp dụng AMD64.


Quy ước gọi SysV (Linux) và quyết định về số lượng đăng ký nên được lưu giữ bằng callee so với lưu người gọi, được đưa ra lần đầu tiên vào tháng 11 năm 2000, bởi Jan Hubicka (một nhà phát triển gcc). Anh ấy đã biên dịch SPEC2000 và xem kích thước mã và số lượng lệnh. Chủ đề thảo luận đó đưa ra một số ý kiến ​​giống như câu trả lời và nhận xét về câu hỏi SO này. Trong luồng thứ 2, anh ấy đề xuất trình tự hiện tại là tối ưu và hy vọng là cuối cùng, tạo ra mã nhỏ hơn so với một số lựa chọn thay thế .

Anh ấy đang sử dụng thuật ngữ "toàn cầu" để chỉ các đăng ký được bảo toàn cuộc gọi, phải được đẩy / bật lên nếu được sử dụng.

Sự lựa chọn của rdi, rsi, rdxnhư ba args đầu tiên đã được thúc đẩy bởi:

  • tiết kiệm kích thước mã nhỏ trong các hàm gọi memsethoặc hàm chuỗi C khác trên args của chúng (trong đó gcc nội tuyến một hoạt động chuỗi đại diện?)
  • rbxđược bảo toàn cuộc gọi vì có thể truy cập hai reg được bảo toàn cuộc gọi mà không có tiền tố REX (rbx và rbp) là một chiến thắng. Có lẽ được chọn vì đó là reg khác duy nhất không được sử dụng ngầm bởi bất kỳ hướng dẫn nào. (chuỗi đại diện, số lượng dịch chuyển và đầu ra / đầu vào mul / div chạm vào mọi thứ khác).
  • Không có thanh ghi nào có mục đích đặc biệt được bảo toàn lệnh gọi (xem điểm trước), do đó, một hàm muốn sử dụng lệnh chuỗi đại diện hoặc thay đổi số biến có thể phải di chuyển các args hàm đến một nơi khác, nhưng không phải lưu / khôi phục giá trị của người gọi.
  • Chúng tôi đang cố gắng tránh RCX sớm trong chuỗi, vì nó là thanh ghi được sử dụng phổ biến cho các mục đích đặc biệt, như EAX, vì vậy nó có cùng mục đích bị thiếu trong chuỗi. Ngoài ra, nó không thể được sử dụng cho cuộc gọi tổng hợp và chúng tôi muốn tạo chuỗi cuộc gọi tổng hợp để khớp với chuỗi lệnh gọi hàm càng nhiều càng tốt.

    (nền: syscall/ sysretkhông thể tránh khỏi phá hủy rcx(với rip) và r11(với RFLAGS), vì vậy hạt nhân không thể nhìn thấy những gì ban đầu trong rcxkhi syscallchạy.)

Lệnh gọi hệ thống hạt nhân ABI đã được chọn để khớp với lệnh gọi hàm ABI, ngoại trừ r10thay vì rcx, vì vậy, một trình bao bọc libc có các chức năng như mmap(2)có thể chỉ mov %rcx, %r10/ mov $0x9, %eax/ syscall.


Lưu ý rằng quy ước gọi SysV được sử dụng bởi i386 Linux kém hơn so với __vectorcall 32bit của Window. Nó chuyển mọi thứ trên ngăn xếp và chỉ trả về edx:eaxcho int64, không trả về cho các cấu trúc nhỏ . Không có gì ngạc nhiên khi họ đã cố gắng duy trì khả năng tương thích với nó. Khi không có lý do gì để không làm vậy, họ đã làm những việc như giữ nguyên rbxcuộc gọi, vì họ quyết định rằng có một cái khác trong 8 nguyên bản (không cần tiền tố REX) là tốt.

Làm cho tối ưu ABI là nhiều quan trọng hơn dài hạn hơn bất kỳ xem xét khác. Tôi nghĩ rằng họ đã làm một công việc khá tốt. Tôi không hoàn toàn chắc chắn về việc trả về các cấu trúc được đóng gói vào các thanh ghi, thay vì các trường khác nhau trong các đăng ký khác nhau. Tôi đoán rằng mã chuyển chúng theo giá trị mà không thực sự hoạt động trên các trường sẽ thắng theo cách này, nhưng công việc giải nén thêm có vẻ ngớ ngẩn. Họ có thể có nhiều thanh ghi trả về số nguyên hơn rdx:rax, vì vậy việc trả về một cấu trúc có 4 thành viên có thể trả về chúng ở dạng rdi, rsi, rdx, rax hoặc gì đó.

Họ đã cân nhắc việc chuyển các số nguyên trong vector regs, vì SSE2 có thể hoạt động trên các số nguyên. May mắn thay họ đã không làm điều đó. Các số nguyên được sử dụng làm hiệu số con trỏ rất thường xuyên và một chuyến đi khứ hồi để xếp chồng bộ nhớ là khá rẻ . Ngoài ra, các lệnh SSE2 mất nhiều byte mã hơn các lệnh số nguyên.


Tôi nghi ngờ rằng các nhà thiết kế Windows ABI có thể đã nhằm mục đích giảm thiểu sự khác biệt giữa 32 và 64bit vì lợi ích của những người phải chuyển asm từ cái này sang cái khác hoặc có thể sử dụng một vài #ifdefs trong một số ASM để cùng một nguồn có thể dễ dàng xây dựng hơn phiên bản 32 hoặc 64 bit của một hàm.

Giảm thiểu các thay đổi trong chuỗi công cụ dường như không thể. Một trình biên dịch x86-64 cần một bảng riêng biệt trong đó thanh ghi được sử dụng để làm gì và quy ước gọi là gì. Có một sự chồng chéo nhỏ với 32bit không có khả năng tiết kiệm đáng kể kích thước / độ phức tạp của chuỗi công cụ.


1
Tôi nghĩ rằng tôi đã đọc ở đâu đó trên blog của Raymond Chen về lý do lựa chọn các thanh ghi đó sau khi đánh giá điểm chuẩn từ phía MS nhưng tôi không thể tìm thấy nó nữa. Tuy nhiên một số lý do liên quan đến việc homezone đã giải thích ở đây blogs.msdn.microsoft.com/oldnewthing/20160623-00/?p=93735 blogs.msdn.microsoft.com/freik/2006/03/06/...
phuclv


@phuclv: Xem thêm Viết bên dưới ESP có hợp lệ không? . Nhận xét của Raymond về câu trả lời của tôi ở đó đã chỉ ra một số chi tiết SEH mà tôi không biết, điều này giải thích tại sao Windows x86 32/64 hiện không có vùng màu đỏ de-facto. Bài đăng trên blog của anh ấy có một số trường hợp hợp lý cho cùng một khả năng xử lý trang mã mà tôi đã đề cập trong câu trả lời đó :) Vì vậy, Raymond đã giải thích nó tốt hơn tôi (không ngạc nhiên vì tôi bắt đầu biết rất ít về Windows), và bảng kích thước vùng màu đỏ cho phi x86 thực sự rất gọn gàng.
Peter Cordes

13

Hãy nhớ rằng ban đầu Microsoft "chính thức không tham gia vào nỗ lực AMD64 ban đầu" (từ "Lịch sử máy tính 64-bit hiện đại" của Matthew Kerner và Neil Padgett) vì họ là đối tác mạnh mẽ với Intel về kiến ​​trúc IA64. Tôi nghĩ rằng điều này có nghĩa là ngay cả khi họ muốn làm việc với các kỹ sư GCC trên ABI để sử dụng cả trên Unix và Windows, họ sẽ không làm như vậy vì điều đó có nghĩa là họ sẽ công khai ủng hộ nỗ lực AMD64 khi họ chưa có ' vẫn chưa chính thức làm như vậy (và có lẽ sẽ khiến Intel khó chịu).

Trên hết, hồi đó Microsoft hoàn toàn không có khuynh hướng thân thiện với các dự án mã nguồn mở. Chắc chắn không phải Linux hoặc GCC.

Vậy tại sao họ lại hợp tác trên ABI? Tôi đoán rằng các ABI khác nhau đơn giản bởi vì chúng được thiết kế ít nhiều giống nhau và riêng biệt.

Một trích dẫn khác từ "Lịch sử của máy tính 64-bit hiện đại":

Song song với sự hợp tác của Microsoft, AMD cũng tham gia vào cộng đồng mã nguồn mở để chuẩn bị cho con chip này. AMD đã ký hợp đồng với cả Code Sorcery và SuSE cho công việc chuỗi công cụ (Red Hat đã được Intel tham gia vào cổng chuỗi công cụ IA64). Russell giải thích rằng SuSE đã sản xuất trình biên dịch C và FORTRAN, còn Code Sorcery thì sản xuất trình biên dịch Pascal. Weber giải thích rằng công ty cũng đã tham gia với cộng đồng Linux để chuẩn bị một cổng Linux. Nỗ lực này rất quan trọng: nó đóng vai trò như một động lực để Microsoft tiếp tục đầu tư vào nỗ lực AMD64 Windows, và cũng đảm bảo rằng Linux, vốn đang trở thành một hệ điều hành quan trọng vào thời điểm đó, sẽ khả dụng khi chip được phát hành.

Weber đi xa hơn khi nói rằng công việc Linux hoàn toàn quan trọng đối với sự thành công của AMD64, bởi vì nó cho phép AMD sản xuất một hệ thống end-to-end mà không cần bất kỳ công ty nào khác trợ giúp. Khả năng này đảm bảo rằng AMD có một chiến lược sống sót trong trường hợp xấu nhất ngay cả khi các đối tác khác rút lui, điều này khiến các đối tác khác phải tham gia vì sợ bị bỏ lại phía sau.

Điều này cho thấy rằng ngay cả AMD cũng không cảm thấy hợp tác nhất thiết là điều quan trọng nhất giữa MS và Unix, nhưng việc hỗ trợ Unix / Linux là rất quan trọng. Có thể ngay cả việc cố gắng thuyết phục một hoặc cả hai bên thỏa hiệp hoặc hợp tác không đáng để nỗ lực hoặc mạo hiểm (?) Chọc tức một trong hai bên? Có lẽ AMD nghĩ rằng ngay cả việc đề xuất một ABI chung cũng có thể làm chậm hoặc trật mục tiêu quan trọng hơn là chỉ cần có hỗ trợ phần mềm sẵn sàng khi chip đã sẵn sàng.

Theo suy đoán của tôi, nhưng tôi nghĩ lý do chính khiến các ABI khác nhau là lý do chính trị mà MS và các bên Unix / Linux không hợp tác với nhau về nó, và AMD không coi đó là vấn đề.


Quan điểm tốt đẹp về chính trị. Tôi đồng ý rằng đó không phải là lỗi hay trách nhiệm của AMD. Tôi đổ lỗi cho Microsoft vì đã chọn một quy ước gọi điện tồi tệ hơn. Nếu quy ước kêu gọi của họ trở nên tốt hơn, tôi có một số thông cảm, nhưng họ phải thay đổi từ ABI ban đầu của họ sang __vectorcallvì việc vượt qua __m128ngăn xếp bị hút. Có ngữ nghĩa cuộc gọi được bảo tồn cho 128B thấp của một số các regs vector cũng là lạ (một phần lỗi của Intel vì đã không thiết kế một mở rộng tiết kiệm / khôi phục cơ chế với SSE ban đầu, và vẫn không có AVX.)
Peter Cordes

1
Tôi thực sự không có bất kỳ chuyên môn hoặc kiến ​​thức nào về mức độ tốt của ABI. Tôi chỉ thỉnh thoảng cần biết chúng là gì để tôi có thể hiểu / gỡ lỗi ở cấp lắp ráp.
Michael Burr

1
Một ABI tốt sẽ giảm thiểu kích thước mã và số lượng lệnh, đồng thời giữ cho chuỗi phụ thuộc có độ trễ thấp bằng cách tránh các vòng lặp thêm qua bộ nhớ. (cho args, hoặc cho người dân địa phương cần được đổ / nạp lại). Có sự đánh đổi. Vùng đỏ của SysV có thêm một vài lệnh ở một nơi (bộ điều phối bộ xử lý tín hiệu của hạt nhân), mang lại lợi ích tương đối lớn cho các chức năng của lá là không phải điều chỉnh con trỏ ngăn xếp để có được một số khoảng trống. Vì vậy, đó là một chiến thắng rõ ràng với nhược điểm gần như bằng không. Nó đã được thông qua mà không có nhiều cuộc thảo luận sau khi nó được đề xuất cho SysV.
Peter Cordes

1
@dgnuff: Đúng vậy, đó là câu trả lời cho Tại sao mã nhân không thể sử dụng Vùng đỏ . Ngắt sử dụng ngăn xếp hạt nhân, không phải ngăn xếp không gian người dùng, ngay cả khi chúng đến khi CPU đang chạy mã không gian người dùng. Kernel không tin tưởng ngăn xếp không gian người dùng bởi vì một luồng khác trong cùng một tiến trình không gian người dùng có thể sửa đổi nó, do đó sẽ chiếm quyền kiểm soát hạt nhân!
Peter Cordes

1
@ DavidA.Gray: vâng, ABI không nói rằng bạn phải sử dụng RBP làm con trỏ khung nên mã được tối ưu hóa thường không (ngoại trừ trong các hàm sử dụng allocahoặc một số trường hợp khác). Điều này là bình thường nếu bạn đã từng gcc -fomit-frame-pointerlà mặc định trên Linux. ABI xác định siêu dữ liệu mở ngăn xếp cho phép xử lý ngoại lệ vẫn hoạt động. (Tôi cho rằng nó hoạt động giống như công cụ CFI của GNU / Linux x86-64 System V .eh_frame). gcc -fomit-frame-pointerđã là mặc định (với tối ưu hóa được bật) kể từ mãi mãi trên x86-64 và các trình biên dịch khác (như MSVC) cũng làm điều tương tự.
Peter Cordes

12

Win32 có cách sử dụng riêng cho ESI và EDI và yêu cầu chúng không được sửa đổi (hoặc ít nhất là chúng phải được khôi phục trước khi gọi vào API). Tôi sẽ tưởng tượng mã 64-bit làm tương tự với RSI và RDI, điều này sẽ giải thích tại sao chúng không được sử dụng để chuyển các đối số hàm xung quanh.

Tuy nhiên, tôi không thể cho bạn biết tại sao RCX và RDX được chuyển đổi.


1
Tất cả các quy ước gọi có một số thanh ghi được chỉ định là đầu và một số được giữ nguyên như ESI / EDI và RSI / RDI trên Win64. Nhưng đó là những thanh ghi mục đích chung, Microsoft có thể chọn sử dụng chúng theo cách khác mà không có vấn đề gì.
JanKanis

1
@Somejan: Chắc chắn rồi, nếu họ muốn viết lại toàn bộ API và có hai hệ điều hành khác nhau. Tuy nhiên, tôi sẽ không gọi đó là "không có vấn đề". Trong hàng chục năm nay, MS đã đưa ra những lời hứa nhất định về những gì nó sẽ làm và sẽ không làm với các thanh ghi x86, và chúng đã ít nhiều nhất quán và tương thích suốt thời gian qua. Họ sẽ không ném tất cả những thứ đó ra ngoài cửa sổ chỉ vì một số sắc lệnh từ AMD, đặc biệt là một sắc lệnh quá tùy tiện và nằm ngoài lĩnh vực "xây dựng bộ xử lý".
cHao

5
@Somejan: AMD64 UN * X ABI luôn chính xác như vậy - một phần dành riêng cho UNIX . Tài liệu, x86-64.org/documentation/abi.pdf , có tiêu đề Giao diện nhị phân ứng dụng Hệ thống V, Phần bổ sung cho Bộ xử lý Kiến trúc AMD64 là có lý do. Các ABI UNIX (phổ biến) (một bộ sưu tập nhiều tập, sco.com/developers/devspecs ) để lại một phần cho chương 3 dành riêng cho bộ xử lý - Phần bổ sung - là các quy ước gọi hàm và quy tắc bố trí dữ liệu cho một bộ xử lý cụ thể.
FrankH.

7
@Somejan: Microsoft Windows chưa bao giờ cố gắng đặc biệt gần gũi với UN * X và khi chuyển Windows sang x64 / AMD64, họ chỉ đơn giản là chọn mở rộng quy ước gọi của riêng mình __fastcall . Bạn tuyên bố Win32 / Win64 không tương thích, nhưng sau đó, nhìn kỹ: Đối với một hàm mang theo hai 32bit args và trả về 32bit, Win64 và Win32 __fastcallthực sự 100% tương thích (giống regs để thông qua hai 32bit args, giá trị trả về như nhau). Thậm chí một số mã nhị phân (!) Có thể hoạt động ở cả hai chế độ hoạt động. Phía UNIX hoàn toàn đoạn tuyệt với "lối cũ". Vì những lý do chính đáng, nhưng nghỉ là nghỉ.
FrankH.

2
@Olof: Nó không chỉ là một thứ của trình biên dịch. Tôi đã gặp sự cố với ESI và EDI khi tôi thực hiện các công cụ độc lập trong NASM. Windows chắc chắn quan tâm đến những thanh ghi đó. Nhưng có, bạn có thể sử dụng chúng nếu bạn lưu chúng trước khi thực hiện và khôi phục chúng trước khi Windows cần.
cHao
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.