制作一个最小的Hello World程序

制作一个最小的Hello World程序

环境:

​ 1、WSL for Ubuntu(Linux系统即可)2、build-essential工具

正常的一个Hello World程序。

#include<stdio.h>
int main(){
	printf("Hello World!");
	reutrn 0;
}

使用 gcc --verbose demo.c 会看到一堆的编译链接信息。

如果不想依赖动态链接库编译,而静态编译使用命令 gcc -static demo.cls -l a.out 发现 a.out 有900多KB(-static 会复制libc),不符合最小的HelloWorld程序。然后使用 objdump -d a.out | less 查看汇编代码,发现很长的一堆汇编代码。

如果compile only gcc -c demo.c && objdump -d demo.o 发现汇编代码很短,然后 ld demo.o 出现警告提示不能找到入口符号 _strat 和一个错误不能找到puts的定义。接下来用hack的手法来躲过去:

#include<stdio.h>
#include<unistd.h>
void _start(){
//    printf("Hello World!\n");
}

​ 执行命令 gcc -c demo.c && objdump -d demo.o && ld demo.o 完美避过。通过 size a.out 发现只有90多B,基本符合最小的程序。尝试运行 a.out 出现 Segmentation fault(小尝试:如果在_start里面加入死循环 while(1); 就不会出现。)

​ 为什么呢?接下来就是通过Command gdb a.out状态机视角观察程序的状态转移(程序状态:内存Memory和寄存器register)

(gdb) starti #执行到第一条汇编语句
(gdb) layout asm #查看汇编代码调试界面
(gdb) si #汇编级调试下一步

发现下图这条语句执行后不正常退出。

在这里插入图片描述

报错信息:

(gdb) si
0x0000000000000001 in ?? ()

问题出在:进程的初始状态不能返回,然后程序异常退出。

有办法让状态机 “停下来” 吗?

  • 纯 “计算” 的状态机:不行
  • 要么死循环,要么 undefined behavior

解决办法:syscall

#include <sys/syscall.h>
int main() {
  syscall(SYS_exit, 42);
}
  • 调试代码:syscall 的实现在哪里?
    • 坏消息:在 libc 里,不方便直接链接
    • 好消息:代码很短,而且似乎看懂了

最小Hello World的代码诞生 minimal.S (.s是纯汇编文件,.S则是预处理+汇编)

#include <sys/syscall.h>

.globl _start
_start:
  movq $SYS_write, %rax   # write(
  movq $1,         %rdi   #   fd=1,
  movq $st,        %rsi   #   buf=st,
  movq $(ed - st), %rdx   #   count=ed-st
  syscall                 # );

  movq $SYS_exit,  %rax   # exit(
  movq $1,         %rdi   #   status=1
  syscall                 # );

st:
  .ascii "\033[01;31mHello, OS World\033[0m\n"
ed:

编译链接运行它 gcc -c minimal.S && ld minimal.o && ./a.out

输出:Hello, OS World

size a.out 发现大小只有74B。

代码阅读可以参考syscall的manual man syscall,也可以用gdb调试它。

Hint

gcc如果不指定可执行文件名称统一输出为a.out

.i文件是进行预编译之后生成的文件(可用command gcc -E xxx.c -o xxx.i 生成)。

.o文件又称object文件,是可执行文件(多个o文件链接成一个程序),.so 是shared object相当于windows的dll。

.s是纯汇编文件,.S则是预处理+汇编

ld(Link eDitor)命令是二进制工具集 GNU Binutils 的一员,是 GNU 链接器,用于将目标文件与库链接为可执行文件或库文件。(example:ld demo.o #链接demo.o到a.out上)

参考

南京大学2022操作系统-P2 中 最小的HelloWrold

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值