今天看到一个很有意思的小程序,它让我对Linux下C程序的编译链接有了一个全新的认识!

这个程序的就是写一个简单的输出“hello World!”:

要求:1.不使用C运行库,写一个独立于任何库的程序。(也就是说我们不能#include)。

2.不适用main函数为程序的入口(大家都知道一般使用了库的程序都是使用main函数作为程序的入口,在这里我们使用自己写的函数nomain作为程序的入口)。

3.使用连接器ld把程序的所有段合为一个“Tinytext”段。

显然要符合要求我们就只能用汇编去写,源代码如下:char *str="Hello world!\n";

void print()

{

asm("movq $13,%%rdx \n\t"

"movq %0,%%rcx \n\t"

"movq $0,%%rbx \n\t"

"movq $4,%%rax \n\t"

"int $0x80     \n\t"

::"r"(str):"edx","ecx","ebx");

}

void exit()

{

asm("movq $42,%rbx   \n\t"

"movq $1,%rax    \n\t"

"int $0x80       \n\t");

}

void nomain()

{

print();

exit();

}

我们vi一个TinyHelloWorld.c。里面写上如上代码。

本人的环境是64位的,如果是32为环境的朋友只要把,movq改为movl,rdx改为edx,rax改为eax,rbx改为ebx。

由于操作系统的系统结构发生了变化,在x86-64中,所有通用寄存器(GPRs)都从32位扩充到了64位,名字也发生了变化。8个通用寄存器(eax, ebx, ecx, edx, ebp, esp, esi, edi)在新的结构中被命名为rax, rbx, rcx, rdx, rbp, rsp, rsi, rdi。movl命令也需相应改成movq。

首先程序的入口时nomain函数,它调用print函数打印HelloWorld,然后调用exit函数退出。print函数使用了Linux的WRITE系统调用,exit函数使用了EXIT系统调用。

定义一个字符串,它是放在只读代码段的。

print函数和exit函数中,WRITE系统调用和EXIT系统调用都是通过0x80中断实现的。其中eax为调用号rbx,rcx,rdx是一些寄存器用来传递参数的。比如WRITE系统调用是往一个文件句柄写入数据,如果用C语言来表示WRITE系统调用的话他的函数原型是:int write(int filedesc,char* buffer,int size)WRITE的调用号为4,则rax为0。

filedesc表示被写入的句柄文件,我们默认输出为默认终端,他的句柄为0,所以rbx为0。

buffer表示要写入的缓冲区地址使用rcx寄存器传送,我们要输出str字符串,所以rcx=str。

size表示要写入的字节数,这里str的长度为13字节,所以rdx=13。

代码写好以后我们使用普通的命令行来编译链接TinyHelloWorld.cgcc -c -fno-builtin TinyHelloWorld.c  //生成TinyHelloWorld.o-c参数是表示编译。

-fno-builtin参数关闭GCC内置函数的功能(GCC中有很多内置的函数,它你会把C库的一些函数替换成内置的函数,以达到优化的功能)

然后链接TinyHelloWorld.o文件生成可执行文件TinyHelloWorld.ld -static -e nomain -o TinyHelloWorld TinyHelloWorld.o-static参数指在这里使用静态链接方式。

-e nomai参数表示程序的入口为nomain函数

-o 表示链接

运行可以输出Hello World!

至此,一个HelloWorld程序写好了。

我们使用objdump指令来查看TinyHelloWorld这个文件可以看出来他又4个段:.data .rodata .text .commond 段。这几个段的属性都是只读的,按理来说我们可以把他们合围一个段。这就需要借助ld链接器来实现。objdump -h TinyHelloWorld

使用-verbose查看默认的链接脚本信息:ld -verbose TinyHelloWorld

然后编写TinyHelloWorld.lds脚本:ENTRY(nomain)

SECTIONS

{

.= 0x08048000 + SIZEOF_HEADERS;

tinytext : { *(.text) *(.data) *(.rodata)}

/DISCARD/ :{ *(.comment) }

}

然后使用自己编写的脚本链接目标文件。gcc -c -fno-builtin TinyHelloWorld.

ld -static -T TinyHelloWorld.lds -o TinyHello TinyHelloWorld.o

-static -T TinyHelloWorld.lds参数是使用静态链接,并且使用自己编写的TinyHelloWorld.lds脚本链接。

它会生成一个588个字节的可执行文件TinyHelloWorld。执行可以打印Hello World!。如果你使用objdump查看TinyHelloWorld的段,你会发现我们达到了将最后一个只有一个段的要求。

linux连接到程序,Linux下C程序的链接过程相关推荐

  1. linux连接磁盘阵列,CentOS/Linux 连接 iSCSI 磁盘阵列

    CentOS/Linux连接iSCSI磁盘整列 iSCSI:即Internet Small Computer System Interface 系统环境:CentOS 6.5 mini 磁盘阵列:联想 ...

  2. 用TortoiseGit工具push上传程序和下拉程序pull

    目录 TortoiseGit安装与配置 如何上传程序push 如何下拉程序pull TortoiseGit安装与配置 安装TortoiseGit.可从网上搜索下载. Settings方法如下: 注:一 ...

  3. linux用于开发qt java_Linux下Qt程序的打包发布

    为便于描述,我们这里假设生成的程序名称为test(即要发布的程序名称) 方法一: 1. QtCreate使用Release版本编译 将编译后生成的可执行程序(如:test)复制到一个空目录下 2.使用 ...

  4. linux在python的虚拟环境下运行程序_在win10和linux上分别安装Python虚拟环境的方法步骤...

    很多初学者会使用windows作为开发机使用, 今天就来看下如何在win10和Linux下分别安装Python虚机环境.虚机环境有非常多的优点,今天我们用的虚拟环境是virtualenv. virtu ...

  5. linux java socket编程_linux下java程序与C语言程序通过SOCKET通信的简单例子

    #include int sockfd,newfd; void *read_socket(); int main() { int ret; pthread_t read_tid,write_tid; ...

  6. linux连接池等待时间,LINUX系统下解决time_wait 连接数过多问题

    经常检查apache的连接数,会发现很多无用的time_wait连接.有人说这是正常的,是因为一个请求中途中断造成的:还有人说微软的IE连接时产生的Time_wait会比用Firefox连接时多.个人 ...

  7. linux连接校园网wifi,Linux/Ubuntu 16.04 使用校园网客户端Dr.com DrClient 有线连网,同时开启WiFi热点...

    前面写过Ubuntu 16.04 使用校园网客户端 DrClient 无线上网,在这篇文章中将要介绍下,在Ubuntu 16.04上如何使用校园网客户端实现有线登录,这个问题也让博主困惑了很久,但是问 ...

  8. linux mysql 5.6.22_linux下MySQL5.6.2安装过程

    MySQL是一个关系型数据库管理系统,并且又是开源的,现在很多系统和网站都在使用它,今天给大家分享下我在linux下安装MySQL5.6.2的过程以及遇到的问题. 环境:CentOS release ...

  9. linux 连接存储,在Linux中连接和使用云存储的三种途径

    个人云存储现在变得非常有用,因为你再也不用担心你把东西存储在什么地方了:你能很容易的获取你的文件,并时刻保持文件更新.在Linux上你也多种保持访问你的云存储.这一点非常棒,因为你可以使用你最喜欢的方 ...

  10. linux 连接投影仪软件,linux连接投影机方法介绍

    方案一: 一般来说,需要笔记本当前使用的分辨率和投影仪的分辨率相同,才能在投影仪上显示笔记本的X.那么,可以先运行这个命令: $xrandr 比如在我的电脑上,结果如下: [2007-04-11 09 ...

最新文章

  1. c++概念模型的官方解释
  2. Spring Boot 线程池的创建、@Async 配置步骤及注意事项
  3. 【微服务学习】Polly:熔断降级组件
  4. linux给ftp账号分配sftp权限,Linux设置用户通过SFTP访问目录的权限教程
  5. 数学归纳法在数据结构与算法分析设计中的应用
  6. r语言把多个图合并在一张图_R语言绘图 | 折线图画法,如何画出你满意的图?
  7. 【渝粤教育】国家开放大学2018年秋季 0363-21T市场调查与预测 参考试题
  8. 出走的门徒之一——地平线 余凯:造物主的一小步
  9. 零基础学习CANoe Panel(13)—— 滑条(TrackBar )
  10. 学习如何使用 Git 来压扁、变基和精选
  11. Bert入门:使用Bert运行MRPC的demo成功案例
  12. 为什么RGB 与 CMYK的差异,会有所不同?
  13. android 谷歌定位demo,android实现定位与目的地的导航示例代码
  14. 2022年PMP考试的3A好考吗?
  15. 如何预防网站http劫持问题?
  16. 最实用的 Docker 知识(一)
  17. linux stopped 进程,linux 查杀 stopped 进程
  18. android防拆机方案,拆机狂人必备 iFixit Android客户端试用
  19. 什么是空头陷阱?(全网最全面的分析)?
  20. 10大最具智慧毕业典礼演讲 求知若饥虚心若愚

热门文章

  1. Kaggle问题总结1
  2. 系统安装操作优化:chapter 3 安装windos操作系统。
  3. 统计学习:线性回归分析(1)
  4. 该段代码编译运行后显示的是蓝色背景,白色闪烁字的效果
  5. 基于MATLAB的LS-SVM实现方法以及SVM的一些知识点
  6. Caffe常用层参数介绍
  7. 阴差阳错2019-12-13
  8. 2-3 人工智能需要的基本数学知识|人工智能框架TensorFlow应用实践
  9. 等值连接_sql高阶教程:非等值自连接
  10. 3DSlicer3:模块管理(一)颜色、DCM、数据、模型、注释