pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

C 表達(dá)式中的匯編指令

這篇文章主要介紹了C 表達(dá)式中的匯編指令,需要的朋友可以參考下

asm 為 gcc 中的關(guān)鍵字,asm 表達(dá)式為在 C代碼中嵌套匯編指令,該表達(dá)式只是單純的替換出匯編代碼,并不對(duì)匯編代碼的含義進(jìn)行解析。

asm 表達(dá)式有兩種形式,第二種 asm-qualifiers 包含了 goto 語(yǔ)句。
第一種形式為常見的用法,AssemblerTemplate 和 OutputOperands 必須存在, 其中 Clobbers 存在需要 InputOperands 也出現(xiàn)。


asm asm-qualifiers ( AssemblerTemplate 
     : OutputOperands 
     [ : InputOperands
     [ : Clobbers ] ])

asm asm-qualifiers ( AssemblerTemplate 
      : 
      : InputOperands
      : Clobbers
      : GotoLabels)

Qualifiers 的類型

volatile, 避免編譯器的優(yōu)化inline, 內(nèi)斂限定符,最小的體積goto, 包含跳轉(zhuǎn)指令

參數(shù)

AssemblerTemplate
- 匯編指令模板是包含匯編器指令的文字字符串,編輯器替換引用輸入,編譯器不會(huì)解析該指令的含義。OutputOperands
- 由 AssemblerTemplate 中的指令修改的C變量的逗號(hào)分隔列表,允許使用空列表。InputOperands
- 由 AssemblerTemplate 中的指令讀取的C變量的逗號(hào)分隔列表,允許使用空列表。Clobbers
- 用逗號(hào)分隔的寄存器列表或由 AssemblerTemplate 修改的值,不能出現(xiàn)在 OutputOperands 和 InputOperands 中被提及,允許使用空列表。GotoLabels
- 當(dāng)使用asm的goto形式時(shí),此部分包含 AssemblerTemplate 中的代碼可能跳轉(zhuǎn)到的所有C標(biāo)簽的列表。

AssemblerTemplate

匯編指令由一個(gè)字符串給出,多條匯編指令結(jié)合在一起使用的時(shí)候,中間以 \r\t 隔開,如


asm("inc %0\n\tinc %0" : "=r"(res) : "0"(res));

/APP
# 11 "asm.c" 1
  inc %rax
  inc %rax
# 0 "" 2
/NO_APPs

需要轉(zhuǎn)義的字符:%, =, {, }, |

故在ATT匯編中,對(duì)寄存器進(jìn)行操作的需要雙 %%, 如 inc %%rax.

OutputOperands

操作數(shù)之間用逗號(hào)分隔。 每個(gè)操作數(shù)具有以下格式:


[ [asmSymbolicName] ] constraint (cvariablename)

asmSymbolicName
- 為操作數(shù)指定名稱,格式為 %[name]
c // res = num asm("movq %[num], %[res]" : [res] "=r"(res) : [num] "m"(num));
- 如果未指定名稱使用數(shù)字, 從 output 域開始,第一個(gè)參數(shù)為 %0, 一次類推, 這里的 res 為 %0, num 為 %1
c // res = num asm("movq %1, %0" : "=r"(res) : "m"(num));constraint
- 一個(gè)字符串常量,用于指定對(duì)操作數(shù)的存儲(chǔ)的 約束, 需要以 "=" 或 "+" 開頭cvariablename
- 指定一個(gè)C左值表達(dá)式來保存輸出,通常是一個(gè)變量名。 括號(hào)是語(yǔ)法的必需部分

第一個(gè)參數(shù)為增加可讀性使用的,現(xiàn)在我們有代碼如下


int64_t res;
int64_t num = 1;

asm("movq %[num], %[res]" : [res] "=r"(res) : [num] "m"(num));
asm("movq %1, %0" : "=r"(res) : "m"(num));
asm("movq %1, %0" : "=m"(res) : "m"(num));
asm("movq %1, %0" : "=r"(res) : "r"(num));

// 對(duì)應(yīng)的匯編代碼, 只保留asm表達(dá)式中的代碼
# 13 "asm.c" 1
  movq -16(%rbp), %rax // asm-1
 # 0 "" 2
/NO_APP

/APP
 # 15 "asm.c" 1
  movq -16(%rbp), %rax // asm-2
 # 0 "" 2
/NO_APP

/APP
 # 17 "asm.c" 1
  movq -16(%rbp), -8(%rbp) // asm-3
 # 0 "" 2
/NO_APP

/APP
 # 19 "asm.c" 1
  movq %rax, %rax // asm-4
 # 0 "" 2
/NO_APP
  1. 使用名稱替換和數(shù)字替換效果一樣,見 asm-1 和 asm-2約束的用法,這里使用比較簡(jiǎn)單通用的的兩種情況,r 為通過寄存器尋址操作,m 通過內(nèi)存尋址操作,所以看到當(dāng)
  2. 約束了 r 就對(duì)應(yīng)寄存器的操作。
  3. 結(jié)果保存在 res 也就是 cvariablename 中

InputOperands

輸入操作數(shù)使C變量和表達(dá)式中的值可用于匯編代碼。


[ [asmSymbolicName] ] constraint (cexpression)

asmSymbolicName 和輸出列表的用法完全一致

constraint 約束不能使用 =+. 可以使用 "0", 這表明在輸出約束列表中(從零開始)的條目,指定的輸入必須與輸出約束位于同一位置。


int64_t res = 3;
int64_t num = 1;
asm("addq %1, %0" : "=g"(res) : "0"(num));

// 輸入輸出位置相同
  movq $3, -8(%rbp)
  movq $1, -16(%rbp)
  movq -16(%rbp), %rax
/APP
# 32 "asm.c" 1
  addq %rax, %rax
# 0 "" 2
/NO_APP
  • cexpression 可以不為左值,作為匯編表達(dá)式的輸入值即可
  • Clobbers

破壞列表,主要用于指示編譯器生成的匯編指令。

從asm表達(dá)式中看到輸出操作數(shù)中列出條目的更改編譯器是可以確定的,但內(nèi)聯(lián)匯編代碼可能不僅對(duì)輸出進(jìn)行了修改。 例如,計(jì)算可能需要其他寄存器,或者處理器可能會(huì)由于特定匯編程序指令而破壞寄存器的值。 為了將這些更改通知編譯器,在Clobber列表中列出這些會(huì)產(chǎn)生副作用的條目。 破壞列表?xiàng)l目可以是寄存器名稱,也可以是特殊的破壞列表項(xiàng)(在下面列出)。 每個(gè)內(nèi)容列表?xiàng)l目都是一個(gè)字符串常量,用雙引號(hào)引起來并用逗號(hào)分隔。

寄存器


 ```c
 asm volatile("movc3 %0, %1, %2"
   : /* No outputs. */
   : "r"(from), "r"(to), "g"(count)
   : "%rbx", "%rcx", "%rdx", "memory");

 /APP
 # 25 "asm.c" 1
   movc3 %rax, %r8, -72(%rbp)
 # 0 "" 2
 /NO_APP
 ```

 可以看到使用到了 rax 寄存器,然后修改程序在 Clobbers 增加 %rax, 結(jié)果如下

 ```c
 asm volatile("movc3 %0, %1, %2"
   : /* No outputs. */
   : "r"(from), "r"(to), "g"(count)
   : "%rax", "%rbx", "%rcx", "%rdx", "memory");

 /APP
 # 25 "asm.c" 1
   movc3 %r8, %r9, -72(%rbp)
 # 0 "" 2
 /NO_APP
 ```

特殊破壞列表項(xiàng)

- "cc", 表示匯編代碼修改了標(biāo)志寄存器
- "memory", 為了確保內(nèi)存中包含正確的值,編譯器可能需要在執(zhí)行asm之前將特定的寄存器值刷新到內(nèi)存中

編譯器為了破壞列表項(xiàng)的值受到破壞,當(dāng)這些條目是寄存器時(shí),不對(duì)其進(jìn)行使用;為特殊參數(shù)時(shí),重新刷新得到最新的值。

約束

一些基礎(chǔ)的約束

約束名 說明
whitespace 空白字符被忽略
m 允許使用內(nèi)存操作數(shù),以及機(jī)器通常支持的任何類型的地址
o 允許使用內(nèi)存操作數(shù),但前提是地址是可偏移的
V 允許使用內(nèi)存操作數(shù),不可偏移的內(nèi)存地址,與 "o'互斥
r 允許在通用寄存器中使用的寄存器操作數(shù),其中可以指定寄存器,如 a(%rax), b(%rbx)
i 允許使用立即整數(shù)操作數(shù)
n 允許使用具有已知數(shù)值的立即整數(shù)操作數(shù), ‘I', ‘J', ‘K', … ‘P' 更應(yīng)該使用 n
F 允許使用浮點(diǎn)立即數(shù)
g 允許使用任何寄存器,內(nèi)存或立即數(shù)整數(shù)操作數(shù),但非通用寄存器除外
X 允許任何操作數(shù), ‘0', ‘1', ‘2', … ‘9'
p 允許使用有效內(nèi)存地址的操作數(shù)

標(biāo)識(shí)符約束

標(biāo)識(shí)符 說明
= 表示此操作數(shù)是由該指令寫入的:先前的值將被丟棄并由新數(shù)據(jù)替換
+ 表示該操作數(shù)由指令讀取和寫入
& 表示(在特定替代方法中)此操作數(shù)是早期指令操作數(shù),它是在使用輸入操作數(shù)完成指令之前寫入的,故輸入操作數(shù)部分不能分配與輸出操作數(shù)相同的寄存器
% 表示該操作數(shù)與后續(xù)操作數(shù)的可交換指令

內(nèi)核示例

x86 的內(nèi)存屏障指令。


// 避免編譯器的優(yōu)化,聲明此處內(nèi)存可能發(fā)生破壞
#define barrier() asm volatile("" ::: "memory")
// 在32位的CPU下,lock 指令為鎖總線,加上一條內(nèi)存操作指令就達(dá)到了內(nèi)存屏障的作用,64位的cpu已經(jīng)有新增的 *fence 指令可以使用
// mb() 執(zhí)行一個(gè)內(nèi)存屏障作用的指令,為指定CPU操作;破壞列表聲明 cc memory 指示避免編譯器進(jìn)行優(yōu)化
#ifdef CONFIG_X86_32
#define mb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "mfence", \
        X86_FEATURE_XMM2) ::: "memory", "cc")
#define rmb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "lfence", \
        X86_FEATURE_XMM2) ::: "memory", "cc")
#define wmb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "sfence", \
        X86_FEATURE_XMM2) ::: "memory", "cc")
#else
#define mb() asm volatile("mfence":::"memory")
#define rmb() asm volatile("lfence":::"memory")
#define wmb() asm volatile("sfence" ::: "memory")
#endif

x86 下獲取 current 的值


DECLARE_PER_CPU(struct task_struct *, current_task);

#define this_cpu_read_stable(var) percpu_stable_op("mov", var)

static __always_inline struct task_struct *get_current(void)
{
  return this_cpu_read_stable(current_task);
}

#define percpu_stable_op(op, var)   \
({       \
  typeof(var) pfo_ret__;    \
  switch (sizeof(var)) {    \
  case 8:      \
    asm(op "q "__percpu_arg(P1)",%0" \
    : "=r" (pfo_ret__)   \
    : "p" (&(var)));   \
    break;     \
  }      \
  pfo_ret__;     \
})

current_task 為一個(gè) struct task_struct 類型的指針,追蹤宏調(diào)用,在x86-64 下命中了 case 8: 的匯編代碼, 展開的代碼為


asm("mov" "q ""%%""gs" ":" "%" "P1"",%0" : "=r" (pfo_ret__) : "p" (&(current_task)));
// 變換一下為
asm("movq %%gs:%P1, %0" : "=r"(pfo_ret__) : "p"(&(current_task)));

這行代碼的含義為將 約束輸入部分必須為有效的地址(p約束), 將CPU id(通過段寄存器gs和偏移通過GDT得到,這里后文分析了)通過寄存器(r約束)賦值給 pfo_ret__.

參考

GCC文檔
C語(yǔ)言ASM匯編內(nèi)嵌語(yǔ)法zz

總結(jié)

以上所述是小編給大家介紹的C 表達(dá)式中的匯編指令,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)html5模板網(wǎng)網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請(qǐng)聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

這篇文章主要介紹了匯編中的數(shù)組分配和指針的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)
這篇文章主要介紹了asm基礎(chǔ)——匯編指令之in/out指令,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)
這篇文章主要介紹了匯編語(yǔ)言 寄存器內(nèi)存訪問原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
這篇文章主要介紹了使用匯編語(yǔ)言實(shí)現(xiàn)if else 循環(huán)函數(shù)調(diào)用的具體方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編
這篇文章主要介紹了匯編語(yǔ)言位向量(位映射)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)
這篇文章主要介紹了匯編語(yǔ)言AND指令實(shí)現(xiàn)對(duì)兩個(gè)操作數(shù)進(jìn)行邏輯(按位)與操作,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面
主站蜘蛛池模板: 西安微信朋友圈广告投放_微信朋友圈推广_西安度娘网络科技有限公司 | 便携式XPDM露点仪-在线式防爆露点仪-增强型烟气分析仪-约克仪器 冰雕-冰雪世界-大型冰雕展制作公司-赛北冰雕官网 | 上海单片机培训|重庆曙海培训分支机构—CortexM3+uC/OS培训班,北京linux培训,Windows驱动开发培训|上海IC版图设计,西安linux培训,北京汽车电子EMC培训,ARM培训,MTK培训,Android培训 | 杰福伦_磁致伸缩位移传感器_线性位移传感器-意大利GEFRAN杰福伦-河南赉威液压科技有限公司 | bng防爆挠性连接管-定做金属防爆挠性管-依客思防爆科技 | 尼龙PA610树脂,尼龙PA612树脂,尼龙PA1010树脂,透明尼龙-谷骐科技【官网】 | 杭州画室_十大画室_白墙画室_杭州美术培训_国美附中培训_附中考前培训_升学率高的画室_美术中考集训美术高考集训基地 | 天津市能谱科技有限公司-专业的红外光谱仪_红外测油仪_紫外测油仪_红外制样附件_傅里叶红外光谱技术生产服务厂商 | 油液红外光谱仪-油液监测系统-燃油嗅探仪-上海冉超光电科技有限公司 | 石家庄装修设计_室内家装设计_别墅装饰装修公司-石家庄金舍装饰官网 | 天津拓展_天津团建_天津趣味运动会_天津活动策划公司-天津华天拓展培训中心 | 点焊机-缝焊机-闪光对焊机-电阻焊设备生产厂家-上海骏腾发智能设备有限公司 | 北京网站建设-企业网站建设-建站公司-做网站-北京良言多米网络公司 | 火锅加盟_四川成都火锅店加盟_中国火锅连锁品牌十强_朝天门火锅【官网】 | 利浦顿蒸汽发生器厂家-电蒸汽发生器/燃气蒸汽发生器_湖北利浦顿热能科技有限公司官网 | 微型气泵-真空-蠕动-水泵-厂家-深圳市品亚科技有限公司 | 高低温试验房-深圳高低温湿热箱-小型高低温冲击试验箱-爱佩试验设备 | 最新范文网_实用的精品范文美文网| 欧必特空气能-商用空气能热水工程,空气能热水器,超低温空气源热泵生产厂家-湖南欧必特空气能公司 | 电子海图系统-电梯检验系统-智慧供热系统开发-商品房预售资金监管系统 | 400电话_400电话申请_888元包年_400电话办理服务中心_400VIP网 | pbt头梳丝_牙刷丝_尼龙毛刷丝_PP塑料纤维合成毛丝定制厂_广州明旺 | 上海电子秤厂家,电子秤厂家价格,上海吊秤厂家,吊秤供应价格-上海佳宜电子科技有限公司 | 上海单片机培训|重庆曙海培训分支机构—CortexM3+uC/OS培训班,北京linux培训,Windows驱动开发培训|上海IC版图设计,西安linux培训,北京汽车电子EMC培训,ARM培训,MTK培训,Android培训 | 单柱拉力机-橡胶冲片机-哑铃裁刀-江都轩宇试验机械厂 | 成都顶呱呱信息技术有限公司-贷款_个人贷款_银行贷款在线申请 - 成都贷款公司 | Eiafans.com_环评爱好者 环评网|环评论坛|环评报告公示网|竣工环保验收公示网|环保验收报告公示网|环保自主验收公示|环评公示网|环保公示网|注册环评工程师|环境影响评价|环评师|规划环评|环评报告|环评考试网|环评论坛 - Powered by Discuz! | 电子天平-华志电子天平厂家| 青岛侦探_青岛侦探事务所_青岛劝退小三_青岛婚外情取证-青岛王军侦探事务所 | 电竞学校_电子竞技培训学校学院-梦竞未来电竞学校官网 | 网站优化公司_SEO优化_北京关键词百度快速排名-智恒博网络 | 电动手术床,医用护理床,led手术无影灯-曲阜明辉医疗设备有限公司 | 粉丝机械,粉丝烘干机,粉丝生产线-招远市远东粉丝机械有限公司 | 气动隔膜泵-电动隔膜泵-循环热水泵-液下排污/螺杆/管道/化工泵「厂家」浙江绿邦 | 深圳离婚律师咨询「在线免费」华荣深圳婚姻律师事务所专办离婚纠纷案件 | 压片机_高速_单冲_双层_花篮式_多功能旋转压片机-上海天九压片机厂家 | 螺杆真空泵_耐腐蚀螺杆真空泵_水环真空泵_真空机组_烟台真空泵-烟台斯凯威真空 | 北京企业宣传片拍摄_公司宣传片制作-广告短视频制作_北京宣传片拍摄公司 | 办公室家具公司_办公家具品牌厂家_森拉堡办公家具【官网】 | 青州开防盗门锁-配汽车芯片钥匙-保险箱钥匙-吉祥修锁店 | 报警器_家用防盗报警器_烟雾报警器_燃气报警器_防盗报警系统厂家-深圳市刻锐智能科技有限公司 |