2008-09-14 39 views
46

Tôi nhớ lại trong ngày với borland biên dịch DOS cũ bạn có thể làm một cái gì đó như thế này:Có cách nào để chèn mã lắp ráp vào C?

asm { 
mov ax,ex 
etc etc... 
} 

Có bán nền tảng cách độc lập để làm điều này bây giờ? Tôi có nhu cầu thực hiện một cuộc gọi BIOS, vì vậy nếu có một cách để làm điều này mà không có mã asm, đó sẽ là hữu ích như nhau đối với tôi.

+0

Xem thêm các liên kết trong [wiki thẻ lắp ráp nội tuyến] (https://stackoverflow.com/tags/inline-assembly/info) để biết cách nhận được quyền này. Thật khó, và gợi ý tốt nhất là https://gcc.gnu.org/wiki/DontUseInlineAsm. Đối với hiệu suất, bất cứ khi nào có thể tinh chỉnh mã nguồn của bạn để giúp trình biên dịch làm cho mã tốt hơn, thay vì sử dụng nội tuyến asm. (ví dụ: bằng cách xem đầu ra asm của trình biên dịch để xem những gì nó không thể tối ưu hóa hoặc nó làm gì sai.) –

Trả lời

54

Sử dụng GCC

__asm__("movl %edx, %eax\n\t" 
     "addl $2, %eax\n\t"); 

Sử dụng VC++

__asm { 
    mov eax, edx 
    add eax, 2 
} 
+0

Trình tạo C++, từ CodeGear, cũng hỗ trợ từ khóa __asm. – stukelly

+0

VS trình biên dịch không hỗ trợ lắp ráp nội tuyến! Tôi đã đốt ngón tay của tôi cố gắng để làm điều đó một vài năm trước đây! –

+2

@JayD: trình biên dịch VS hỗ trợ lắp ráp nội tuyến tùy thuộc vào mục tiêu. Ví dụ, hỗ trợ 32 bit x86; 64-bit x86-64 thì không. –

4

Một khởi đầu tốt sẽ được đọc bài viết này mà nói về lắp ráp nội tuyến trong C/C++:

http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx

Ví dụ từ bài viết:

#include <stdio.h> 


int main() { 
    /* Add 10 and 20 and store result into register %eax */ 
    __asm__ ("movl $10, %eax;" 
       "movl $20, %ebx;" 
       "addl %ebx, %eax;" 
    ); 

    /* Subtract 20 from 10 and store result into register %eax */ 
    __asm__ ("movl $10, %eax;" 
        "movl $20, %ebx;" 
        "subl %ebx, %eax;" 
    ); 

    /* Multiply 10 and 20 and store result into register %eax */ 
    __asm__ ("movl $10, %eax;" 
        "movl $20, %ebx;" 
        "imull %ebx, %eax;" 
    ); 

    return 0 ; 
} 
9

Trong GCC, có nhiều điều hơn thế. Trong hướng dẫn, bạn phải nói cho trình biên dịch biết những gì đã thay đổi, để trình tối ưu hóa của nó không bị hỏng. Tôi không phải chuyên gia, nhưng đôi khi nó trông giống như sau:

asm ("lock; xaddl %0,%2" : "=r" (result) : "0" (1), "m" (*atom) : "memory"); 

Đó là một ý tưởng tốt để viết một số mẫu mã trong C, sau đó yêu cầu GCC để tạo ra một danh sách lắp ráp, sau đó sửa đổi mã.

2

Trình biên dịch Microsoft không phải x86 không hỗ trợ lắp ráp trực tuyến. Bạn phải định nghĩa toàn bộ hàm trong một tệp nguồn lắp ráp riêng biệt và chuyển nó cho một trình biên dịch.

Bạn rất khó có thể gọi vào BIOS theo hệ điều hành chế độ được bảo vệ và nên sử dụng bất kỳ cơ sở nào có sẵn trên hệ thống đó. Ngay cả khi bạn đang ở trong chế độ hạt nhân nó có thể không an toàn - BIOS có thể không được đồng bộ chính xác về trạng thái OS nếu bạn làm như vậy.

+0

Mike, ý của bạn là gì bởi "trình biên dịch Microsoft không phải x86 không hỗ trợ lắp ráp trực tuyến", tất nhiên bạn có thể có, ví dụ Lắp ráp nội tuyến ARM (không phải x86), chỉ cần tìm kiếm nó. –

+1

"Lắp ráp nội tuyến không được hỗ trợ trên bộ vi xử lý ARM và x64." - https://docs.microsoft.com/en-gb/cpp/assembler/inline/inline-assembler. * Inline * assembler có nghĩa là sử dụng các khối '__asm', và tôi đang nói cụ thể về các trình biên dịch của Microsoft. Bạn vẫn có thể tạo một tệp .asm riêng biệt, lắp ráp với bộ tạo Microsoft (ML/ML64/armasm) và liên kết kết quả .obj với chương trình C/C++ bằng CL. Các câu trả lời khác chỉ ra rằng bạn có thể làm việc lắp ráp nội tuyến với các trình biên dịch khác. –

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