Tôi quyết định sẽ là vui vẻ để tìm hiểu lắp ráp x86 trong kỳ nghỉ hè. Vì vậy, tôi bắt đầu với một chương trình xin chào thế giới rất đơn giản, mượn các ví dụ miễn phí gcc -S
có thể cho tôi. Tôi đã kết thúc với điều này:câu hỏi lắp ráp i386: tại sao tôi cần phải can thiệp với con trỏ ngăn xếp?
HELLO:
.ascii "Hello, world!\12\0"
.text
.globl _main
_main:
pushl %ebp # 1. puts the base stack address on the stack
movl %esp, %ebp # 2. puts the base stack address in the stack address register
subl $20, %esp # 3. ???
pushl $HELLO # 4. push HELLO's address on the stack
call _puts # 5. call puts
xorl %eax, %eax # 6. zero %eax, probably not necessary since we didn't do anything with it
leave # 7. clean up
ret # 8. return
# PROFIT!
Nó biên dịch và thậm chí cả hoạt động! Và tôi nghĩ rằng tôi hiểu rõ nhất nhất của nó.
Mặc dù, phép thuật xảy ra ở bước 3. Tôi có xóa dòng này hay không, chương trình của tôi sẽ chết giữa cuộc gọi đến puts
và xor
từ lỗi ngăn xếp không đúng. Và tôi có thay đổi $20
thành một giá trị khác không, nó cũng sẽ sụp đổ. Vì vậy, tôi đã đi đến kết luận rằng giá trị này là very
quan trọng.
Vấn đề là, tôi không biết nó làm gì và tại sao cần thiết.
Có ai có thể giải thích cho tôi không? (Tôi đang sử dụng Mac OS, có bao giờ quan trọng không.)
Vì vậy, giá trị trả lại được chuyển trong '% eax'? Tôi nghĩ rằng nó sẽ luôn luôn đi trên stack kể từ khi họ có khả năng có thể lớn hơn 32 bit. Và ngoài ra, tại sao tôi cần phân bổ 24 byte nếu tôi chỉ sử dụng 4 trong số đó? (__EDIT__ nó cũng hoạt động với 4. Vì vậy, tôi đoán ngăn xếp phải được căn chỉnh trên một ranh giới nhất định.) – zneak
Âm thanh giống như nó đang gặp sự cố liên kết, không phải là tràn ngăn xếp. Các giá trị được trả về trong edx: eax, eax hoặc một lát của chúng hoặc một thanh ghi FPU. –
Tôi khá chắc chắn rằng con trỏ ngăn xếp phải được căn chỉnh trên bội số của một DWORD (4 byte) trên x86 vì nó là 32-bit. – erjiang