机器代码层面的函数调用

2018.04.18

CPU 发出指令把硬盘程序指令搬到内存,操作系统给程序指令分配内存。然后操作系统会告诉 CPU 「程序入口点」,也就是第一条指令地址。

CPU 从内存出取得的指令一般是这三类:

  1. 把数据从内存运到 CPU 寄存器。
  2. 对寄存器数据进行运算。
  3. 把寄存器数据写入到内存。

x86 体系机器:每次函数调用都会创建一个帧。

帧,内存中一段连续空间。

多个函数帧在内存里排起来, 就像一个先进后出的栈一样。

但这个栈与普通的栈不一样,这个栈的栈底在上面,从上往下生长(从高地址往低地址生长)。
4 个字节为单位,4 个字节内从低地址往高地址生长。

ebp,CPU 特殊寄存器,指向栈中当前函数帧的起始地址。
esp,CPU 特殊寄存器,指向栈中当前函数帧的尾地址。

ebp 与 esp

下面是 CPU 向内存取的函数调用指令。

  1. 把 ebp 的值压入栈中。(CPU -> 内存)
    这时,地址 800~804 的内容是 1000,esp 指向地址 800 。

  2. 把 esp 的值赋给 ebp 。(CPU)
    这时,esp、ebp 同时指向地址 800,一个新的函数帧诞生!
    函数帧的起始地址是 800, 里边的内容是1000 。

  3. 把 esp 的值减去 24 。(CPU)
    esp 指向地址 776,这是为准备函数实参腾出空间。
    减去 24 是为了数据对齐。24 + 4(入栈的 ebp) + 4(返回地址) = 32 。
    x86 编程规定函数帧是 16 的整数倍。

  4. 把 10 放到 ebp 减去 4 的地址,把 20 放到 ebp 减去8的地址。(CPU -> 内存)
    其实就是:int x=10; int y=20 。

  5. 把 x 地址放到 esp 指向的地址,把 y 地址放到 esp+4 指向的地址。
    其实就是准备实参 &x, &y 。

准备函数实参
  1. 把地址 100 压入栈中。
    这是调用函数之前,调用方下一条指令地址(函数返回地址)压入栈。
int sum = add(&x, &y); 
printf("the sum is %d\n",sum);  // 假设这条指令的地址是 100
准备返回地址
  1. 函数调用前的保护现场,以便返回时恢复现场。 (CPU -> 内存)
    把寄存器 ebp 的值压到栈里去
    把 esp 的值赋给 ebp
    把寄存器 ebx 的值压入栈
保护现场
  1. CPU 取出数据计算。(CPU)
int add(int *xp , int *yp){
    int x = *xp;
    int y = *yp;
    return x+y
}

把 ebp 加 8 的数据取出来放到 edx 寄存器。取得 xp 。
把 ebp 加 12 的数据取出来放到 ecx 寄存器。取得 yp 。
把 edx 指向的内存地址的数据取出来,放到 ebx 寄存器。取得 *xp 放入 ebx 。
把 ecx 指向的内存地址的数据取出来,放到 eax 寄存器。取得 *yp 放入 eax 。
把 ebx 和 eax 的值加起来,放到 eax 寄存器中。取得 *xp+*yp,放入 eax 。

  1. 恢复现场。(内存 -> CPU)
    把 esp 指向的数据弹出的 ebx 寄存器。
    把 esp 指向的数据弹出到 ebp 寄存器。
恢复现场
  1. 返回。
    CPU 取出返回地址 100,去那里找到指令继续执行。

函数调用总结

  1. 把参数和返回地址准备好。

  2. 新建函数帧:
    把寄存器 ebp 的值压入栈。
    把 esp 的值赋给 ebp。

  3. 函数调用完后, 重置 ebp 和 esp,让他们重新指向调用方的函数帧。

内存缓冲区溢出

用户输入的数据是从低地址向高地址存放的。

黑客输入精心设计的数据过多以至于覆盖了返回地址,让返回地址指向恶意代码入口地址。

输入函数有边界检查就可避免攻击。

参考文档:
http://mp.weixin.qq.com/s/hX8tHnoq4gdkhcLHUGzEbg
http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513039&idx=1&sn=381c1b8c7f86906c4838050b8c1db2bb&scene=21#wechat_redirect

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