Các biến tĩnh được lưu trữ ở đâu?


7

Giả sử tôi đang sử dụng 8051. Tôi đã biên dịch một mã có biến tĩnh. Biến tĩnh đó sẽ được lưu trữ ở đâu? Trong RAM? Trong ngăn xếp? Trên đống ?? Trong chớp mắt? Ở đâu?

Ngoài ra, hãy sửa tôi nếu tôi sai: CONST được lưu trong ROM. Và các biến toàn cục được lưu trữ trong Flash. (Nếu tôi không có Flash thì sao?)

Tôi đang mong đợi câu trả lời liên quan đến Lập trình nhúng. Nó không giống như trong Phân đoạn mã hoặc .bss, nhưng chính xác là ở đâu trên bảng của tôi?


2
Tôi hy vọng các biến tĩnh sẽ được lưu trữ ở cùng một nơi với các biến toàn cục. Rốt cuộc, chúng là cùng một thứ với phạm vi khác nhau. (hãy cho tôi biết nếu tôi sai)
user606723

Câu trả lời:


7

Câu trả lời sau đây dựa trên kinh nghiệm của tôi khi xem mapfiles, nếu tôi sai về sth. làm ơn sửa cho tôi

Các vars tĩnh chắc chắn không được lưu trữ trên heap, vì điều này chỉ dành cho các biến được phân bổ trong thời gian chạy (và các vars tĩnh được phân bổ trong thời gian biên dịch).

Các biến tĩnh được lưu trữ trong RAM, giống như các biến toàn cục của bạn. Phạm vi của một biến nhất định chỉ quan trọng đối với trình biên dịch, ở cấp mã máy không ai ngăn bạn đọc biến cục bộ bên ngoài hàm (miễn là bộ điều khiển của bạn không có một số tính năng ưa thích để bảo vệ các vùng nhớ khỏi bị truy cập) .

Và các biến toàn cục được lưu trữ trong Flash.

Không. Hãy nghĩ về nó: Để viết một chút flash, bạn phải xóa toàn bộ khối dữ liệu và sau đó viết lại toàn bộ với dữ liệu đã sửa đổi. Và các bước này không thực hiện trong một chu kỳ như lưu trữ đơn giản vào RAM. Biến toàn cục được lưu trữ trong RAM, giống như đã đề cập trước đó. Điều này cũng giải quyết sự nhầm lẫn của bạn về các hệ thống không có flash.


1
"Biến tĩnh" được biết tại thời điểm biên dịch không phải là biến, mà là hằng số. Các biến tĩnh được gán và thay đổi tại thời gian chạy. Sự khác biệt với các biến khác là phạm vi và thời gian tồn tại của chúng: chúng tồn tại miễn là chương trình tồn tại.
stevenvh

@stevenvh: Tôi có thể nghĩ về các ví dụ về các biến tĩnh, chắc chắn không phải là hằng số. Nếu bạn đã đúng, điều đó không có nghĩa là consttừ khóa sẽ vô dụng?
0x6d64

1
Bạn đã chỉnh sửa câu trả lời của mình, nhưng cách nó được diễn đạt giống như được biết đến vào thời gian biên dịch là tiêu chí cơ bản để gọi nó là tĩnh. Bạn hoàn toàn có thể xác định các biến tĩnh có giá trị không được biết tại thời điểm biên dịch; bạn có thể khai báo chúng mà không cần gán.
stevenvh

10

Giả sử tôi đang sử dụng 8051.

Sau đó, bạn phải biết về bộ nhớ CODE, DATA, IDATA, XDATA và PDATA - 8051 là một kiến ​​trúc đa Harvard.

Biến tĩnh đó sẽ được lưu trữ ở đâu?

Đó là một câu hỏi hay. Nó sẽ phụ thuộc vào các cài đặt trình biên dịch - thường được gọi là "mô hình bộ nhớ"; Nhưng bạn cũng có thể nói rõ ràng trình biên dịch sẽ đặt nó ở đâu:

xdata unsigned int i;  // integer in XDATA memory

Trình biên dịch / trình liên kết sẽ có thể tạo một tệp Map, nó sẽ hiển thị cho bạn các địa chỉ của các biến của bạn.

CONST được lưu trữ trong ROM.

Điều này có thể phụ thuộc vào trình biên dịch và cần được kiểm tra đối với tệp Map. Tôi nhớ gắn thẻ những cái đó rõ ràng:

code const char fooStr[]="Foo";  // string constant in code = flash memory

Và các biến toàn cục được lưu trữ trong Flash

Cả đúng và sai. Chúng nằm trong một trong những bộ nhớ dữ liệu của 8051, nhưng giá trị ban đầu sẽ được tải từ Flash khi khởi động - trừ khi biến được khởi tạo bằng 0.


2

Trên các bộ xử lý nơi lưu trữ mã nằm trong cùng một không gian địa chỉ với tất cả các biến khác, trình biên dịch thường sẽ đặt các biến toàn cục hoặc biến tĩnh "const" vào phần liên kết của riêng chúng và các trình liên kết thường sẽ được cấu hình để đặt phần đó vào mã của hệ thống lưu trữ (flash, OTP, hoặc bất cứ điều gì). Điều này sẽ làm giảm dung lượng RAM theo yêu cầu của chương trình và sẽ giảm lượng công việc mà mã khởi động phải làm.

Trên các bộ xử lý có kho lưu trữ mã ở một không gian địa chỉ khác (ví dụ PIC hoặc 8051), một số trình biên dịch sẽ sử dụng constvòng loại để báo hiệu rằng chúng nên đặt các biến vào kho lưu trữ mã và sử dụng các hướng dẫn khác nhau để truy cập chúng, trong khi các trình biên dịch khác sẽ không . Các trình biên dịch như vậy sẽ yêu cầu chỉ các con trỏ có constvòng loại có thể được sử dụng để truy cập constcác biến được khai báo, vì không có yêu cầu đó, các trình biên dịch sẽ không biết rằng các hướng dẫn đặc biệt phải được sử dụng để truy cập các con trỏ đó.

Trên các trình biên dịch 8051 mà tôi đã thấy (Archimedes và Keil), có 8051 từ khóa dành riêng cho trình biên dịch __data, __idata, __code, __bdata, _ pdata và _xdata có sẵn để chỉ ra rằng các biến nên được tải trong một không gian địa chỉ cụ thể. Theo mặc định, tên có thể được sử dụng có hoặc không có dấu gạch dưới; các phiên bản không gạch dưới thuận tiện hơn, nhưng có thể bị vô hiệu hóa, ví dụ: một phiên bản đang chuyển một chương trình sử dụng mã định danh có tên codehoặc data). Nếu một con trỏ được khai báo mà không áp dụng một trong những từ khóa đó cho mục tiêu của nó, trình biên dịch sẽ phân bổ ba byte: một để chỉ ra không gian bộ nhớ mà mục tiêu đang ở và hai để giữ địa chỉ 16 bit nếu cần. Khai báo một biến constmà không áp dụngcodevòng loại sẽ khiến biến được đặt trong không gian địa chỉ RAM mặc định và được tải với giá trị mặc định khi khởi động; một biến được khai báo theo cách đó có thể được chuyển đến mã mong đợi một con trỏ trong không gian địa chỉ mặc định (nhưng sẽ sử dụng RAM). Thêm một khai báo __code(hoặc code, nếu được bật) sẽ khiến biến được đặt trong không gian mã. Sử dụng codekhai báo thường tốt hơn không, nhưng trong một số trường hợp, đặc biệt là nếu mục được đề cập là nhỏ, việc dễ dàng truy cập mọi thứ trong idataRAM có thể bù đắp cho việc mất một vài byte dung lượng đó.


0

Trả lời một phần: "Ngoài ra, hãy sửa tôi nếu tôi sai: CONST được lưu trong ROM."

Sai. Từ khóa 'const' là một chỉ thị để giúp trình biên dịch. Khi một biến được khai báo là 'const' thì trình biên dịch sẽ biết nó không thể thay đổi, nhưng nó vẫn là một biến được cấp phát một vị trí bộ nhớ.

Nếu bạn cần / muốn lưu trữ nó trong ROM, thì bạn sẽ cần sử dụng một từ khóa khác cho trình biên dịch cho nó biết loại bộ nhớ hoặc vị trí sẽ sử dụng. Tôi không nghĩ rằng có một từ khóa được tiêu chuẩn hóa cho việc này. Có lẽ bởi vì C bắt đầu cuộc sống trên PC với tất cả không gian chương trình và không gian biến đổi là RAM.

Đối với PIC, bạn sẽ sử dụng từ khóa 'rom' để khai báo biến.

ví dụ: "rom int const x = 42; '


Đôi khi vị trí của một biến const được kiểm soát bởi một từ khóa không chuẩn. Lưu ý rằng thường có một cách để cấu hình trình liên kết để xác định nơi các biến const được lưu trữ. Điều này, tất nhiên, thay đổi theo từng chuỗi công cụ.
semaj

0

Tĩnh ngụ ý biến được tách biệt với tệp / hàm / vùng mã đó. Nơi được định nghĩa, cả hai chỉ hiển thị ở đó và khi được sử dụng trên các phi toàn cầu về cơ bản biến biến đó thành toàn cầu từ góc độ lưu trữ. Biến cục bộ có định nghĩa tĩnh có nghĩa là tôi muốn không mất giá trị đó từ một cuộc gọi của hàm này sang hàm khác, vì vậy nó phải được lưu trữ trên toàn cầu cho hàm đó, thông thường một biến cục bộ nằm trên ngăn xếp để hàm có thể được tái entrant (một bản sao mới của các biến cục bộ cho mỗi mục nhập vào hàm). Vì vậy, toàn cầu tĩnh là toàn cầu, dù sao thì địa phương tĩnh là cục bộ nhưng được lưu trữ cùng với toàn cầu. Trong những gì thường được gọi là .data nhưng bộ công cụ có thể có tên khác nhau.

int x = 7;

được cất giữ. Biến toàn cục hoặc cục bộ tĩnh không được khởi tạo khi được xác định

int y;

là trong những gì thường được gọi là .bss. Đây là một đoạn khác của bộ nhớ đọc / ghi, nhưng bộ nhớ này trước khi bắt đầu hàm main () là 0 đối với bạn để theo thông số kỹ thuật hoặc mỗi giả định các biến đó bằng 0 khi chương trình của bạn bắt đầu.

const là một cách để nói rằng tôi đang tuyên bố đây là một biến chỉ đọc, tôi không có kế hoạch cho mọi lưu trữ cho nó chỉ đọc từ nó. Vì vậy, trình biên dịch có thể chọn (thực ra đó là lập trình viên vì cuối cùng họ chỉ ra những gì trình liên kết thực hiện, thường để cho tập lệnh liên kết mặc định được sử dụng và không đảm nhận công việc đó) cho dù đó là flash hay ram, nó có thể đi vào và làm việc bình thường.

Đối với vi điều khiển và những nơi khác mà bạn cần khởi động và bắt đầu chạy từ bộ nhớ không bay hơi (flash / rom / vv). Trước hết, chương trình phải được lưu trữ trong một cái gì đó không dễ bay hơi. Tiếp theo công cụ .data, những thứ bạn đã khởi tạo trong mã của mình khi xác định biến, những thứ mà tại thời gian biên dịch có thể được xác định. cũng phải ở trong bộ lưu trữ không bay hơi, nhưng cuối cùng dữ liệu đó được đọc / ghi để mã bootstrap chạy trước hàm main () được thực hiện, thực hiện công việc sao chép các khối .data vào bộ nhớ đọc / ghi. Mã .bss hoặc các biến cục bộ toàn cục hoặc tĩnh không được khởi tạo và được coi là 0 khi bạn bắt đầu, chúng không cần bộ nhớ không bay hơi, chỉ cần vị trí và bao nhiêu, và từ đó bootstrap có thể đọc / ghi nhớ.

Có nhiều lý do tại sao chúng ta giao tiếp bằng các thuật ngữ như .text, .data, .bss, .rodata, v.v. Bởi vì chúng ta thấy rằng các công cụ đặt các yếu tố của chương trình của chúng ta vào những nơi đó và sau đó chúng ta có thể thấy những nơi đó phải sống ở đâu lưu trữ dễ bay hơi và sau đó trong thời gian chạy nếu điều đó là khác nhau. .text mặc dù ngớ ngẩn, là chương trình của chúng tôi, mã máy và dữ liệu liên quan khác. .data là các biến từ chương trình của chúng tôi được khởi tạo trước khi bắt đầu khác không, vì vậy chúng phải được lưu trữ trong bộ lưu trữ không bay hơi sau đó chuyển sang đọc / ghi trước khi sử dụng chúng. .bss là các biến từ chương trình của chúng tôi được coi là 0 khi chúng tôi bắt đầu, do đó, số lượng và vị trí cần được lưu trữ trong trạng thái không bay hơi và boostrap có thể thực hiện zeroing (hoặc đôi khi chúng chỉ được lưu trữ dưới dạng một số không trong đèn flash / rom là tốt). .

Sau đó, có các thuật ngữ heap và stack, thường sau chương trình của bạn nếu cần, .bss và .data tiêu thụ một lượng ram, thường là từ các địa chỉ thấp hơn trở lên. sau đó phần còn lại của ram được chia thành đống và chồng, đôi khi không có một đường thẳng chắc chắn giữa chúng, các chương trình hành vi xấu có thể có đống và đống va chạm gây ra sự cố. ngăn xếp thường là từ trên xuống và đống thường là từ dưới lên, nhưng đây không phải là quy tắc cứng và nhanh.

Những thứ này ở đâu trên bảng của bạn? tốt, nó phụ thuộc cả vào chip và bo mạch vì các tùy chọn là gì sau đó tùy thuộc vào bạn lập trình viên quyết định khi bạn điều khiển quá trình biên dịch và liên kết. Hầu hết mọi người đều lấy một ví dụ hoặc một chuỗi công cụ biết về hệ thống của bạn và bạn để các cài đặt mặc định. Nhưng bạn có trách nhiệm hoàn toàn. Để vi điều khiển khởi động, bạn phải có cách để làm điều đó, thường là flash hoặc tắt chip tùy thuộc vào mcu, và những thứ không bay hơi được đề cập ở trên phải được lưu trữ ở đó hoặc ở một nơi không bay hơi khác . Tương tự như vậy, bạn có một số ram, bạn phải chia nó ra với những thứ đọc / ghi bạn cần bao gồm cả stack và heap nếu bạn đủ can đảm để sử dụng nó trong một hệ thống như vậy (không khôn ngoan). Một số bộ xử lý ngăn xếp là một phần của thiết kế và bạn không phải lo lắng về, những người khác bạn làm. Nếu bạn có bội số của những thứ này, ram không biến động hoặc đọc / ghi thì thật tuyệt, bạn có thể chọn và chọn nơi đặt đồ.

nếu bạn sử dụng một toolchain từ ai đó hoặc có quyền truy cập vào những cái khác nhau, không có lý do gì để cho rằng họ sẽ làm điều tương tự chính xác với chương trình của bạn với tập lệnh liên kết mặc định của họ. thông thường các bộ công cụ cung cấp các tệp bản đồ hoặc các cách khác để xem nơi họ đã đặt mọi thứ cho bạn.

chắc chắn có thể có một hệ thống dựa trên vi điều khiển không có đèn flash, mỗi lần nghe thấy chuột hay bàn phím? Một số cùng với nhiều sản phẩm khác có thể hoạt động mà không cần những thứ như vậy. Ví dụ, một số có thể có logic của chip để quản lý bảng liệt kê usb, sau đó trình điều khiển hệ điều hành cho sản phẩm đó chứa phần sụn, tải phần sụn để ram trên thiết bị và khởi động bộ xử lý và có thể liệt kê lại usb rằng bây giờ nó là một con chuột hoặc bất cứ điều gì. không phải ai cũng làm điều đó nhưng đôi khi nó được thực hiện Tương tự như vậy, bạn có thể có một số thiết kế khác trong đó một số phần cứng hoặc giải pháp khác tải chương trình vào chip / ram trước khi khởi động bộ xử lý một cách hiệu quả khiến nó có cảm giác như bộ xử lý đó không có đèn flash. Nhưng bạn vẫn có cùng .text, .data,.


-1

Mặc dù câu hỏi của bạn có liên quan đến 8051 và nhiều câu trả lời đúng đã được đề xuất, tôi cũng muốn bao gồm một câu trả lời cho những người đến đây chỉ bằng cách đọc câu hỏi của bạn chứ không phải chi tiết. Tôi muốn cung cấp một vài liên kết cho kiến ​​trúc ARM trên Dòng vi điều khiển LPC sử dụng Keil IDE. Đây là một vài liên kết quan trọng giúp tôi hiểu hành vi của các biến được đặt ở đâu:

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.