从25行汇编代码看计算机工作步骤

飞鸟 原创作品转载请注明出处 《Linux操作系统分析》MOOC课程

1. 编写C语言代码main.c

int g(int x)
{
return x + 7;
}

int f(int x)
{
return g(x);
}

int main(void)
{
return f(4) + 2;
}

2.编译输出为汇编代码

在64位Linux虚拟机上执行以下命令:

gcc –S –o main.s main.c -m32

-m32指明输出为32位汇编代码

3.汇编代码解释

1.32位通用寄存器

  • eax 累加器

    乘、除、输入、输出等

  • ebx 基地址寄存器

    可作为存储器指针

  • ecx 计数寄存器

    指示循环及位移次数

  • edx 数据寄存器

    存放I/O端口地址

  • ebp 堆栈基指针

  • esp 堆栈顶指针

    存放堆栈内存储单元的偏移量

  • esi edi 变址寄存器

    存放存储单元在段内的偏移量

2.段寄存器

  • CS 代码段

    代码段的段值

  • DS 数据段

    数据段的段值

  • ES 附加段

    附加数据段的段值

  • SS 堆栈段

    堆栈段的段值

  • FS 附加段

    附加数据段的段值

  • GS 附加段

    附加数据段的段值

汇编代码程序截图

汇编程序代码截图

常见汇编指令介绍

  • movl %eax, %edx
    • edx = eax; 寄存器寻址
  • movl $0x123, %edx
    • edx = 0x123 立即寻址,立即数是以$开头的数值
  • movl 0x123, %edx
    • edx = (int32_t)0x123 直接寻址 直接访问一个指定的内存地址的数据
  • movl (%ebx), %edx
    • edx = (int32_t)ebx 间接寻址 将寄存器的值作为一个内存地址来访问内存
  • movl 4(%ebx), %edx

    • edx = (int32_t)(ebx + 4) 变址寻址 在间接寻址之时改变寄存器的数值
  • pushl %eax

    • subl $4, %esp
    • movl %eax, (%esp)
  • popl %eax
    • movl (%esp), %eax
    • addl $4, %esp
  • call 0x12345
    • pushl %eip
    • movl $0x12345, %eip
  • ret
    • popl %eip
  • enter
    • pushl %ebp
    • movl %esp,%ebp
  • leave
    • movl %ebp, %esp
    • popl %ebp

注:

  • eip寄存器不能被直接修改,只能通过特殊指令间接修改;
    eip 指示了当前要执行的指令;
  • ebp esp 指示了程序执行的堆栈空间;
  • eax 作为运算结果的保存值使用;函数的返回值默认使用eax寄存器存储返回给上一级函数
汇编代码说明
1g:
2   pushl   %ebp
3   movl    %esp, %ebp
4   movl    8(%ebp), %eax
5   addl    $7, %eax
6   popl    %ebp
7   ret
8f:
9   pushl   %ebp         
10  movl    %esp, %ebp   
11  subl    $4, %esp      
12  movl    8(%ebp), %eax  
13  movl    %eax, (%esp) 
14  call    g           
15  leave               
16  ret                 
17main:     //主函数
18  pushl   %ebp        
19  movl    %esp, %ebp  
20  subl    $4, %esp    
21  movl    $8, (%esp)  
22  call    f             
23  addl    $2, %eax   
24  leave              
25  ret                

程序从main函数开始
首先,保存ebp的值,然后将ebp的值设为esp,相当于保存原函数的堆栈,然后建立当前函数的堆栈
把立即数4压栈,然后调用函数f
将当前ebp所指向的堆栈位置向上数两个的位置,也就是放4的那个位置,压栈
做一个变址寻址,即将4放入累加器eax中
累加器再加7,累加器为11.
然后pop %ebp,相当于leave,由于g函数中没有额外压栈,所以不做mov指令
返回f函数
esp向上移动一个堆栈位置然后leave
返回main
同样esp向上移动一个堆栈位置然后leave,与此同时eax加2,得到最终值13
程序结束

小结:

通过汇编代码的逐行解释,了解了重要寄存器的功能及CPU执行命令的实现过程。按照冯诺依曼计算机结构,计算机工作的过程就是CPU不断从通过指针从寄存器中读取、执行指令。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值