2010-03-08 9 views
7

là người mới bắt đầu của asm, tôi đang kiểm tra mã asm gcc -S được tạo để tìm hiểu.tại sao gcc 4.x mặc định dự trữ 8 byte cho ngăn xếp trên linux khi gọi một phương thức?

lý do gcc 4.x đặt trước mặc định 8 byte cho ngăn xếp khi gọi phương thức?

func18 là hàm trống không trả về tham số không có biến cục bộ được xác định. Tôi không thể tìm ra lý do tại sao 8 byte được dành riêng ở đây (không phải bất kỳ diễn đàn/trang web đề cập đến lý do, ppl dường như mang nó cho các cấp) là nó cho% ebp chỉ cần đẩy? hoặc trở về loại ?! nhiều thx!

 .globl _func18 
    _func18: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    .text 
+0

Thực tế, không có hướng dẫn nào có ý nghĩa ... một hàm không có bất kỳ biến cục bộ nào không cần phải thiết lập con trỏ khung – Martin

+0

Nó có thể phụ thuộc vào mức tối ưu hóa. Bạn có thể bao gồm mã được tạo hoàn chỉnh cho hàm này không? –

+2

Không phải là không gian này cho địa chỉ trả về và con trỏ khung ngăn xếp? – jdizzle

Trả lời

0

Là người giàu được đề cập ở trên, đó là tất cả vì tối ưu hóa, hiển thị bên dưới. nhưng tôi vẫn không biết tại sao 8 byte được đặt trước là thứ gì đó được tối ưu hóa ?!

gốc c

void func18() {} 
int main() {return 0;} 

biên dịch mà không cờ tối ưu hóa quy định

.text                     
.globl _func18 
_func18: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    leave 
    ret 
.globl _main 
_main:                      
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    movl $0, %eax 
    leave 
    ret 
    .subsections_via_symbols 

với -os tối ưu hóa cờ, dự trữ không có chồng hơn

.text 
.globl _func18 
_func18: 
    pushl %ebp 
    movl %esp, %ebp 
    leave 
    ret 
.globl _main 
_main: 
    pushl %ebp 
    xorl %eax, %eax 
    movl %esp, %ebp 
    leave 
    ret 
    .subsections_via_symbols 
+2

đặt câu hỏi này vào câu hỏi riêng của bạn, không phải trong câu trả lời riêng – moo

0

Cách dễ dàng để tìm hiểu: Bạn có chức năng trống gọi một hàm khác với một tham số không. Nếu tham số được lưu trữ trực tiếp vào ngăn xếp (không đẩy), thì đó là những gì không gian thêm cho.

+0

Tôi đã thử trước đây, có vẻ như không liên quan với nó – nikcname

8

Một số hướng dẫn yêu cầu các loại dữ liệu nhất định phải được căn chỉnh đến nhiều nhất là ranh giới 16 byte (cụ thể là kiểu dữ liệu SSE __m128). Để đáp ứng yêu cầu này, gcc đảm bảo rằng ngăn xếp ban đầu được sắp xếp 16 byte và phân bổ không gian ngăn xếp theo bội số của 16 byte. Nếu chỉ có địa chỉ trả về 4 byte và con trỏ khung 4 byte cần được đẩy, cần thêm 8 byte để giữ cho ngăn xếp được căn chỉnh với ranh giới 16 byte. Tuy nhiên, nếu gcc xác định rằng căn chỉnh bổ sung là không cần thiết (nghĩa là các kiểu dữ liệu ưa thích không được sử dụng và không có hàm bên ngoài nào được gọi), thì nó có thể bỏ qua bất kỳ hướng dẫn bổ sung nào được sử dụng để căn chỉnh ngăn xếp. Các phân tích cần thiết để xác định điều này có thể yêu cầu một số tối ưu hóa được thực hiện.

Xem thêm tài liệu gcc cho tùy chọn -mpreferred-stack-boundary=num.

+0

thx mark, do đó tất cả để căn chỉnh dữ liệu khi tối ưu hóa với sse, rất hợp lý như tôi vô hiệu hóa tối ưu hóa và subl $ 8 % esp đã biến mất. ref gcc rất hữu ích !!! chỉ 1 điều, trong khi tôi điều chỉnh -mpreferred-stack-ranh giới, đặt phòng chỉ chg giữa 3 và 4, 4-12, nó gậy với 8 byte, tôi nghĩ rằng đặt phòng sau đó nên được 20 byte, không? – nikcname

+0

Nếu bạn đã sử dụng -mpreferred-stack-boundary = 12, thì trong bất kỳ hàm nào gọi hàm bên ngoài, nó sẽ phân bổ không gian ngăn xếp theo bội số của 2^12 = 4096 byte. Nếu bạn không gọi bất kỳ hàm bên ngoài nào thì thường sẽ có thể tìm ra rằng việc duy trì liên kết đó không cần thiết cho mã mà nó đang tạo (phụ thuộc vào phiên bản gcc, tùy chọn và kiến ​​trúc mục tiêu chính xác của bạn). – mark4o

+0

vì vậy bạn có nghĩa là trong trường hợp func mà không gọi func bên ngoài, gcc chỉ dính với 8 byte nào theo mặc định? – nikcname