我还记得早期使用旧版的Borland DOS编译器时,可以做出这样的操作:
asm {
mov ax,ex
etc etc...
}
现在有没有一种半平台独立的方法来做这件事?我需要调用BIOS,所以如果有一种不需要汇编代码就能实现的方法,对我来说同样有用。
我还记得早期使用旧版的Borland DOS编译器时,可以做出这样的操作:
asm {
mov ax,ex
etc etc...
}
现在有没有一种半平台独立的方法来做这件事?我需要调用BIOS,所以如果有一种不需要汇编代码就能实现的方法,对我来说同样有用。
__ attribute__((naked))
的函数中,该函数仅包含内联汇编,否则会出现错误。 如果您修改寄存器,则必须使用GNU C扩展汇编约束/破坏来告诉编译器;踩到编译器的寄存器可能会导致非常奇怪的结果。(仅禁用优化测试一种情况并不能证明它是安全的)。请参阅https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html / https://stackoverflow.com/tags/inline-assembly/info / http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html。 - Peter Cordes在GCC中,事情不仅仅是这样的。在指令中,您必须告诉编译器发生了什么变化,以便其优化器不会出错。我不是专家,但有时看起来像这样:
asm ("lock; xaddl %0,%2" : "=r" (result) : "0" (1), "m" (*atom) : "memory");
在编写C代码后,建议通过GCC生成汇编程序清单,然后对代码进行修改。
一个好的起点是阅读本文,该文章讨论了C/C++中的内联汇编:
http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx
文章中的示例:
#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 ;
}
__attribute__((naked))
函数的主体)。只使用GNU C扩展汇编,例如asm("sub %1, %0" : "+r"(dst) : "ri"(20));
。请参阅https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html和https://stackoverflow.com/tags/inline-assembly/info。你链接的文章确实讨论了扩展汇编,但在其更大的`asm volatile`示例中缺少一些临时寄存器的clobbers。 - Peter Cordesmov %1, %%eax
开始 asm 模板,而不是在首次要求输入时使用寄存器。 - Peter Cordes对于微软编译器,只支持x86的内联汇编。对于其他目标,您需要在单独的汇编源文件中定义整个函数,将其传递给汇编器并链接生成的对象模块。
在受保护模式操作系统下,您极有可能无法调用BIOS,并且应使用该系统上可用的任何设施。即使在内核模式下,这样做也可能不安全 - 如果这样做,BIOS可能无法正确地与操作系统状态同步。
__asm
块,我特别指的是微软的编译器。您仍然可以创建一个单独的.asm文件,使用Microsoft汇编器(ML / ML64 / armasm)汇编该文件,并使用CL将生成的.obj与C / C ++程序链接起来。其他答案表明您可以使用其他编译器进行内联汇编。 - Mike Dimmick使用asm
或__asm__
函数(在编译器中有区别)
同时,您也可以使用fortran
函数编写Fortran代码
asm("syscall");
fortran("Print *,"J");