tôi đang cố gắng để có được một bức tranh rõ ràng về người (gọi hoặc callee) là chịu trách nhiệm nội các sắp xếp đống. Trường hợp để lắp ráp 64-bit là khá rõ ràng, rằng đó là bởi gọi.responsiblity của sự liên kết ngăn xếp trong x86 lắp ráp
Đề cập đến System V AMD64 ABI, phần 3.2.2 Stack Khung:
Sự kết thúc của khu vực tranh luận đầu vào sẽ được xếp trên một 16 (32, nếu __m256 được truyền trên stack) ranh giới byte.
Nói cách khác, nó nên được an toàn giả định, mà cho tất cả các điểm nhập cảnh của gọi là chức năng:
16 | (%rsp + 8)
giữ (thêm tám là vì call
implicitely đẩy trở lại địa chỉ trên stack).
Giao diện trong thế giới 32 bit (giả sử cdecl) như thế nào? Tôi nhận thấy rằng gcc
nơi sự liên kết bên hàm được gọi với cấu trúc sau:
and esp, -16
mà dường như chỉ ra, đó là trách nhiệm callee của.
Nói một cách rõ ràng hơn, hãy xem xét đoạn mã sau:
global main
extern printf
extern scanf
section .rodata
s_fmt db "%d %d", 0
s_res db `%d with remainder %d\n`, 0
section .text
main:
start 0, 0
sub esp, 8
mov DWORD [ebp-4], 0 ; dividend
mov DWORD [ebp-8], 0 ; divisor
lea eax, [ebp-8]
push eax
lea eax, [ebp-4]
push eax
push s_fmt
call scanf
add esp, 12
mov eax, [ebp-4]
cdq
idiv DWORD [ebp-8]
push edx
push eax
push s_res
call printf
xor eax, eax
leave
ret
Có cần thiết để sắp xếp ngăn xếp trước khi scanf
được gọi là? Nếu vậy, thì điều này sẽ đòi hỏi giảm %esp
bốn byte trước khi đẩy hai đối số này để scanf
như:
4 bytes (return address)
4 bytes (%ebp of previous stack frame)
8 bytes (for two variables)
12 bytes (three arguments for scanf)
= 28
Mã căn chỉnh 16 byte trông giống như 'và esp, 0xfffffff0' thường là thứ bạn sẽ tìm thấy được thêm vào mã mẫu của' main'. Nhưng đối với mọi liên kết chức năng khác được duy trì bởi chức năng gọi. Tôi nên chỉ ra rằng đối với mã 32 bit, bạn nên làm theo [System V i386 ABI] (https://www.uclibc.org/docs/psABI-i386.pdf). Có, bạn cần phải giữ cho xếp chồng 16-byte liên kết ngay trước khi một cuộc gọi chức năng như 'scanf' vv –
x86 ngăn xếp phải được liên kết trên 4 byte chỉ (kích thước đăng ký chung). vì vậy thường không cần thực hiện các nhiệm vụ đặc biệt để sắp xếp xếp chồng. in x64 - đây là trách nhiệm của người gọi cho stack align trên 16 * x trước khi gọi – RbMm
@RbMm: Theo tôi hiểu, yêu cầu căn chỉnh cho x86 stack trên Linux đã tăng lên. Yêu cầu hiện tại là 16 byte (32 nếu một người vượt qua đối số '_m256'). Phần 2.2.2 của ABI bây giờ có chứa cụm từ này: 'Phần cuối của vùng đối số đầu vào phải được căn chỉnh trên một ranh giới byte 16 (32, nếu __m256 được chuyển vào chồng).' –