2017-08-22 15 views
6

Tôi đã đọc rằng biến số double (8 byte) phải được căn chỉnh 8 byte.Bối rối về căn chỉnh dữ liệu cho các biến kép

Bây giờ nếu tôi đang viết toàn bộ mã cho chương trình của mình, thì tôi có thể biến các biến số double thành 8 byte được căn chỉnh mà không gặp bất kỳ sự cố nào.

Nhưng nói rằng tôi có kịch bản sau: Tôi tạo một hàm tạo biến số double trên ngăn xếp và tôi cung cấp chức năng này cho người khác để sử dụng nó trong chương trình của anh ấy. Bây giờ khi chức năng của tôi được gọi, chức năng của tôi sẽ không có ý tưởng nếu biến số double sẽ được tạo trên một địa chỉ có thể chia cho 8!

Sự cố này có thể giải quyết được không (tôi lưu ý rằng nếu không có sự giải quyết cho vấn đề này), tôi không quan tâm đến sự mất mát hiệu năng không đáng kể từ việc không căn chỉnh các biến số double của tôi.

+0

AFAIK 'gcc' đã căn chỉnh ngăn xếp thành 16 byte, có nghĩa là nó cũng đáp ứng các yêu cầu căn chỉnh 8 byte. –

+0

@ 眠 り ネ ロ ク: Depends.on phiên bản Linux. Tôi không thể nhớ lại khi nào nhưng trước năm 2009, Linux vẫn đang sử dụng SysV i386 ABI lịch sử mà chỉ yêu cầu sự liên kết ngăn xếp 4 byte. GCC thay đổi thành 16 (phá vỡ với ABI ban đầu) và sau đó ABI đã được sửa đổi thành liên kết chồng 16 byte trên một cuộc gọi hàm. Vì vậy, về mặt kỹ thuật, sự liên kết được sử dụng phụ thuộc vào phiên bản Linux. –

+1

@MichaelPetch đúng. Theo https://en.wikipedia.org/wiki/X86_calling_conventions: *** Kể từ phiên bản GCC 4.5 **, ngăn xếp phải được căn chỉnh với ranh giới 16 byte khi gọi một hàm (các phiên bản trước chỉ yêu cầu 4 byte alignment.) * –

Trả lời

6

Bên trong một hàm, bạn có thể buộc ngăn xếp được căn chỉnh 8 byte bằng cách đặt thành không ba bit ít quan trọng nhất của esp. Điều này có thể đạt được bằng phương tiện của hướng dẫn and:

andl $0xfffffff8, %esp 

Các kết quả esp sẽ bằng (nghĩa là .: esp đã được liên kết) hoặc thấp hơn so với trước đó. Vì ngăn xếp trên kiến ​​trúc x86 tăng xuống dưới, kết quả này trong một đệm có kích thước từ 0-7 byte được phân bổ trên ngăn xếp.

Lưu ý rằng nếu esp là liên kết đã 8-byte trước khi thực hiện các hướng dẫn and (ví dụ: ba bit trọng số thấp nhất của nó đã là không), không có đệm ở tất cả (ví dụ: một đệm của 0 byte) được tạo ra trên ngăn xếp.


Khi rời khỏi chức năng, giá trị lưu trước của esp sẽ được khôi phục nếu bạn đang sử dụng các chức năng phổ biến mở đầulời bạt:

myFunction: 
    //prologue: save the current stack frame 
    pushl %ebp 
    movl %esp, %ebp 

    andl $0xfffffff8, %esp 
    //stack now 8-byte aligned 
    //... 

    leave //restore the previous stack frame 
    ret 

Bằng cách này, đệm giao trước đây sẽ bây giờ được deallocated từ stack.

+1

Worth chỉ ra rằng một số quy ước gọi (như phiên bản hiện đại của hệ thống x86 V ABI) đã yêu cầu sự liên kết 16B của '% esp' trước một' call' (vì vậy args trên stack được căn chỉnh, và bạn có thể có được không gian liên kết cho người dân địa phương với sự lựa chọn đúng của bù đắp) –

Các vấn đề liên quan