2011-01-05 36 views
13

Tôi tương đối mới đối với tất cả các công cụ cấp thấp này, ngôn ngữ lắp ráp .. và muốn tìm hiểu thêm chi tiết. Tại sao có sự khác biệt giữa Linux, ngôn ngữ Windows Assembly?Tại sao có sự khác biệt giữa các ngôn ngữ lắp ráp như Windows, Linux?

Khi tôi hiểu khi biên dịch mã C Hệ điều hành không thực sự tạo ra mã máy hoặc mã lắp ráp thuần túy, nó tạo mã nhị phân phụ thuộc OS. Nhưng tại sao?

Ví dụ khi tôi sử dụng hệ thống x86, CPU chỉ hiểu x86 ASM đúng không? Tại sao chúng tôi không viết mã assembly x86 thuần túy và tại sao có các biến thể lắp ráp khác nhau dựa trên hệ điều hành? Nếu chúng ta viết ASM thuần túy hoặc hệ điều hành sản xuất ASM thuần túy thì sẽ không có vấn đề tương thích nhị phân giữa các hệ điều hành hay không?

Tôi thực sự tự hỏi mọi lý do đằng sau chúng. Bất kỳ câu trả lời chi tiết, bài viết, cuốn sách sẽ là tuyệt vời. Cảm ơn.

+2

khác biệt duy nhất là: phương pháp bạn sử dụng phụ thuộc vào hệ điều hành. ví dụ: phương thức C printf() sẽ làm điều gì đó khác trên OS bởi vì mọi HĐH xử lý nó theo cách khác. –

Trả lời

13

Không có sự khác biệt. Mã lắp ráp là giống nhau nếu bộ vi xử lý giống nhau. mã x86 được biên dịch trên Windows là nhị phân tương thích với mã x86 trên Linux. Trình biên dịch không tạo mã nhị phân phụ thuộc vào hệ điều hành, nhưng nó có thể gói mã theo một định dạng khác (ví dụ: PE so với ELF).

Sự khác biệt là thư viện được sử dụng. Để sử dụng công cụ hệ điều hành (ví dụ I/O), bạn phải liên kết với các thư viện của hệ điều hành. Không có gì đáng ngạc nhiên, các thư viện hệ thống Windows không có sẵn trên máy Linux (trừ khi bạn có Wine) và ngược lại.

+0

Vậy tại sao có các ngôn ngữ Assembly khác nhau Windows Asm, Linux Asm, Dos Asm? – mcaaltuntas

+0

@mcaaltuntas: Không cần thiết. Sự khác biệt nằm trong cách mà các tài nguyên được sử dụng (các cuộc gọi OS, về cơ bản), không nằm trong tập lệnh. – Piskvor

+5

@mcaaltuntas: không có. có x86 lắp ráp, lắp ráp x86_64, lắp ráp mips, lắp ráp m68k ... không lắp ráp linux hoặc cửa sổ lắp ráp –

3

Trừ khi bạn đang sử dụng môi trường phát triển hệ thống nhúng, bạn đang biên dịch với các trình biên dịch được nhắm mục tiêu đến một thời gian chạy cụ thể. Thời gian chạy đó xác định các quy ước cho việc sử dụng phần cứng: chuyển đối số, xử lý ngoại lệ, v.v. Các quy ước này tương tác với hệ điều hành hoặc ít nhất với các thư viện thời gian chạy có sẵn mà chương trình cần liên kết.

1

Hệ điều hành xác định hai thứ: (1) calling convention, xác định cách tham số đi vào ngăn xếp và do đó tác động đến mã lắp ráp và (2) thư viện thời gian chạy thực hiện các chức năng phổ biến như phân bổ bộ nhớ, đầu vào/đầu ra, toán cấp cao hơn, v.v.

Vì vậy, trong khi x+y biên dịch thành cùng một mã lắp ráp trong Windows hoặc Linux trên bộ vi xử lý x86, y = sin(x) sẽ khác nhau do một quy ước gọi khác và thư viện toán khác.

Ngoài ra, ngôn ngữ lắp ráp cũng phụ thuộc vào bộ xử lý. x86, x86_64, ARM, PowerPC, đều có ngôn ngữ lắp ráp riêng.

3

Lắp ráp Linux lịch sử có xu hướng được thực hiện bằng cách sử dụng cú pháp AT & T, vì đây là những gì mà các hỗ trợ GNU Assembler hỗ trợ. Tương tự như vậy, các nhà lắp ráp Windows có xu hướng sử dụng cú pháp Intel, như với MASMNASM.

Tất cả các trình tạo x86 tạo ra cùng một đầu ra - tức là, mã máy x86. Và bạn có thể sử dụng NASM hoặc GNU Assembler trên Linux để lập trình theo cú pháp của Intel và GNU Assembler trên Windows để lập trình theo cú pháp AT & T.

+2

Các công cụ GNU (bao gồm gdb) hỗ trợ cả hai cú pháp & & intel trong các phiên bản hiện tại. Tôi thường đặt intel-syntax; nó làm cho mọi việc trở nên dễ dàng hơn nhiều, đặc biệt khi làm việc với các công cụ như Ida Pro cùng một lúc –

4

Vâng, bạn không chạy lắp ráp thẳng. Mã phải ở trong một số loại định dạng có thể thực thi: các cửa sổ sử dụng PE, hầu hết các Unices đều sử dụng ELF ngay bây giờ (mặc dù đã có những người khác, như a.out).

Hướng dẫn lắp ráp cơ sở giống nhau và các chức năng bạn tạo với chúng giống nhau.

Sự cố đi kèm với quyền truy cập vào các tài nguyên khác. Bộ xử lý thực sự tốt khi tính toán, nhưng không thể truy cập đĩa cứng hoặc in một ký tự vào màn hình hoặc kết nối với điện thoại Bluetooth. Những yếu tố này luôn luôn phụ thuộc vào một số hệ điều hành. Chúng được thực hiện dưới dạng syscalls, nơi bộ xử lý báo hiệu hệ điều hành để thực hiện một tác vụ nào đó. Nhiệm vụ số 17 trên Linux không nhất thiết là nhiệm vụ 17 trên các cửa sổ; họ thậm chí có thể không có tương đương.

Vì hầu hết các thư viện có một số syscalls ở mức thấp nhất của chúng, đây là lý do tại sao mã không thể được biên dịch lại trong mọi trường hợp.

+0

+1 Tôi tin rằng đó là một trong những lý do chính: các định dạng tệp thực thi khác nhau. – karlphillip

1

Không có sự khác biệt trong ngôn ngữ lắp ráp (mặc dù có thể có sự khác biệt giữa các trình lắp ráp, và do đó các ký hiệu được sử dụng), miễn là chúng tôi gắn bó với x86. Cả Linux và Microsoft Windows đều chạy trên các kiến ​​trúc khác, nhiều hơn thế trong trường hợp của Linux.

Tuy nhiên, một hệ điều hành hiện nay không chỉ tải chương trình vào bộ nhớ và để nó đi. Nó cung cấp một lượng lớn các dịch vụ. Vì nó cũng bảo vệ các chương trình với nhau, nó áp đặt các hạn chế. Để làm bất cứ điều gì khác hơn là tính toán cơ bản, nó thường là cần thiết để đi qua hệ điều hành. (Điều này ít đúng với các hệ điều hành cũ hơn, như MS-DOS và CP/M, có thể tải các chương trình chạy độc lập, nhưng hiện nay hầu hết mọi hệ thống không được nhúng đều có hệ điều hành hiện đại.)

Cũng không phải là chương trình được lưu trữ dưới dạng các đốm màu nhị phân đơn giản. Nó thường cần thiết để liên kết với các thư viện khác, thường là chương trình được nạp để thực thi (đó là cách các DLL làm việc, ví dụ), và nó là cần thiết để liên kết với hệ điều hành. Có thể có các thông tin khác mà hệ điều hành yêu cầu và do đó phải có một số loại thông tin về blob nhị phân trong tệp thi hành. Điều này thay đổi giữa các hệ điều hành.

Do đó, tệp thực thi phải ở định dạng được tải vào bộ nhớ và điều này thay đổi từ OS sang OS. Để làm bất cứ điều gì hữu ích, họ phải thực hiện các cuộc gọi hệ điều hành, khác nhau giữa các hệ thống. Đó là lý do tại sao bạn không thể thực thi Windows và các thư viện liên quan và chạy nó trên Linux.

0

Có tồn tại một vài bộ ghép cho các nền tảng khác nhau, được cung cấp tệp nguồn, sẽ tạo ra tệp nhị phân đầu ra trực tiếp được thiết kế để tải tại một địa chỉ cụ thể. Những người lắp ráp như vậy đã được phổ biến cho một số vi điều khiển nhỏ, hoặc cho một số bộ vi xử lý lịch sử như 6502 và Z80. Khi lắp ráp chương trình, nó sẽ là cần thiết để biết địa chỉ nơi nó sẽ được dự kiến ​​sẽ cư trú; sử dụng một địa chỉ khác sẽ yêu cầu lắp ráp lại chương trình. Mặt khác, lắp ráp trong một hệ thống như vậy là một quá trình một bước. Chạy trình assembler trên mã nguồn và nhận được một đầu ra thực thi. Trong một số trường hợp, nó sẽ có thể có mã nguồn, lắp ráp, và đầu ra tất cả trong bộ nhớ cùng một lúc (trên Commodore 64 của tôi, tôi đã sử dụng một assembler được xuất bản trong tạp chí Gazette của Compute làm việc như thế).

Mặc dù ghép lại mọi thứ bất cứ khi nào thay đổi địa chỉ có thể là thực tế cho một chương trình sẽ "chiếm đoạt máy", trong nhiều trường hợp, bạn nên sử dụng quy trình nhiều bước trong đó tệp nguồn được xử lý thành tệp mã đối tượng , chứa các hướng dẫn lắp ráp nhưng cũng chứa các loại thông tin "tượng trưng" khác nhau về chúng; các tệp này sau đó được xử lý theo nhiều cách khác nhau để tạo ra một hình ảnh bộ nhớ có thể được tải trực tiếp vào bộ nhớ, hoặc một tệp đối tượng có thể di chuyển được kết hợp mà trình tải của hệ điều hành sẽ biết cách điều chỉnh cho bất kỳ địa chỉ nào mà nó có thể được tải .

Để hệ thống liên kết đối tượng hữu ích, nó phải cho phép một số loại tính toán địa chỉ được trì hoãn cho đến khi chương trình được liên kết hoặc được tải. Một số hệ thống chỉ cho phép tính toán cực kỳ đơn giản được thực hiện tại thời gian tải/liên kết, trong khi các hệ thống khác cho phép tính toán phức tạp hơn. Các sơ đồ đơn giản hơn có thể hiệu quả hơn khi chúng có thể thực hiện được, nhưng các hạn chế của chúng có thể bắt buộc các giải pháp thay thế. Ví dụ, một thói quen mà sẽ được sử dụng BX để lặp thông qua một cấu trúc dữ liệu với ít hơn 256 byte có thể được viết như một cái gì đó như:

mov bx,StartAddr 

lp: mov al, [bx] ... làm một số tính toán inc bx cmp bl, < (StartAddr + Length); Nhà điều hành tiền tố < có nghĩa là "LSB của" jnz lp

Có thể sử dụng cmp bx,(StartAddr+Length), nhưng nếu công cụ biên dịch có thể hỗ trợ, so sánh chỉ với byte thấp sẽ nhanh hơn. Mặt khác, một số loại công cụ lắp ráp/liên kết 16 bit có thể yêu cầu tất cả các bản sửa lỗi địa chỉ phải được thực hiện với các địa chỉ 16 bit được lưu trữ trong mã.

Bởi vì các hệ thống khác nhau cho phép các tính năng khác nhau trong định dạng mã đối tượng của chúng, chúng yêu cầu các tính năng khác nhau trong ngôn ngữ lắp ráp của chúng để kiểm soát chúng. Các tập lệnh có thể được chỉ định bởi nhà sản xuất chip, nhưng các tính năng để thể hiện tính toán địa chỉ relocatable thường không.

0

Ngôn ngữ lắp ráp có liên quan đến kiến ​​trúc CPU không phải với O.S., nhưng O.S. có một loạt các chức năng hệ thống được biên dịch trong nhị phân mà chương trình lắp ráp của bạn có thể gọi, bằng cách gọi ngắt. Ví dụ đầu ra đầu vào tiêu chuẩn, hoạt động ecc ....

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