2010-07-29 24 views
14

Tôi vừa mới nhận thấy một số mã ngôn ngữ lắp ráp lạ của phương thức chính trống.Giải thích việc lắp ráp lạ của hàm C `main` trống bằng trình biên dịch Visual C++

//filename: main.c 
void main() 
{ 

} 

tháo:

push  ebp 
mov   ebp,esp 
sub   esp,0C0h; why on the earth is it reserving 192 bytes? 
push  ebx 
push  esi 
push  edi ; good compiler. Its saving ebx, esi & edi values. 
lea   edi,[ebp-0C0h] ; line 1 
mov   ecx,30h ; line 2 
mov   eax,0CCCCCCCCh ; line 3 
rep stos dword ptr es:[edi] ; line 4 


xor   eax,eax ; returning value 0. Code following this line is explanatory. 
pop   edi ; restoring the original states of edi,esi & ebx 
pop   esi 
pop   ebx 
mov   esp,ebp 
pop   ebp 
ret 
  1. tại sao trên trái đất là nó đặt 192 byte cho chức năng mà không có bất kỳ biến
  2. whats up với bốn dòng: dòng 1, dòng 2, dòng 3, dòng 4? nó đang cố gắng làm gì & TẠI SAO?
+0

tại sao cú pháp mã không được đánh dấu? – claws

+0

Lắp ráp nào được tạo ra khi bạn lắp ráp một tuyên bố chính không trống, và điều gì xảy ra khi bạn thay đổi kiểu trả về của main thành int? –

+5

Thật đáng để chỉ ra rằng lợi nhuận chính int. Sử dụng void cho main không phải là juju tốt. – nmichaels

Trả lời

15

Bốn dòng mã bạn đã chỉ định là trình gỡ lỗi xóa không gian biến cục bộ bằng giá trị đặc biệt "rõ ràng" (0xCCCCCCCC). Tôi không chắc chắn tại sao có 192 byte của không gian dường như đã chết, nhưng đó có thể là VC + + xây dựng một số không gian bảo vệ vào khu vực biến địa phương của bạn để cố gắng phát hiện ngăn xếp đập.

Bạn có thể sẽ nhận được một đầu ra rất khác nếu bạn chuyển từ Debug sang Release build.

+1

tại sao '0xCCCCCCCC' = '1100 1100 1100 1100 1100 1100 1100 1100'? sẽ không thanh toán bù trừ với 0x00000000 sẽ có ý nghĩa hơn? – claws

+0

@claws: Microsoft đã chọn giá trị đó vì nó khác biệt và dễ xác định nếu chương trình của bạn kết thúc bằng biến chưa được khởi tạo. Việc sử dụng zero sẽ che dấu rất nhiều lỗi tiềm ẩn vì thường các biến sẽ được khởi tạo bằng 0, và việc trình biên dịch làm như vậy trong một bản xây dựng gỡ lỗi sẽ khiến bản phát hành bị lỗi. –

+0

@Greg Hewgill: Cách xem tháo gỡ trong cấu hình Phát hành trong Visual Studio? Tôi đã đặt một breakpoint tại khung đóng và xem tháo gỡ. Điều này dường như không hoạt động ở chế độ phát hành. – claws

18

Greg đã giải thích cách trình biên dịch tạo mã để chẩn đoán các biến cục bộ chưa được khởi tạo, được bật bởi tùy chọn biên dịch/RTCu. Giá trị 0xcccccccc được chọn để phân biệt và dễ dàng nhận ra trong trình gỡ lỗi. Và để đảm bảo các chương trình bom khi một con trỏ uninitialized là dereferenced. Và để đảm bảo nó chấm dứt chương trình khi nó được thực thi dưới dạng mã. 0xcc là khá lý tưởng để làm tất cả những công việc này tốt, đó là opcode hướng dẫn cho INT3.

192 byte bí ẩn được phân bổ trong khung ngăn xếp ở đó để hỗ trợ tùy chọn biên tập Edit + Continue,/ZI. Nó cho phép bạn chỉnh sửa mã trong khi điểm ngắt đang hoạt động. Và thêm các biến cục bộ vào một hàm có 192 byte có sẵn để cung cấp không gian cho những người được thêm vào đó. Vượt quá không gian đó sẽ làm cho IDE buộc bạn phải xây dựng lại chương trình của mình.

Btw: điều này có thể gây ra sự cố nếu bạn sử dụng đệ quy trong mã của mình. Việc xây dựng gỡ lỗi sẽ đánh bom với tên của trang web này nhanh hơn rất nhiều. Thông thường không nhiều vấn đề, bạn gỡ lỗi với kích thước tập dữ liệu thực tế.

+2

Lên, để cung cấp thông tin tối nghĩa nhưng hấp dẫn. – mickeyf

+0

Điều bạn nói là chính xác http://stackoverflow.com/questions/370195/when-and-why-will-an-os-initialise-memory-to-0xcd-0xdd-etc-on-malloc-free-new –

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