2017-06-25 16 views
5

Tôi hiện đang học lập trình lắp ráp bằng cách làm theo cuốn sách "lập trình x86 ngôn ngữ lắp ráp" của Kip Irvine.Chức năng của "nhãn dữ liệu" trong bộ lắp ráp x86 là gì?

Trong cuốn sách, tác giả cố gắng giải thích các khái niệm về data label

Nhãn dữ liệu xác định vị trí của một biến, cung cấp một cách thuận tiện để tham khảo các biến trong mã. Sau đây, cho Ví dụ, định nghĩa một biến có tên count:

count DWORD 100 

các lắp ráp gán một địa chỉ số để mỗi nhãn.

Vì vậy, sự hiểu biết của tôi về những gì data label có nghĩa là: nhãn dữ liệu count là một giá trị số là vị trí trong bộ nhớ. Khi tôi sử dụng count trong mã của mình, tôi thực sự đang sử dụng giá trị chứa trong vị trí đó trong bộ nhớ, trong trường hợp này, 100.

Sự hiểu biết của tôi về nhãn dữ liệu có đúng không? Nếu nó có phần không chính xác, ai đó có thể vui lòng chỉ ra sai lầm?

+4

Nhãn dữ liệu là tham chiếu (bí danh) đến địa chỉ bộ nhớ chứa dữ liệu. 'count DWORD 100' tạo ra một nhãn sẽ có một offset mà cuối cùng sẽ được biết khi chương trình được chạy. 'count' là nhãn. Nó cuối cùng sẽ có một địa chỉ. Tại địa chỉ đó, có giá trị 32 bit (DWORD) bằng 100 –

+0

@MichaelPetch vì vậy khi tôi đang sử dụng nhãn dữ liệu 'đếm' trong mã của mình, tôi thực sự đang sử dụng giá trị chứa trong vị trí bộ nhớ đó. nếu tôi muốn biết vị trí thực sự của bộ nhớ 'đếm' thì sao? có thể nhận được giá trị thực tế của vị trí bộ nhớ không? – Thor

+2

trong masm bạn có thể sử dụng từ khóa 'offset' để lấy địa chỉ' count'.Nếu bạn có một chương trình 32 bit 'mov eax, số đếm offset' sẽ di chuyển địa chỉ 32 bit đếm thành eax. 'mov eax, [count]' sẽ di chuyển giá trị 32 bit tại địa chỉ được kết hợp với số đếm trong _EAX_. Bạn cũng có thể lấy địa chỉ của một nhãn bằng _LEA_ sử dụng một cái gì đó như 'lea eax, [count]'. Với _LEA_ (tải địa chỉ hiệu quả), bạn không sử dụng từ khóa 'offset'. –

Trả lời

5

Nhãn là cách tượng trưng để ghi địa chỉ bộ nhớ, không có gì hơn, không có gì ít hơn. Bản thân nhãn không mất khoảng trống và chỉ là một cách hữu ích để cho phép bạn tham khảo vị trí đó trong bộ nhớ sau này.

(Vâng, chúng cũng có thể biến thành các ký hiệu trong tệp đối tượng để cho phép tính địa chỉ số tại thời gian liên kết, thay vì tại thời gian lắp ráp. Nhưng đối với nhãn được xác định và tham chiếu trong cùng một tệp, độ phức tạp này chủ yếu là vô hình; xem bên dưới về các địa chỉ là hằng số thời gian liên kết, không phải là thời gian tập hợp.)

ví dụ:

; NASM syntax, but the concepts apply exactly to MASM as well 
; For MASM, you may need BYTE PTR or whatever size overrides in loads. 
section .rodata  ; or section .data if you want to be able to store here, too. 
COUNT: 
    db 0x12 
FOO: 
    db 0 
BAR: 
    dw 0x80FF  ; same as db 0xff, 0x80 

Tải 4 byte như mov eax, [COUNT] sẽ nhận được 0x80FF0012 (vì x86 là ít người cuối). Tải 2 byte từ FOO như mov cx, [FOO] sẽ nhận được 0xFF00.

Bạn thực sự có thể sử dụng tải chồng lên nhau từ một hằng số theo cách này, ví dụ: với các chuỗi nơi một số là các chất nền của những người khác. Đối với các chuỗi bị vô hiệu hóa, chỉ các hậu tố chung có thể được kết hợp vào cùng một không gian lưu trữ theo cách này.


Điều này có nghĩa là COUNT là biến 4 byte hoặc biến 1 byte? Không, không. Ngôn ngữ hội không thực sự có "biến".

biến là một khái niệm cao cấp mà bạn có thể thực hiện bằng ngôn ngữ lắp ráp với một nhãn một chỉ thị lắp ráp mà bảo lưu một số không gian tĩnh. Lưu ý rằng các nhãn riêng biệt với các chỉ thị db trong ví dụ ở trên.

Nhưng biến không cần phải có bất kỳ dung lượng lưu trữ tĩnh nào: ví dụ: biến truy cập vòng lặp của bạn có thể (và thường phải) chỉ tồn tại trong sổ đăng ký.

Biến thậm chí không cần phải có một vị trí cố định duy nhất.Nó có thể được đổ vào ngăn xếp trong một phần của một chức năng mà nó không được sử dụng, nhưng sống trong sổ đăng ký ở một phần khác của một hàm. Trong mã trình biên dịch tạo ra, các biến thường di chuyển giữa các thanh ghi vì không có lý do vì các trình biên dịch thậm chí không cố gắng sử dụng cùng một thanh ghi cho cùng một biến.


Lưu ý rằng MASM hoàn toàn liên kết nhãn với kích thước toán hạng dựa trên chỉ thị theo sau. Vì vậy, bạn có thể phải viết mov eax, dword ptr [count] nếu mov eax, [count] cung cấp lỗi không khớp với kích thước toán hạng.

Một số người coi đây là một tính năng, nhưng những người khác nghĩ rằng công cụ phép thuật kích thước này là hoàn toàn kỳ lạ. Cú pháp NASM không có bất kỳ phép thuật nào. Bạn có thể cho biết cách một dòng sẽ lắp ráp mà không phải đi và tìm nơi nhãn được xác định. add [count], 1 là một lỗi trong NASM, bởi vì không có gì ngụ ý một toán hạng.

Đừng ngại khi nghĩ rằng mọi thứ bạn sử dụng biến trong C phải có bộ nhớ tĩnh với nhãn trong chương trình ngôn ngữ lắp ráp. Nhưng nếu bạn muốn sử dụng thuật ngữ "biến" để lưu trữ dữ liệu tĩnh + nhãn như Kip Irvine, hãy tiếp tục.


Cũng lưu ý rằng nhãn dữ liệu không đặc biệt hoặc khác với nhãn mã. Không có gì ngăn bạn viết jmp COUNT. Giải mã 12 00 FF 80 như một (sequence of) x86 hướng dẫn (s) là trái như là một tập thể dục cho người đọc, nhưng (nếu nó trong một trang với quyền thực thi), nó sẽ được lấy và giải mã bởi CPU.

Tương tự, không có gì ngăn bạn tải dữ liệu từ các nhãn mã làm toán hạng bộ nhớ. Nó thường không phải là một ý tưởng tốt cho lý do hiệu suất để trộn mã và dữ liệu (tất cả các CPU sử dụng tách L1D và L1I cache), nhưng điều đó cũng hoạt động. Trong một hệ điều hành điển hình (như Linux), phân đoạn văn bản của một tệp thực thi có chứa mã và các phần dữ liệu chỉ đọc và được ánh xạ với quyền đọc và thực thi. (Nhưng không phải viết cho phép, vì vậy cố gắng để cửa hàng sẽ lỗi trừ khi bạn sửa đổi các điều khoản.)

Một JIT-biên dịch viết mã máy để một bộ đệm và sau đó nhảy ở đó. Nó có thể là một bộ đệm tĩnh với một nhãn, nhưng thường thì nó sẽ là một bộ đệm được cấp phát động có địa chỉ là một biến.


Địa chỉ tĩnh thường là hằng số thời gian liên kết, nhưng thường không phải là hằng số lắp ráp. (Trừ khi bạn đang viết bộ nạp khởi động, hoặc một thứ khác chắc chắn được tải tại địa chỉ đã biết, thì org 0x100 có thể hữu ích.) Điều này có nghĩa là bạn có thể làm mov al, [COUNT+2], nhưng không phải mov al, [COUNT*2]. (Các định dạng tệp đối tượng hỗ trợ chuyển vị số nguyên, nhưng không hỗ trợ toán tử toán học khác). Trong mã PIC, địa chỉ nhãn thậm chí không phải là hằng số thời gian liên kết, nhưng ít nhất trong mã PIC 64 bit bù đắp từ mã đến một nhãn dữ liệu là hằng số liên kết thời gian, vì vậy địa chỉ tương đối RIP có thể được sử dụng mà không có thêm một mức độ gián tiếp (thông qua Bảng bù đắp toàn cầu).

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