2011-12-23 30 views
8

Tôi muốn cổng chức năng OUTB C đến D.Chuyển đổi giúp đỡ: __asm__ __volatile__

static __inline void outb (unsigned char value, unsigned short int port) 
{ 
    __asm__ __volatile__ ("outb %b0,%w1" 
          : 
          : 
         "a" (value), 
          "Nd" (port)); 
} 

Đây là phiên bản D.

extern(C) 
{ 
    void outb (ubyte value, ushort port) 
    { 
     // I couldn't figure out this part 
    } 

} 

Đây là một số liên kết về chủ đề.

D Inline Assembler

http://dlang.org/iasm.html

GCC-Inline-hội-HOWTO

http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

Nhưng tôi không biết ngôn ngữ lắp ráp vì vậy tôi cần một số giúp đỡ. Bất kỳ trợ giúp sẽ được đánh giá cao. Cảm ơn.

Trả lời

8

Hướng dẫn outb chỉ nên được gọi là outb %al, %dx trong đó %al là giá trị và %dx là cổng.

D sử dụng cú pháp Intel cho x86, trái ngược với bộ phối hợp GNU sử dụng cú pháp AT & T theo mặc định. Cú pháp Intel tương ứng sẽ là out dx, al, và mã tương ứng trong D sẽ trông như thế:

void outb (ubyte value, ushort port) 
{ 
    asm { 
     mov AL, value; 
     mov DX, port; 
     out DX, AL; 
    } 
} 

Lưu ý rằng bạn không cần phải viết lắp ráp ở tất cả, vì druntime có core.bitop.outp chức năng mà thực hiện các lệnh tương tự.

void outb (ubyte value, ushort port) 
{ 
    import core.bitop; 
    outp(port, value); 
} 
4

Điều đầu tiên đó là lẽ vấp ngã bạn lên là danh sách được hỗ trợ trình biên dịch D của opcodes không bao gồm outb, theo quy định của chức năng C mà bạn cung cấp. Sau khi đào một số, tôi đã phát hiện ra rằng outb là một tên cụ thể hơn cho opcode chung out. outb cho biết đối số đầu tiên cho opcode sẽ được chứa trong thanh ghi byte (trái ngược với outwoutl, cho biết kích thước đối số đầu tiên, tương ứng, từ và từ kép), tuy nhiên trình biên dịch D sử dụng mã opcode out cho tất cả các hoạt động, và xác định opcode cụ thể để viết dựa trên kích thước của đối số bạn chỉ định.

Bằng cách đó, điều tiếp theo cần làm là chuyển cú pháp GCC thành cú pháp D. Theo GCC-Inline-hội-HOWTO, mã mà bạn cung cấp sử dụng cú pháp lắp ráp mở rộng:

asm (assembler template 
    : output operands     /* optional */ 
    : input operands     /* optional */ 
    : list of clobbered registers  /* optional */ 
    ); 

Nhìn vào mẫu của bạn, chức năng xác định một hướng dẫn lắp ráp (outb) với hai đối số, đầu tiên là một byte (%b0) và thứ hai là một từ hoặc một số nguyên ngắn (%w0).

Bit khó hiểu về danh sách đối số đầu vào là chuỗi tiền tố mỗi thông số hàm của bạn. Những điều này, theo HOWTO, được gọi là những ràng buộc. Về cơ bản chúng là các quy tắc mà GCC phải tuân thủ trong việc sử dụng các tham số như các đối số cho các hướng dẫn lắp ráp được cung cấp.Ràng buộc "a" được áp dụng cho thông số value cho biết rằng nội dung của biến phải được đặt trong đăng ký eax, ax hoặc al tùy thuộc vào kích thước của biến. Ràng buộc trên biến số port, "Nd", cho biết giá trị đầu tiên nằm trong khoảng 0-255 và thứ hai, giá trị phải được đặt trong thanh ghi edx, dx hoặc một lần nữa, dựa trên kích thước của biến.

Trình biên dịch D không cung cấp nhiều trợ giúp với các biến trong các khối lắp ráp như GCC thực hiện; trong trình biên dịch nội tuyến của D, bạn sẽ cần phải di chuyển cụ thể các giá trị của các tham số vào các thanh ghi thích hợp. Đối với outb, các thanh ghi này là dxal. Sau cú pháp lắp ráp nội tuyến D's, bạn có thể di chuyển các biến và gọi out opcode như sau:

asm 
{ 
    MOV AL, value; 
    MOV DX, port; 
    OUT DX, AL; 
} 

Lưu ý rằng, bởi vì GCC sử dụng AT & T cú pháp lắp ráp, và D sử dụng cú pháp lắp ráp Intel, thứ tự của các đối số được cung cấp cho OUT bị đảo ngược.

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