c语言中if语句是怎么变成汇编代码的详解

 更新时间:2021年11月24日 09:19:05   作者:Just_4_fun  
if语句是指编程语言,包括c语言、C#、VB、java、汇编语言等,下面这篇文章主要给大家介绍了关于c语言中if语句是怎么变成汇编代码的相关资料,需要的朋友可以参考下

 1. 要编译的测试代码: 

int a;
int b = 3;

int main(void)
{
    if (3)
        a = 4;
    else
        b = 5;
}

2. 词法分析

  词法分析将c源代码解析成一个个的token。

  关键的,将if两个字符解析成一个if token,后续语法分析的输入就从两个字符减少为1个token,减小了语法分析的难度。

3. 语法分析

if (equal(tok, "if")) {
    Node *node = new_node(ND_IF, tok);
    tok = skip(tok->next, "(");
    node->cond = expr(&tok, tok);
    tok = skip(tok, ")");
    node->then = stmt(&tok, tok);
    if (equal(tok, "else"))
      node->els = stmt(&tok, tok->next);
    *rest = tok;
    return node;
  }

如果当前处理的token是if,则

3.1 创建新的类型为ND_IF的node。

3.2 跳过if后面的"("。

3.3 调用expr函数解析if语句()中的表达式,并将解析结果存储在node->cond。

3.4 跳过“)”。

3.5 调用stmt处理then语句块中的语句,这里是处理"a = 4;",将解析结果存储在node->then。

3.6 如果if语句还有else部分,则调用stmt处理else语句块中的语句,这里是处理"b = 5;",将解析结果存储在node->els。

3.7 node->cond,node->then,node->els都为node节点。

4. 代码生成

switch (node->kind) {
  case ND_IF: {
    int c = count();
    gen_expr(node->cond);
    cmp_zero(node->cond->ty);
    println("  je  .L.else.%d", c);
    gen_stmt(node->then);
    println("  jmp .L.end.%d", c);
    println(".L.else.%d:", c);
    if (node->els)
      gen_stmt(node->els);
    println(".L.end.%d:", c);
    return;
  }
...

如果当前处理的node节点类型为ND_IF,则

4.1 gen_expr

这个函数处理if语句的条件部分,这里是处理3。判断node节点为NUM,会生成汇编语句"mov     rax, 3",将3载入rax寄存器。

4.2 cmp_zero

cmp_zero会生成汇编语句"cmp     eax, 0",比较3和0。

4.3 println(" je .L.else.%d", c);

该语句会生成汇编代码" je .L.else.1",当上条比较语句中eax为0时会执行跳转,跳转到else分支运行。这里由于eax为3,所以不跳转。

4.4 gen_stmt(node->then);

这条语句会将then分支中的语句解析为汇编源码,这里是"a = 4;",这条语句是表达式语句,所以会调用gen_expr函数。

4.4.1 gen_expr

"lea     rax, a",将a的地址载入rax寄存器中。

"push rax",将rax入栈。

"mov     rax, 4",将4载入rax寄存器中。

"pop     rdi",将变量a的地址载入rdi寄存器。

"mov     [rdi], eax",将4写入变量a。 

4.5 println(" jmp .L.end.%d", c);

执行完then分支代码后跳转到下一条语句处执行。

4.6 println(".L.else.%d:", c);

插入一条标签,表示else分支代码的开始,如果if语句条件为0会跳转到这。

4.7 gen_stmt(node->els);

生成else分支代码,处理"b = 5;"。

"lea     rax, b",将变量b的地址载入rax寄存器。

"push    rax",将rax寄存器入栈。

"mov     rax, 5",将5载入rax寄存器。

"pop     rdi",将b的地址载入rdi寄存器。

"mov     [rdi], eax",将5写入变量b中。

4.8 println(".L.end.%d:", c);

插入一条标签,表示if语句的结束,then分支语句执行完成后跳转到这里。

总结

到此这篇关于c语言中if语句是怎么变成汇编代码的文章就介绍到这了,更多相关c语言if语句变成汇编代码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言:自定义类型详解

    C语言:自定义类型详解

    这篇文章主要介绍了C语言自定义函数详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-09-09
  • Linux C/C++实现网络流量分析工具

    Linux C/C++实现网络流量分析工具

    网络流量分析的原理基于对数据包的捕获、解析和统计分析,通过对网络流量的细致观察和分析,帮助管理员了解和优化网络的性能,本文将通过C++实现网络流量分析工具,有需要的可以参考下
    2023-10-10
  • C语言中的一维数组与二维数组的实现

    C语言中的一维数组与二维数组的实现

    数组可以帮我们巧妙解决生活中的问题,使我们的代码简洁,本文主要介绍了C语言中的一维数组与二维数组,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • 用C++实现单向循环链表的解决方法

    用C++实现单向循环链表的解决方法

    本篇文章是对用C++实现单向循环链表的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 详解C语言中双指针算法的使用

    详解C语言中双指针算法的使用

    双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。本文将通过示例带大家深入了解双指针算法的使用
    2022-08-08
  • C语言实现一个闪烁的圣诞树

    C语言实现一个闪烁的圣诞树

    本文详细讲解了C语言实现一个闪烁的圣诞树,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • 完全掌握C++编程中构造函数使用的超级学习教程

    完全掌握C++编程中构造函数使用的超级学习教程

    这篇文章主要介绍了C++中的构造函数,包括C++11标准中的新特性的介绍,十分推荐!需要的朋友可以参考下
    2016-01-01
  • 深入解析C++中的函数模板和函数的默认参数

    深入解析C++中的函数模板和函数的默认参数

    这篇文章主要介绍了深入解析C++中的函数模板和函数的默认参数,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • 一起来了解一下C++中的指针

    一起来了解一下C++中的指针

    这篇文章主要为大家详细介绍了C++的指针,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++ Opencv实现录制九宫格视频

    C++ Opencv实现录制九宫格视频

    这篇文章主要为大家介绍了如何利用C++和OpenCV库实现录制九宫格视频,文中的示例代码讲解详细,对我们学习OpenCV有一定帮助,感兴趣的可以了解一下
    2022-05-05

最新评论