Các quy ước gọi cho hệ thống UNIX và Linux gọi trên i386 và x86-64 là gì


146

Các liên kết sau giải thích các quy ước gọi hệ thống x86-32 cho cả UNIX (hương vị BSD) & Linux:

Nhưng các quy ước gọi hệ thống x86-64 trên cả UNIX & Linux là gì?


Không có "tiêu chuẩn" cho các quy ước gọi Unix. Đối với linux chắc chắn, nhưng tôi chắc chắn rằng Solaris, OpenBSD, Linux và Minix có thể có các quy ước gọi khác nhau ít nhất một chút và tất cả chúng đều là unix.
Earlz

2
Điều đó không hoàn toàn đúng - có một bộ UNIX ABI có sẵn cho hầu hết các loại máy, cho phép trình biên dịch C đạt được khả năng tương tác. Trình biên dịch C ++ có một vấn đề lớn hơn.
Jonathan Leffler

1
Cả hai bạn đều đúng. Tôi đang tìm kiếm FreeBSD & Linux.
móng vuốt

Tôi sẽ đánh giá cao nếu câu trả lời chứa thông tin về những gì các thanh ghi được bảo toàn trên các cuộc gọi hệ thống. Tất nhiên, con trỏ ngăn xếp là, (trừ khi thay đổi theo cách được kiểm soát trong lệnh gọi __NR_clone), nhưng chúng có phải là cái khác không?
Albert van der Horst

@AlbertvanderHorst: vâng, tôi vừa cập nhật câu trả lời wiki với các chi tiết cho 32 bit. 64bit đã chính xác: RCx và r11 bị phá hủy do cách thức sysrethoạt động, cùng với rax được thay thế bằng giá trị trả về. Tất cả các thanh ghi khác được bảo quản trên amd64.
Peter Cordes

Câu trả lời:


228

Đọc thêm cho bất kỳ chủ đề nào ở đây: Hướng dẫn dứt khoát cho các cuộc gọi hệ thống Linux


Tôi đã xác minh những thứ này bằng cách sử dụng GNU Assembler (gas) trên Linux.

Giao diện hạt nhân

x86-32 aka i386 Quy ước cuộc gọi hệ thống Linux:

Trong x86-32 tham số cho cuộc gọi hệ thống Linux được thông qua bằng cách sử dụng các thanh ghi. %eaxcho syscall_number. % ebx,% ecx,% edx,% esi,% edi,% ebp được sử dụng để truyền 6 tham số cho các cuộc gọi hệ thống.

Giá trị trả về là trong %eax. Tất cả các thanh ghi khác (bao gồm EFLAGS) được bảo toàn trên int $0x80.

Tôi đã theo đoạn trích từ Hướng dẫn lắp ráp Linux nhưng tôi nghi ngờ về điều này. Nếu bất kỳ ai có thể đưa ra một ví dụ, nó sẽ là tuyệt vời.

Nếu có nhiều hơn sáu đối số, %ebxphải chứa vị trí bộ nhớ nơi lưu danh sách các đối số - nhưng đừng lo lắng về điều này bởi vì không chắc là bạn sẽ sử dụng một tòa nhà có nhiều hơn sáu đối số.

Để biết ví dụ và đọc thêm một chút, hãy tham khảo http://www.int80h.org/bsdasm/#alternate-calling-convent . Một ví dụ khác về Hello World cho i386 Linux bằng cách sử dụng int 0x80: Xin chào, thế giới trong ngôn ngữ lắp ráp với các cuộc gọi hệ thống Linux?

Có một cách nhanh hơn để thực hiện các cuộc gọi hệ thống 32 bit: sử dụng sysenter. Hạt nhân ánh xạ một trang bộ nhớ vào mọi tiến trình (vDSO), với phía không gian người dùng của sysenterđiệu nhảy, phải hợp tác với hạt nhân để có thể tìm thấy địa chỉ trả về. Arg để đăng ký ánh xạ giống như cho int $0x80. Thông thường bạn nên gọi vào vDSO thay vì sử dụng sysentertrực tiếp. (Xem Hướng dẫn dứt khoát cho các cuộc gọi hệ thống Linux để biết thông tin về liên kết và gọi vào vDSO, và để biết thêm thông tin về sysentervà mọi thứ khác liên quan đến các cuộc gọi hệ thống.)

x86-32 [Miễn phí | Mở | Net | DragonFly] Quy ước cuộc gọi hệ thống UNIX BSD:

Các thông số được truyền vào ngăn xếp. Đẩy các tham số (tham số cuối cùng được đẩy trước) vào ngăn xếp. Sau đó đẩy thêm 32 bit dữ liệu giả (Dữ liệu không thực sự là dữ liệu giả. Tham khảo liên kết sau để biết thêm thông tin) và sau đó đưa ra hướng dẫn gọi hệ thốngint $0x80

http://www.int80h.org/bsdasm/#default-calling-convent


x86-64 Quy ước cuộc gọi hệ thống Linux:

x86-64 Mac OS X tương tự nhưng khác nhau . TODO: kiểm tra xem * BSD làm gì.

Tham khảo phần: "A.2 AMD64 Linux Kernel Conventions" của System V Application Binary Interface AMD64 Architecture Processor Bổ sung . Các phiên bản mới nhất của psABI i386 và x86-64 System V có thể được tìm thấy được liên kết từ trang này trong repo của người bảo trì ABI . (Xem thêm thẻ wiki cho các liên kết ABI cập nhật và nhiều nội dung hay khác về x86 asm.)

Đây là đoạn trích từ phần này:

  1. Các ứng dụng cấp người dùng sử dụng làm các thanh ghi số nguyên để truyền chuỗi% rdi,% rsi,% rdx,% rcx,% r8 và% r9. Giao diện kernel sử dụng% rdi,% rsi,% rdx,% r10,% r8 và% r9.
  2. Một cuộc gọi hệ thống được thực hiện thông qua syscallhướng dẫn . Điều này ghi lại % RCx và% r11 cũng như giá trị trả về% rax, nhưng các thanh ghi khác được giữ nguyên.
  3. Số lượng tòa nhà phải được thông qua trong đăng ký% rax.
  4. Các cuộc gọi hệ thống được giới hạn trong sáu đối số, không có đối số nào được truyền trực tiếp trên ngăn xếp.
  5. Trở về từ tòa nhà, đăng ký% rax chứa kết quả của cuộc gọi hệ thống. Một giá trị trong phạm vi từ -4095 đến -1 chỉ ra lỗi -errno.
  6. Chỉ các giá trị của lớp INTEGER hoặc MEM MEM class được truyền vào kernel.

Hãy nhớ điều này là từ phụ lục dành riêng cho Linux cho ABI và ngay cả đối với Linux, thông tin này không mang tính quy phạm. (Nhưng thực tế nó chính xác.)

int $0x80ABI 32 bit này có thể sử dụng được trong mã 64 bit (nhưng không được khuyến khích). Điều gì xảy ra nếu bạn sử dụng 32-bit int 0x80 Linux ABI trong mã 64 bit? Nó vẫn cắt các đầu vào của nó thành 32 bit, do đó, nó không phù hợp với các con trỏ và nó không có giá trị r8-r11.

Giao diện người dùng: chức năng gọi

Quy ước gọi hàm x86-32:

Trong x86-32 tham số được truyền vào ngăn xếp. Tham số cuối cùng được đẩy đầu tiên vào ngăn xếp cho đến khi tất cả các tham số được thực hiện và sau đó calllệnh được thực thi. Điều này được sử dụng để gọi các hàm thư viện C (libc) trên Linux từ lắp ráp.

Các phiên bản hiện đại của i386 System V ABI (được sử dụng trên Linux) yêu cầu căn chỉnh 16 byte %esptrước a call, như Hệ thống V ABI x86-64 luôn luôn được yêu cầu. Callees được phép giả định rằng và sử dụng tải / lưu trữ 16 byte SSE có lỗi khi không được chỉ định. Nhưng trong lịch sử, Linux chỉ yêu cầu căn chỉnh ngăn xếp 4 byte, do đó, phải mất thêm công sức để dự trữ không gian được căn chỉnh tự nhiên ngay cả đối với 8 byte doublehoặc thứ gì đó.

Một số hệ thống 32 bit hiện đại khác vẫn không yêu cầu căn chỉnh ngăn xếp hơn 4 byte.


x86-64 Quy ước gọi chức năng không gian người dùng System V:

x86-64 System V vượt qua các đối số trong các thanh ghi, hiệu quả hơn so với quy ước đối số ngăn xếp của i System System V. Nó tránh được độ trễ và các hướng dẫn bổ sung về việc lưu trữ args vào bộ nhớ (bộ đệm) và sau đó tải lại chúng trong callee. Điều này hoạt động tốt bởi vì có nhiều thanh ghi có sẵn hơn và tốt hơn cho các CPU hiệu suất cao hiện đại, nơi có độ trễ và vấn đề thực thi không theo thứ tự. (ABI i386 rất cũ).

Trong cơ chế mới này : Đầu tiên các tham số được chia thành các lớp. Lớp của mỗi tham số xác định cách thức mà nó được truyền cho hàm được gọi.

Để biết thông tin đầy đủ, hãy tham khảo: "Trình tự gọi chức năng 3.2" của Giao diện nhị phân ứng dụng System V Bổ sung bộ xử lý kiến ​​trúc AMD64 , phần đọc:

Khi các đối số được phân loại, các thanh ghi được gán (theo thứ tự từ trái sang phải) để truyền như sau:

  1. Nếu lớp là NHỚ, truyền đối số trên ngăn xếp.
  2. Nếu lớp là INTEGER, thì thanh ghi có sẵn tiếp theo của chuỗi% rdi,% rsi,% rdx,% rcx,% r8 và% r9 được sử dụng

Vì vậy, %rdi, %rsi, %rdx, %rcx, %r8 and %r9các thanh ghi theo thứ tự được sử dụng để truyền tham số nguyên / con trỏ (tức là lớp INTEGER) cho bất kỳ hàm libc nào từ assembly. % rdi được sử dụng cho tham số INTEGER đầu tiên. % rsi cho thứ 2,% rdx cho thứ 3, v.v. Sau đó, callhướng dẫn nên được đưa ra. Ngăn xếp ( %rsp) phải được căn chỉnh 16B khi callthực thi.

Nếu có nhiều hơn 6 tham số INTEGER, tham số INTEGER thứ 7 và sau đó được truyền vào ngăn xếp. (Người gọi bật lên, giống như x86-32.)

8 đối số dấu phẩy động đầu tiên được truyền vào% xmm0-7, sau đó trên ngăn xếp. Không có thanh ghi vector bảo tồn cuộc gọi. (Một hàm có kết hợp các đối số FP và số nguyên có thể có hơn 8 đối số thanh ghi tổng.)

Các hàm biến thể ( nhưprintf ) luôn luôn cần %al= số lượng thanh ghi FP args.

Có các quy tắc về thời điểm đóng gói cấu trúc vào các thanh ghi ( rdx:raxkhi trả về) so với trong bộ nhớ. Xem ABI để biết chi tiết và kiểm tra đầu ra của trình biên dịch để đảm bảo mã của bạn đồng ý với các trình biên dịch về cách một cái gì đó sẽ được chuyển / trả lại.


Lưu ý rằng quy ước gọi hàm Windows x64 có nhiều khác biệt đáng kể so với x86-64 System V, giống như không gian bóng phải được người gọi dành riêng (thay vì vùng đỏ) và xmm6-xmm15 được bảo toàn cuộc gọi. Và các quy tắc rất khác nhau mà arg đi trong đăng ký nào.


1
Trong linux 32 "tất cả các thanh ghi trừ ax bx cd dx si di bp đều được giữ nguyên". Tôi không thể nghĩ về bất kỳ ...
Albert van der Horst

Trên amd64, nếu có hơn 6 tham số và chúng được truyền vào ngăn xếp, ai chịu trách nhiệm dọn dẹp ngăn xếp sau cuộc gọi, người gọi hoặc callee?
Nicolás

1
@ Nicolás: người gọi dọn dẹp ngăn xếp. Tôi đã cập nhật câu trả lời với nhiều chi tiết hơn về quy ước gọi hàm.
Peter Cordes

1
Nếu bạn sử dụng int 0x80ABI của Linux với mã 64 bit, đây chính xác là những gì xảy ra: stackoverflow.com/questions/46087730/ . Nó zeros r8-r11 và hoạt động chính xác như khi chạy trong quy trình 32 bit. Trong câu hỏi và trả lời đó, tôi có một ví dụ cho thấy nó hoạt động hoặc không thực hiện được việc cắt một con trỏ. Và tôi cũng đào sâu vào nguồn kernel để chỉ ra lý do tại sao nó hoạt động theo cách đó.
Peter Cordes

1
@EvanCarroll: Đoạn trích (đoạn trích dẫn) nằm ở liên kết được cung cấp Hướng dẫn lắp ráp Linux cụ thể trong phần 4.3 Các cuộc gọi hệ thống Linux
Michael Petch

14

Có lẽ bạn đang tìm kiếm x86_64 ABI?

Nếu đó không chính xác là những gì bạn đang theo đuổi, hãy sử dụng 'x86_64 abi' trong công cụ tìm kiếm ưa thích của bạn để tìm các tài liệu tham khảo thay thế.


5
thực ra, tôi chỉ muốn quy ước cuộc gọi hệ thống. đặc biệt cho UNIX (FreeBSD)
móng vuốt

3
@claws: quy ước gọi hệ thống là một phần của ABI.
Jonathan Leffler

1
vâng Tôi đã đi đến irc phát triển nhân của từng hệ điều hành riêng lẻ và hỏi họ về nó. Họ đã bảo tôi xem xét nguồn và tìm hiểu. Tôi không hiểu nếu không có tài liệu làm sao họ có thể bắt đầu phát triển? Vì vậy, tôi đã thêm một câu trả lời từ thông tin tôi đã thu thập, hy vọng những người khác điền vào phần còn lại của các chi tiết.
móng vuốt

@JonathanLeffler liên kết dường như không hoạt động ngay bây giờ. Nếu bạn cũng gặp vấn đề khi truy cập liên kết, bạn có thể vui lòng cập nhật nó không?
Ajay Brahmakshatriya

@AjayBrahmakshatriya: Cảm ơn vì đã ngẩng cao đầu; Tôi đã thêm một liên kết đến bản ghi Wayback Machine. Toàn bộ trang web x86-64.org không phản hồi với bất kỳ dữ liệu nào.
Jonathan Leffler

11

Các quy ước gọi xác định cách các tham số được truyền trong các thanh ghi khi gọi hoặc được gọi bởi chương trình khác. Và nguồn tốt nhất của các quy ước này là ở dạng các tiêu chuẩn ABI được xác định cho mỗi phần cứng này. Để dễ biên dịch, ABI tương tự cũng được sử dụng bởi không gian người dùng và chương trình kernel. Linux / Freebsd theo cùng ABI cho x86-64 và một bộ khác cho 32 bit. Nhưng x86-64 ABI cho Windows khác với Linux / FreeBSD. Và nói chung ABI không phân biệt cuộc gọi hệ thống với "cuộc gọi chức năng" thông thường. Tức là, đây là một ví dụ cụ thể về các quy ước gọi x86_64 và nó giống nhau cho cả không gian người dùng và nhân Linux: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 / (lưu ý dãy a, b, c, d, e, f của tham số):

Một kết xuất tốt của các quy ước gọi và sử dụng đăng ký

Hiệu suất là một trong những lý do cho các ABI này (ví dụ: truyền tham số qua các thanh ghi thay vì lưu vào ngăn xếp bộ nhớ)

Đối với ARM có nhiều ABI khác nhau:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/l Library / ios / documentation / Code /Conualual / iPhoneOSABIReference / iPhoneOSABIReference.pdf

Công ước ARM64:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

Đối với Linux trên PowerPC:

http: // refspecs.freest Standards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf

Và để nhúng có PPC EABI:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

Tài liệu này là tổng quan tốt về tất cả các quy ước khác nhau:

http://www.agner.org/optizes/calling_conventions.pdf


Hoàn toàn bên cạnh điểm. Người đăng câu hỏi sẽ không yêu cầu quy ước gọi tòa nhà 64 bit trong linux nếu nó giống với các hội tụ ABI chung.
Albert van der Horst

6

Nhận xét nguồn Linux kernel 5.0

Tôi biết rằng các chi tiết cụ thể của x86 đang ở dưới arch/x86, và những thứ lặt vặt đó đi theo arch/x86/entry. Vì vậy, một cách nhanh chóng git grep rditrong thư mục đó dẫn tôi đến arch / x86 / entry / entry_64.S :

/*
 * 64-bit SYSCALL instruction entry. Up to 6 arguments in registers.
 *
 * This is the only entry point used for 64-bit system calls.  The
 * hardware interface is reasonably well designed and the register to
 * argument mapping Linux uses fits well with the registers that are
 * available when SYSCALL is used.
 *
 * SYSCALL instructions can be found inlined in libc implementations as
 * well as some other programs and libraries.  There are also a handful
 * of SYSCALL instructions in the vDSO used, for example, as a
 * clock_gettimeofday fallback.
 *
 * 64-bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
 * then loads new ss, cs, and rip from previously programmed MSRs.
 * rflags gets masked by a value from another MSR (so CLD and CLAC
 * are not needed). SYSCALL does not save anything on the stack
 * and does not change rsp.
 *
 * Registers on entry:
 * rax  system call number
 * rcx  return address
 * r11  saved rflags (note: r11 is callee-clobbered register in C ABI)
 * rdi  arg0
 * rsi  arg1
 * rdx  arg2
 * r10  arg3 (needs to be moved to rcx to conform to C ABI)
 * r8   arg4
 * r9   arg5
 * (note: r12-r15, rbp, rbx are callee-preserved in C ABI)
 *
 * Only called from user space.
 *
 * When user can change pt_regs->foo always force IRET. That is because
 * it deals with uncanonical addresses better. SYSRET has trouble
 * with them due to bugs in both AMD and Intel CPUs.
 */

và cho 32 bit tại arch / x86 / entry / entry_32.S :

/*
 * 32-bit SYSENTER entry.
 *
 * 32-bit system calls through the vDSO's __kernel_vsyscall enter here
 * if X86_FEATURE_SEP is available.  This is the preferred system call
 * entry on 32-bit systems.
 *
 * The SYSENTER instruction, in principle, should *only* occur in the
 * vDSO.  In practice, a small number of Android devices were shipped
 * with a copy of Bionic that inlined a SYSENTER instruction.  This
 * never happened in any of Google's Bionic versions -- it only happened
 * in a narrow range of Intel-provided versions.
 *
 * SYSENTER loads SS, ESP, CS, and EIP from previously programmed MSRs.
 * IF and VM in RFLAGS are cleared (IOW: interrupts are off).
 * SYSENTER does not save anything on the stack,
 * and does not save old EIP (!!!), ESP, or EFLAGS.
 *
 * To avoid losing track of EFLAGS.VM (and thus potentially corrupting
 * user and/or vm86 state), we explicitly disable the SYSENTER
 * instruction in vm86 mode by reprogramming the MSRs.
 *
 * Arguments:
 * eax  system call number
 * ebx  arg1
 * ecx  arg2
 * edx  arg3
 * esi  arg4
 * edi  arg5
 * ebp  user stack
 * 0(%ebp) arg6
 */

glibc 2.29 Linux x86_64 thực hiện cuộc gọi hệ thống

Bây giờ chúng ta hãy gian lận bằng cách nhìn vào một triển khai libc lớn và xem những gì họ đang làm.

Điều gì có thể tốt hơn là nhìn vào glibc mà tôi đang sử dụng ngay bây giờ khi tôi viết câu trả lời này? :-)

glibc 2.29 định nghĩa các tòa nhà x86_64 tại sysdeps/unix/sysv/linux/x86_64/sysdep.hvà có chứa một số mã thú vị, ví dụ:

/* The Linux/x86-64 kernel expects the system call parameters in
   registers according to the following table:

    syscall number  rax
    arg 1       rdi
    arg 2       rsi
    arg 3       rdx
    arg 4       r10
    arg 5       r8
    arg 6       r9

    The Linux kernel uses and destroys internally these registers:
    return address from
    syscall     rcx
    eflags from syscall r11

    Normal function call, including calls to the system call stub
    functions in the libc, get the first six parameters passed in
    registers and the seventh parameter and later on the stack.  The
    register use is as follows:

     system call number in the DO_CALL macro
     arg 1      rdi
     arg 2      rsi
     arg 3      rdx
     arg 4      rcx
     arg 5      r8
     arg 6      r9

    We have to take care that the stack is aligned to 16 bytes.  When
    called the stack is not aligned since the return address has just
    been pushed.


    Syscalls of more than 6 arguments are not supported.  */

và:

/* Registers clobbered by syscall.  */
# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"

#undef internal_syscall6
#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
({                                  \
    unsigned long int resultvar;                    \
    TYPEFY (arg6, __arg6) = ARGIFY (arg6);              \
    TYPEFY (arg5, __arg5) = ARGIFY (arg5);              \
    TYPEFY (arg4, __arg4) = ARGIFY (arg4);              \
    TYPEFY (arg3, __arg3) = ARGIFY (arg3);              \
    TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \
    TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \
    register TYPEFY (arg6, _a6) asm ("r9") = __arg6;            \
    register TYPEFY (arg5, _a5) asm ("r8") = __arg5;            \
    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;           \
    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;           \
    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \
    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \
    asm volatile (                          \
    "syscall\n\t"                           \
    : "=a" (resultvar)                          \
    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),     \
      "r" (_a5), "r" (_a6)                      \
    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \
    (long int) resultvar;                       \
})

mà tôi cảm thấy khá tự giải thích. Lưu ý cách thức này dường như đã được thiết kế để khớp chính xác với quy ước gọi của các hàm ABI System V thông thường: https://en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions

Nhắc nhở nhanh chóng về các clobbers:

  • cccó nghĩa là thanh ghi cờ. Nhưng Peter Cordes bình luận rằng điều này là không cần thiết ở đây.
  • memory có nghĩa là một con trỏ có thể được truyền trong lắp ráp và được sử dụng để truy cập bộ nhớ

Đối với một ví dụ có thể chạy tối thiểu rõ ràng từ đầu, xem câu trả lời này: Làm thế nào để gọi một cuộc gọi hệ thống thông qua sysenter trong lắp ráp nội tuyến?

Tạo một số tòa nhà trong lắp ráp bằng tay

Không khoa học lắm, nhưng vui:

  • x86_64.S

    .text
    .global _start
    _start:
    asm_main_after_prologue:
        /* write */
        mov $1, %rax    /* syscall number */
        mov $1, %rdi    /* stdout */
        mov $msg, %rsi  /* buffer */
        mov $len, %rdx  /* len */
        syscall
    
        /* exit */
        mov $60, %rax   /* syscall number */
        mov $0, %rdi    /* exit status */
        syscall
    msg:
        .ascii "hello\n"
    len = . - msg
    

    GitHub ngược dòng .

aarch64

Tôi đã hiển thị một ví dụ về vùng người dùng có thể chạy tối thiểu tại: /reverseengineering/16917/arm64-syscalls-table/18834#18834 Mã hạt nhân TODO grep ở đây, thật dễ dàng.


1
Các "cc"clobber là không cần thiết: syscalls Linux lưu / khôi phục RFLAGS (The syscall/ sysrethướng dẫn thực hiện điều đó bằng R11, và hạt nhân không thay đổi R11 lưu / RFLAGS khác hơn là thông qua ptracecác cuộc gọi hệ thống gỡ lỗi.) Không phải là nó bao giờ quan trọng, bởi vì một "cc"clobber là ẩn cho x86 / x86-64 trong GNU C Mở rộng asm, vì vậy bạn không thể đạt được bất cứ điều gì bằng cách loại bỏ nó.
Peter Cordes
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.