当前位置: 首页 > news >正文

Linux C编译器从零开发一

基础程序汇编
test.c
int main() {
  return 42;
}
查看反汇编
cc -o test test.c
objdump -d -M intel test
0000000000001129 <main>:
    1129:	f3 0f 1e fa          	endbr64 
    112d:	55                   	push   rbp
    112e:	48 89 e5             	mov    rbp,rsp
    1131:	b8 2a 00 00 00       	mov    eax,0x2a
    1136:	5d                   	pop    rbp
    1137:	c3                   	ret
函数参数汇编
test.c

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

int main() {
  return plus(3, 4);
}

.intel_syntax noprefix
.globl plus, main

plus:
        add rsi, rdi
        mov rax, rsi
        ret

main:
        mov rdi, 3
        mov rsi, 4
        call plus
        ret

 .globl开头表示函数整个程序可见
call原理
  • call将下一条指令(在本例中)ret的地址推入堆栈
  • call跳转到作为参数给出的地址
自定义编译器编译基础程序
test.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "Please input a Number:\n");
    return 1;
  }
  printf(".intel_syntax noprefix\n");
  printf(".globl main\n");
  printf("main:\n");
  printf("  mov rax, %d\n", atoi(argv[1]));
  printf("  ret\n");
  return 0;
}
 编译运行
cc -o test test.c
./test 42 > test.s
cc -o tmp test.s
./tmp
echo $?
 自定义编译器编译加减法程序
test.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "Please input a Number\n");
    return 1;
  }

  char *p = argv[1];

  printf(".intel_syntax noprefix\n");
  printf(".globl main\n");
  printf("main:\n");
  printf("  mov rax, %ld\n", strtol(p, &p, 10));
  // strtol读取数字,读完自动跳到下个符号
  while (*p) {
    if (*p == '+') {
      p++;
      printf("  add rax, %ld\n", strtol(p, &p, 10));
      continue;
    }

    if (*p == '-') {
      p++;
      printf("  sub rax, %ld\n", strtol(p, &p, 10));
      continue;
    }

    fprintf(stderr, "illegal sign '%c'\n", *p);
    return 1;
  }

  printf("  ret\n");
  return 0;
}
 编译
cc -o test test.c
./test 12+3+4 > tmp.s
cc -o tmp tmp.s
./tmp
echo $?
./test 1*3 > tmp.s //会提示非法符号
测试
test.sh
#!/bin/bash
assert() {
  expected="$1"
  input="$2"

  ./chibicc "$input" > tmp.s || exit
  gcc -static -o tmp tmp.s
  ./tmp
  actual="$?"

  if [ "$actual" = "$expected" ]; then
    echo "$input => $actual"
  else
    echo "$input => $expected expected, but got $actual"
    exit 1
  fi
}

assert 0 0
assert 42 42
assert 21 '5+20-4'

echo OK

参考

Compiler Explorer 


创作不易,小小的支持一下吧!

相关文章:

  • JVM 根可达算法
  • C++ 20新特性之线程与jthread
  • Matlab的Simulink系统仿真(simulink调用m函数)
  • 一文搞定 大语言模型(LLM)微调方法
  • C# Winform 用户控件,扩展控件,自定义控件综合实例
  • STM32项目分享:智能窗帘系统
  • IT入门知识博客文章大纲第二部分《编程语言》(2/10)
  • Qt QStackedWidget类详细分析
  • SVN 报错Error: Unable to connect to a repository at URL解决方法
  • 【考研数据结构——C语言描述】第四章 串
  • MySQL的高可用方案:深入Galera Cluster和ProxySQL
  • 【Docker系列】跨平台 Docker 镜像构建:深入理解`--platform`参数
  • Golang - 连接MySQL执行查询脚本
  • OpenAI 宕机事件:GPT 停摆的影响与应对
  • Flink 命令行提交、展示和取消作业
  • 安装golang
  • 【机器学习】神经网络与深度学习:探索智能计算的前沿
  • Python基础教程(十五):面向对象编程
  • 聚焦赛宁网安竞赛平台+赛事服务,引领网络安全竞赛新潮流
  • 浏览器无痕模式和非无痕模式的区别
  • 山大齐鲁医院通报“子宫肌瘤论文现男性患者”:存在学术不端
  • 五一小长假上海“人从众”,全要素旅游交易总额超200亿元
  • 四人自驾游宣恩因酒店爆满无处住宿,求助文旅局后住进局长家
  • 巴菲特批评贸易保护主义:贸易不该被当成武器来使用
  • 抗战回望15︱《五月国耻纪念专号》:“不堪回首”
  • 17家A股城商行一季报扫描:青岛银行营收增速领跑,杭州银行净利增速领跑