日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

rip c语言,GNU C 对标准C语言的扩展

發布時間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 rip c语言,GNU C 对标准C语言的扩展 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

特殊屬性聲明

GNU C 允許聲明函數、變量和類型的特殊屬性,以便進行手工的代碼優化和定制。如果要指定一個屬性聲明,只需要在聲明后添加__ attribute __((ATTRIBUTE))。其中ATTRIBUTE為屬性說明,如果存在多個屬性,則以逗號分隔。GNU C 支持noreturn,noinline, always_inline, pure, const, nothrow, format, format_arg, no_instrument_function, section, constructor, destructor, used, unused, deprecated, weak, malloc, alias warn_unused_result nonnull等十個屬性。

noreturn屬性作用于函數,表示該函數從不返回。這會讓編譯器優化代碼并消除不必要的警告信息。例如: #define ATTRIB_NORET __attribute__((noreturn)) ....

asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;

packed屬性作用于變量和類型,用于變量或結構域時,表示使用最小可能的對齊,用于枚舉、結構或聯合類型時表示該類型使用最小的內存。如對于結構體,就是它告訴編譯器取消結構在編譯過程中的優化對齊,按照實際占用字節數進行對齊。例如: struct example_struct

{

char a;

int b;

long c;

} __attribute__((packed));

regparm屬性用于指定最多可以使用n個寄存器(eax, edx, ecx)傳遞參數,n的范圍是0~3,超過n時則將參數壓入棧中(n=0表示不用寄存器傳遞參數)。

注意:以上這些屬性都是在X86處理器體系結構下的,在X64體系結構下,大部分內容都是同樣有效的。但是,這里要注意regparm屬性,由于在X64體系結構下,GUN C的默認調用約定使用寄存器傳遞參數。所以,如果regparm屬性里使用的寄存器個數超過3個,也仍然會使用其他寄存器來傳遞參數。這一點要遵循X64體系結構的調用約定。

下面可以看一個例子。 int q = 0x5a;

int t1 = 1;

int t2 = 2;

int t3 = 3;

int t4 = 4;

#define REGPARM3 __attribute((regparm(3)))

#define REGPARM0 __attribute((regparm(0)))

void REGPARM0 p1(int a)

{

q = a + 1;

}

void REGPARM3 p2(int a, int b, int c, int d)

{

q = a + b + c + d + 1;

}

int main()

{

p1(t1);

p2(t1,t2,t3,t4);

return 0;

}

使用objdump命令反匯編,相關命令如下: objdump -D 可執行程序

其中-D選項用于反匯編所有的程序段,包括:代碼段、數據段、只讀數據段以及一些系統段等等。而-d命令只反匯編代碼段的內容。

反匯編后的關鍵代碼如下: Disassembly of section .text:

0000000000400474 :

400474: 55 push %rbp

400475: 48 89 e5 mov %rsp,%rbp

400478: 89 7d fc mov %edi,-0x4(%rbp)

40047b: 8b 45 fc mov -0x4(%rbp),%eax

40047e: 83 c0 01 add $0x1,%eax

400481: 89 05 3d 04 20 00 mov %eax,0x20043d(%rip) # 6008c4

400487: c9 leaveq

400488: c3 retq

0000000000400489 :

400489: 55 push %rbp

40048a: 48 89 e5 mov %rsp,%rbp

40048d: 89 7d fc mov %edi,-0x4(%rbp)

400490: 89 75 f8 mov %esi,-0x8(%rbp)

400493: 89 55 f4 mov %edx,-0xc(%rbp)

400496: 89 4d f0 mov %ecx,-0x10(%rbp)

400499: 8b 45 f8 mov -0x8(%rbp),%eax

40049c: 8b 55 fc mov -0x4(%rbp),%edx

40049f: 8d 04 02 lea (%rdx,%rax,1),%eax

4004a2: 03 45 f4 add -0xc(%rbp),%eax

4004a5: 03 45 f0 add -0x10(%rbp),%eax

4004a8: 83 c0 01 add $0x1,%eax

4004ab: 89 05 13 04 20 00 mov %eax,0x200413(%rip) # 6008c4

4004b1: c9 leaveq

4004b2: c3 retq

00000000004004b3 :

4004b3: 55 push %rbp

4004b4: 48 89 e5 mov %rsp,%rbp

4004b7: 53 push %rbx

4004b8: 8b 05 0a 04 20 00 mov 0x20040a(%rip),%eax # 6008c8

4004be: 89 c7 mov %eax,%edi

4004c0: e8 af ff ff ff callq 400474

4004c5: 8b 0d 09 04 20 00 mov 0x200409(%rip),%ecx # 6008d4

4004cb: 8b 15 ff 03 20 00 mov 0x2003ff(%rip),%edx # 6008d0

4004d1: 8b 1d f5 03 20 00 mov 0x2003f5(%rip),%ebx # 6008cc

4004d7: 8b 05 eb 03 20 00 mov 0x2003eb(%rip),%eax # 6008c8

4004dd: 89 de mov %ebx,%esi

4004df: 89 c7 mov %eax,%edi

4004e1: e8 a3 ff ff ff callq 400489

4004e6: b8 00 00 00 00 mov $0x0,%eax

4004eb: 5b pop %rbx

4004ec: c9 leaveq

4004ed: c3 retq

4004ee: 90 nop

4004ef: 90 nop

Disassembly of section .data:

00000000006008c0 <__data_start>:

6008c0: 00 00 add %al,(%rax)

...

00000000006008c4 :

6008c4: 5a pop %rdx

6008c5: 00 00 add %al,(%rax)

...

00000000006008c8 :

6008c8: 01 00 add %eax,(%rax)

...

00000000006008cc :

6008cc: 02 00 add (%rax),%al

...

00000000006008d0 :

6008d0: 03 00 add (%rax),%eax

...

00000000006008d4 :

6008d4: 04 00 add $0x0,%al

...

如果讀者還記得2.2.3節中,關于GCC基于X64體系結構的調用約定的話,那就很容易可以看出,函數p1和p2都使用寄存器傳遞參數,順序就是RDI, RSI, RDX, RCX,這些細節已經跟regparm的規定完全不一致了。所以,在這里作者覺得,regparm已經不起作用了。

總結

以上是生活随笔為你收集整理的rip c语言,GNU C 对标准C语言的扩展的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。