news 2026/11/2 6:09:03

Linux C编译器从零开发一

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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


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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 6:07:50

脉冲线性调频雷达信号处理全链路解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 6:07:36

基于FPGA与STM32的PLFM_RADAR脉冲压缩雷达系统设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 6:07:06

工业SPI隔离通信设计:MAX14431BAEE+与PIC18F4458实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 6:07:01

用PLFM_RADAR搭建雷达感知系统:从线性调频到室内监测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 6:06:42

SPI隔离实战:用MAX14431BAEE+解决PIC18F96J94地电位差问题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 6:06:41

PLFM雷达原理与FPGA实现:高精度低功耗毫米波测距技术

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华