Linux内核分析:操作系统是如何工作的?

函数调用堆栈

堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间

堆栈的几个重要功能

  1. 函数调用框架
  2. 传递参数
  3. 保存返回地址
  4. 提供局部变量空间
  5. 等等

C语言编译器对堆栈的使用有一套的规则
了解堆栈存在的目的和编译器对堆栈使用的规则是理解操作系统一些关键性代码的基础

堆栈相关的寄存器
esp
ebp

相关操作
push 栈顶地址减少4个字节(32位)
pop 栈顶地址增加4个字节(32位)
32位模式下段寄存器出入栈都是用4个字节
ebp在C语言中用作记录当前函数调用的基址

其他关键寄存器
cs:eip 总是指向下一条的指令地址

call xxx

1. push cs:eip
2. 将xxx指向cs:eip
3. enter xxx
pushl %ebp
movl %esp, %ebp
do something
4. leave xxx
movl %ebp, %esp
popl %ebp
ret

一个例子

// test.c
#include <stdio.h>

void p1(char c)
{
    printf("%c\n", c);
}

int p2(int x, int y)
{
    return x + y;
}

int main(void)
{
    char c = 'a';
    int x, y, z;
    x = 1;
    y = 2;
    p1(c);
    z = p2(x, y);
    printf("%d=%d+%d\n", z, x, y);
}

编译
gcc -g -m32 -o test.o test.c

获得反汇编文件
objdump -S test.o

test.c完整的反汇编代码

test.o:     文件格式 elf32-i386
Disassembly of section .init:
080482b4 <_init>:
 80482b4:   53                      push   %ebx
 80482b5:   83 ec 08                sub    $0x8,%esp
 80482b8:   e8 93 00 00 00          call   8048350 <__x86.get_pc_thunk.bx>
 80482bd:   81 c3 43 1d 00 00       add    $0x1d43,%ebx
 80482c3:   8b 83 fc ff ff ff       mov    -0x4(%ebx),%eax
 80482c9:   85 c0                   test   %eax,%eax
 80482cb:   74 05                   je     80482d2 <_init+0x1e>
 80482cd:   e8 2e 00 00 00          call   8048300 <__gmon_start__@plt>
 80482d2:   83 c4 08                add    $0x8,%esp
 80482d5:   5b                      pop    %ebx
 80482d6:   c3                      ret    
Disassembly of section .plt:
080482e0 <printf@plt-0x10>:
 80482e0:   ff 35 04 a0 04 08       pushl  0x804a004
 80482e6:   ff 25 08 a0 04 08       jmp    *0x804a008
 80482ec:   00 00                   add    %al,(%eax)
    ...
080482f0 <printf@plt>:
 80482f0:   ff 25 0c a0 04 08       jmp    *0x804a00c
 80482f6:   68 00 00 00 00          push   $0x0
 80482fb:   e9 e0 ff ff ff          jmp    80482e0 <_init+0x2c>
08048300 <__gmon_start__@plt>:
 8048300:   ff 25 10 a0 04 08       jmp    *0x804a010
 8048306:   68 08 00 00 00          push   $0x8
 804830b:   e9 d0 ff ff ff          jmp    80482e0 <_init+0x2c>
08048310 <__libc_start_main@plt>:
 8048310:   ff 25 14 a0 04 08       jmp    *0x804a014
 8048316:   68 10 00 00 00          push   $0x10
 804831b:   e9 c0 ff ff ff          jmp    80482e0 <_init+0x2c>
Disassembly of section .text:
08048320 <_start>:
 8048320:   31 ed                   xor    %ebp,%ebp
 8048322:   5e                      pop    %esi
 8048323:   89 e1                   mov    %esp,%ecx
 8048325:   83 e4 f0                and    $0xfffffff0,%esp
 8048328:   50                      push   %eax
 8048329:   54                      push   %esp
 804832a:   52                      push   %edx
 804832b:   68 30 85 04 08          push   $0x8048530
 8048330:   68 c0 84 04 08          push   $0x80484c0
 8048335:   51                      push   %ecx
 8048336:   56                      push   %esi
 8048337:   68 4c 84 04 08          push   $0x804844c
 804833c:   e8 cf ff ff ff          call   8048310 <__libc_start_main@plt>
 8048341:   f4                      hlt    
 8048342:   66 90                   xchg   %ax,%ax
 8048344:   66 90                   xchg   %ax,%ax
 8048346:   66 90                   xchg   %ax,%ax
 8048348:   66 90                   xchg   %ax,%ax
 804834a:   66 90                   xchg   %ax,%ax
 804834c:   66 90                   xchg   %ax,%ax
 804834e:   66 90                   xchg   %ax,%ax
08048350 <__x86.get_pc_thunk.bx>:
 8048350:   8b 1c 24                mov    (%esp),%ebx
 8048353:   c3                      ret    
 8048354:   66 90                   xchg   %ax,%ax
 8048356:   66 90                   xchg   %ax,%ax
 8048358:   66 90                   xchg   %ax,%ax
 804835a:   66 90                   xchg   %ax,%ax
 804835c:   66 90                   xchg   %ax,%ax
 804835e:   66 90                   xchg   %ax,%ax
08048360 <deregister_tm_clones>:
 8048360:   b8 23 a0 04 08          mov    $0x804a023,%eax
 8048365:   2d 20 a0 04 08          sub    $0x804a020,%eax
 804836a:   83 f8 06                cmp    $0x6,%eax
 804836d:   77 01                   ja     8048370 <deregister_tm_clones+0x10>
 804836f:   c3                      ret    
 8048370:   b8 00 00 00 00          mov    $0x0,%eax
 8048375:   85 c0                   test   %eax,%eax
 8048377:   74 f6                   je     804836f <deregister_tm_clones+0xf>
 8048379:   55                      push   %ebp
 804837a:   89 e5                   mov    %esp,%ebp
 804837c:   83 ec 18                sub    $0x18,%esp
 804837f:   c7 04 24 20 a0 04 08    movl   $0x804a020,(%esp)
 8048386:   ff d0                   call   *%eax
 8048388:   c9                      leave  
 8048389:   c3                      ret    
 804838a:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
08048390 <register_tm_clones>:
 8048390:   b8 20 a0 04 08          mov    $0x804a020,%eax
 8048395:   2d 20 a0 04 08          sub    $0x804a020,%eax
 804839a:   c1 f8 02                sar    $0x2,%eax
 804839d:   89 c2                   mov    %eax,%edx
 804839f:   c1 ea 1f                shr    $0x1f,%edx
 80483a2:   01 d0                   add    %edx,%eax
 80483a4:   d1 f8                   sar    %eax
 80483a6:   75 01                   jne    80483a9 <register_tm_clones+0x19>
 80483a8:   c3                      ret    
 80483a9:   ba 00 00 00 00          mov    $0x0,%edx
 80483ae:   85 d2                   test   %edx,%edx
 80483b0:   74 f6                   je     80483a8 <register_tm_clones+0x18>
 80483b2:   55                      push   %ebp
 80483b3:   89 e5                   mov    %esp,%ebp
 80483b5:   83 ec 18                sub    $0x18,%esp
 80483b8:   89 44 24 04             mov    %eax,0x4(%esp)
 80483bc:   c7 04 24 20 a0 04 08    movl   $0x804a020,(%esp)
 80483c3:   ff d2                   call   *%edx
 80483c5:   c9                      leave  
 80483c6:   c3                      ret    
 80483c7:   89 f6                   mov    %esi,%esi
 80483c9:   8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi
080483d0 <__do_global_dtors_aux>:
 80483d0:   80 3d 20 a0 04 08 00    cmpb   $0x0,0x804a020
 80483d7:   75 13                   jne    80483ec <__do_global_dtors_aux+0x1c>
 80483d9:   55                      push   %ebp
 80483da:   89 e5                   mov    %esp,%ebp
 80483dc:   83 ec 08                sub    $0x8,%esp
 80483df:   e8 7c ff ff ff          call   8048360 <deregister_tm_clones>
 80483e4:   c6 05 20 a0 04 08 01    movb   $0x1,0x804a020
 80483eb:   c9                      leave  
 80483ec:   f3 c3                   repz ret 
 80483ee:   66 90                   xchg   %ax,%ax
080483f0 <frame_dummy>:
 80483f0:   a1 10 9f 04 08          mov    0x8049f10,%eax
 80483f5:   85 c0                   test   %eax,%eax
 80483f7:   74 1f                   je     8048418 <frame_dummy+0x28>
 80483f9:   b8 00 00 00 00          mov    $0x0,%eax
 80483fe:   85 c0                   test   %eax,%eax
 8048400:   74 16                   je     8048418 <frame_dummy+0x28>
 8048402:   55                      push   %ebp
 8048403:   89 e5                   mov    %esp,%ebp
 8048405:   83 ec 18                sub    $0x18,%esp
 8048408:   c7 04 24 10 9f 04 08    movl   $0x8049f10,(%esp)
 804840f:   ff d0                   call   *%eax
 8048411:   c9                      leave  
 8048412:   e9 79 ff ff ff          jmp    8048390 <register_tm_clones>
 8048417:   90                      nop
 8048418:   e9 73 ff ff ff          jmp    8048390 <register_tm_clones>
0804841d <p1>:
#include <stdio.h>
void p1(char c)
{
 804841d:   55                      push   %ebp
 804841e:   89 e5                   mov    %esp,%ebp
 8048420:   83 ec 18                sub    $0x18,%esp
 8048423:   8b 45 08                mov    0x8(%ebp),%eax
 8048426:   88 45 f4                mov    %al,-0xc(%ebp)
    printf("%c\n", c);
 8048429:   0f be 45 f4             movsbl -0xc(%ebp),%eax
 804842d:   89 44 24 04             mov    %eax,0x4(%esp)
 8048431:   c7 04 24 50 85 04 08    movl   $0x8048550,(%esp)
 8048438:   e8 b3 fe ff ff          call   80482f0 <printf@plt>
}
 804843d:   c9                      leave  
 804843e:   c3                      ret    
0804843f <p2>:
int p2(int x, int y)
{
 804843f:   55                      push   %ebp
 8048440:   89 e5                   mov    %esp,%ebp
    return x + y;
 8048442:   8b 45 0c                mov    0xc(%ebp),%eax
 8048445:   8b 55 08                mov    0x8(%ebp),%edx
 8048448:   01 d0                   add    %edx,%eax
}
 804844a:   5d                      pop    %ebp
 804844b:   c3                      ret    
0804844c <main>:
int main(void)
{
 804844c:   55                      push   %ebp
 804844d:   89 e5                   mov    %esp,%ebp
 804844f:   83 e4 f0                and    $0xfffffff0,%esp
 8048452:   83 ec 20                sub    $0x20,%esp
    char c = 'a';
 8048455:   c6 44 24 13 61          movb   $0x61,0x13(%esp)
    int x, y, z;
    x = 1;
 804845a:   c7 44 24 14 01 00 00    movl   $0x1,0x14(%esp)
 8048461:   00 
    y = 2;
 8048462:   c7 44 24 18 02 00 00    movl   $0x2,0x18(%esp)
 8048469:   00 
    p1(c);
 804846a:   0f be 44 24 13          movsbl 0x13(%esp),%eax
 804846f:   89 04 24                mov    %eax,(%esp)
 8048472:   e8 a6 ff ff ff          call   804841d <p1>
    z = p2(x, y);
 8048477:   8b 44 24 18             mov    0x18(%esp),%eax
 804847b:   89 44 24 04             mov    %eax,0x4(%esp)
 804847f:   8b 44 24 14             mov    0x14(%esp),%eax
 8048483:   89 04 24                mov    %eax,(%esp)
 8048486:   e8 b4 ff ff ff          call   804843f <p2>
 804848b:   89 44 24 1c             mov    %eax,0x1c(%esp)
    printf("%d=%d+%d\n", z, x, y);
 804848f:   8b 44 24 18             mov    0x18(%esp),%eax
 8048493:   89 44 24 0c             mov    %eax,0xc(%esp)
 8048497:   8b 44 24 14             mov    0x14(%esp),%eax
 804849b:   89 44 24 08             mov    %eax,0x8(%esp)
 804849f:   8b 44 24 1c             mov    0x1c(%esp),%eax
 80484a3:   89 44 24 04             mov    %eax,0x4(%esp)
 80484a7:   c7 04 24 54 85 04 08    movl   $0x8048554,(%esp)
 80484ae:   e8 3d fe ff ff          call   80482f0 <printf@plt>
}
 80484b3:   c9                      leave  
 80484b4:   c3                      ret    
 80484b5:   66 90                   xchg   %ax,%ax
 80484b7:   66 90                   xchg   %ax,%ax
 80484b9:   66 90                   xchg   %ax,%ax
 80484bb:   66 90                   xchg   %ax,%ax
 80484bd:   66 90                   xchg   %ax,%ax
 80484bf:   90                      nop
080484c0 <__libc_csu_init>:
 80484c0:   55                      push   %ebp
 80484c1:   57                      push   %edi
 80484c2:   31 ff                   xor    %edi,%edi
 80484c4:   56                      push   %esi
 80484c5:   53                      push   %ebx
 80484c6:   e8 85 fe ff ff          call   8048350 <__x86.get_pc_thunk.bx>
 80484cb:   81 c3 35 1b 00 00       add    $0x1b35,%ebx
 80484d1:   83 ec 1c                sub    $0x1c,%esp
 80484d4:   8b 6c 24 30             mov    0x30(%esp),%ebp
 80484d8:   8d b3 0c ff ff ff       lea    -0xf4(%ebx),%esi
 80484de:   e8 d1 fd ff ff          call   80482b4 <_init>
 80484e3:   8d 83 08 ff ff ff       lea    -0xf8(%ebx),%eax
 80484e9:   29 c6                   sub    %eax,%esi
 80484eb:   c1 fe 02                sar    $0x2,%esi
 80484ee:   85 f6                   test   %esi,%esi
 80484f0:   74 27                   je     8048519 <__libc_csu_init+0x59>
 80484f2:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
 80484f8:   8b 44 24 38             mov    0x38(%esp),%eax
 80484fc:   89 2c 24                mov    %ebp,(%esp)
 80484ff:   89 44 24 08             mov    %eax,0x8(%esp)
 8048503:   8b 44 24 34             mov    0x34(%esp),%eax
 8048507:   89 44 24 04             mov    %eax,0x4(%esp)
 804850b:   ff 94 bb 08 ff ff ff    call   *-0xf8(%ebx,%edi,4)
 8048512:   83 c7 01                add    $0x1,%edi
 8048515:   39 f7                   cmp    %esi,%edi
 8048517:   75 df                   jne    80484f8 <__libc_csu_init+0x38>
 8048519:   83 c4 1c                add    $0x1c,%esp
 804851c:   5b                      pop    %ebx
 804851d:   5e                      pop    %esi
 804851e:   5f                      pop    %edi
 804851f:   5d                      pop    %ebp
 8048520:   c3                      ret    
 8048521:   eb 0d                   jmp    8048530 <__libc_csu_fini>
 8048523:   90                      nop
 8048524:   90                      nop
 8048525:   90                      nop
 8048526:   90                      nop
 8048527:   90                      nop
 8048528:   90                      nop
 8048529:   90                      nop
 804852a:   90                      nop
 804852b:   90                      nop
 804852c:   90                      nop
 804852d:   90                      nop
 804852e:   90                      nop
 804852f:   90                      nop
08048530 <__libc_csu_fini>:
 8048530:   f3 c3                   repz ret 
Disassembly of section .fini:
08048534 <_fini>:
 8048534:   53                      push   %ebx
 8048535:   83 ec 08                sub    $0x8,%esp
 8048538:   e8 13 fe ff ff          call   8048350 <__x86.get_pc_thunk.bx>
 804853d:   81 c3 c3 1a 00 00       add    $0x1ac3,%ebx
 8048543:   83 c4 08                add    $0x8,%esp
 8048546:   5b                      pop    %ebx
 8048547:   c3                      ret   

C代码嵌入汇编代码

内嵌汇编语法

__asm__(
    汇编语句模板:
    输出部分:
    输入部分:
    破坏描述部分
);
即格式为 asm("statements":output_regs:input_regs:clobbered_regs);
asm是__asm__的别名
volatile是__volatile__的别名,表示编译器不要优化代码

asm.c

// asm.c
#include <stdio.h>
int main()
{
/*val1+val2=val3*/
unsigned int val1 = 1;
unsigned int val2 = 2;
unsigned int val3 = 0;
printf("val1:%d,val2:%d,val3:%d\n",val1,val2,val3);
asm volatile(
"movl $0,%%eax\n\t" /*clear %eax to 0*/
"addl %1,%%eax\n\t" /*%eax += val1*/
"addl %2,%%eax\n\t" /*%eax += val2*/
"movl %%eax,%0\n\t" /*val2 = %eax*/
: "=m" (val3) /* output =m mean only write output memory variable*/
: "c" (val1),"d" (val2) /*input c or d mean %ecx/%edx*/
);
printf("val1:%d+val2:%d=val3:%d\n",val1,val2,val3);
return 0;
}

内嵌汇编常用限定符

c_asm.png

asm2.c

int main(void)
{
    int input, output, temp;
    input = 1;
    __asm__ __volatile__(
        "movl $0, %%eax;\n\t"
        "movl %%eax, %1;\n\t"
        "movl %2, %%eax;\n\t"
        "movl %%eax, %0;\n\t"
        : "=m"(output), "=m"(temp)
        : "r"(input)
        : "eax"
    );
    printf("%d %d\n", temp, output);
    return 0;
}

// %0代表output, %1代表temp, %2代表input
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容