static inline int strcmp(const char * cs,const char * ct) { int d0, d1; register int __res; __asm__ __volatile__( "1:\tlodsb\n\t" "scasb\n\t" "jne 2f\n\t" "testb %%al,%%al\n\t" "jne 1b\n\t" "xorl %%eax,%%eax\n\t" "jmp 3f\n" "2:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "3:" :"=a" (__res), "=&S" (d0), "=&D" (d1) :"1" (cs),"2" (ct)); return __res; }
1: lodsb
//裝入串操作數,即從DS段中esi位置的字符傳送到 al 寄存器,然後 esi 根據DF指向串中下一個元素 ,DF=0,增加;DF=1,減少
Scasb
//掃描串操作數,即從 al 中減去ES段中edi位置的字符,不保留結果,只改變標志 CF,AF,PF,SF,OF,ZF,若字符相等,ZF=1,否則ZF=0。若DS段中字符小於ES段中串,則CF=1,後面sbb運算會出現-1
Jne2f
//如果兩個字符不相等,則轉到標號
testb %al %al
//如果al中全是0,則ZF=1(邏輯與結果為0),如果字符串結束遇到null零
jne 1b
//如果ZF=0(邏輯與結果不為0)即字符串未結束,則繼續比較
xorl %eax %eax
//自身異或,結果為0,CF=0,eax清空
jmp 3f
//向前跳至3:,退出,返回值為0
2: sbbl %eax %eax
//32位sbb src,dest;dest-src-CF,存入dest,如果CF=1,則結果為-1(全是1);否則為0。(結果為-1時標志位:CF=1,SF=1,OF=1,ZF=0,PF=1)
orb $1 %al
//對0位或1,保證結果為-1或者1。如果結果為0,或1之後為1,即字符大,返回1,字符小,返回-1
3:
這段代碼看起來非常熟悉,讀起來也不困難。其中 3f 表示往前(forword)找到第一個 標號為 3 的那一行,相應地,1b 表示往後找。其中嵌入式匯編代碼中輸出和輸入部分的結合 情況為: 返回值__res,放在 al 寄存器中,與%0相結合; 局部變量 d0,與%1 相結合,也與輸入部分的 cs 參數相對應,也存放在寄存器 ESI 中,即 ESI 中存放源字符串的起始地址。 局部變量 d1,與%2 相結合,也與輸入部分的 ct 參數相對應,也存放在寄存器 EDI 中,即 EDI 中存放目的字符串的起始地址。 通過對這段代碼的分析我們應當體會到,萬變不利其本,嵌入式匯編與一般匯編的區別 僅僅是形式,本質依然不變。因此,全面掌握 Intel 386 匯編指令乃突破閱讀低層代碼之根 本 大部分指令對於AT&T使用以下後綴: b 字節(8位),對應於Intel的byte ptr w 字(16位),對應於Intel的word ptr l 雙字(實際是表示long,32位),對應於Intel的dword ptr q 四字(64位),對應於Intel的qword ptr