内联汇编
使用处理器持有指令优化范例
下面是一段在D语言进行行内组语的程式码。该程式码使用x86架构的浮点运算器指令来计算 tan --> x {\displaystyle \tan x} 。此实作快于编译器产生的一系列浮点数运算,行内组语也使编程人员得以使用fldpi 指令来载入在x86架构下可得到的最佳之pi估计值。
// 計算tan(x)realtan(realx){asm{fldx[EBP];// 將x值載入浮點運算器的堆疊上fxam;// 測試堆疊頂端的值是否是合法、可計算浮點數fstswAX;sahf;jctrigerr;// 若x是NAN,正負無限,或空值 // 387可以處理denormals數值SC18:fptan;// 為與8087運算器相容fptan會使堆疊頂端為1.0,再來才是tan值,fstpST(0);// 丟棄堆疊頂端的值fstswAX;sahf;jnpLret;// C2為FPU狀態變數,C2 == 1表示x超出允許的範圍;// tan之週期為pi,下面的程式碼就是將x縮至允許的範圍fldpi;fxch;SC17:fprem1;fstswAX;sahf;jpSC17;fstpST(1);// 將pi值移出堆疊jmpSC18;}trigerr:returnreal.nan;Lret:;}
系统调用(system calls)范例
在保护模式运行的应用程序无法直接呼叫专属于OS的功能。因为OS的行程空间包含核心空间(kernel mode)与用户空间(user mode);运行在用户空间的程式只能透过中断来引用专属于操作系统的功能。通常高阶语言都不提供这项功能,所以要运用行内组语将呼叫system calls的过程包装为高阶语言可辨认、呼叫的函式。
下面的C语言片段即含有一个system call的包装函式。其组语语法为GNU汇编器使用的AT&T组语语法。一般这类程式都会使用宏实作,不过为了清楚展示观念,在此列出了完整的程式码。
GNU组译器的行内组语语法相当直觉,基本型式如下:
asm("assembly code");
例如:
asm("movl %ecx, %eax");/* 複製ecx暫存器的內容至eax暫存器*/
或
__asm_("movb %bh, (%eax)");/* 從bh暫存器複製1位元組的資料到eax暫存器所指的記憶體區塊*/
必须注意的是,AT&T语法中的算子顺序与Windows平台下常用的MASM刚好相反。
asm 跟 __asm__ 都是合法型式;当 asm 与程式码中某些变数命名起冲突时可使用后者。
externinterrno;intfuncname(intarg1,int*arg2,intarg3){intres;__asm__volatile("int $0x80"/* 向OS拋出請求*/:"=a"(res)/* 請編譯器將結果將儲存於eax ("a")*/"+b"(arg1),/* 請編譯器將arg1存於ebx ("b")*/"+c"(arg2),/* 請編譯器將arg2存於ecx ("c")*/"+d"(arg3)/* 請編譯器將arg3存於edx ("d")*/:"a"(128)/* 該system call的編號放於eax ("a")*/:"memory","cc");/* 通知編譯器,記憶體與condition code register(決定分支的暫存器)己被更改*//* 若OS回傳負值表示錯誤;則包裝函式要設定errno global variable並回傳 -1 */if(-125<=res&&res<0){errno=-res;res=-1;}returnres;}
免责声明:以上内容版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。感谢每一位辛勤著写的作者,感谢每一位的分享。
- 有价值
- 一般般
- 没价值