1.代码

foo.asm

[plain] view plaincopy
  1. ;编译链接的方法
  2. ;(id的'-s'选项意为"strip all")
  3. ;
  4. ;$ nasm -f elf foo.asm -o foo.o
  5. ;$ gcc -c bar.c -o bar.o
  6. ;$ id -s hello.o bar.o foobar
  7. ;$ ./foobar
  8. ;the 2nd one
  9. ;$
  10. extern choose       ;int choose(int a,int b)
  11. [section .data]     ;数据在此
  12. num1st  dd  3
  13. num2nd  dd  4
  14. [section .text]     ;代码在此
  15. global _start       ;我们必须导出 _start 这个入口,以便让链接器识别
  16. global myprint      ;导出这个函数为了让bar.c使用
  17. _start:
  18. push    dword [num2nd]  ;'.
  19. push    dword [num1st]  ;|
  20. call    choose      ;|choose(num1st,num2nd);
  21. add esp,8       ;/
  22. mov ebx,0
  23. mov eax,1       ;sys_exit
  24. int 0x80        ;系统调用
  25. ;void myprint(char* msg,int len)
  26. myprint:
  27. mov edx,[esp + 8]   ;len
  28. mov ecx,[esp + 4]   ;msg
  29. mov ebx,1
  30. mov eax,4       ;sys_write
  31. int 0x80        ;系统调用
  32. ret

bar.c

[plain] view plaincopy
  1. void myprint(char* msg,int len);
  2. int choose(int a,int b)
  3. {
  4. if(a>=b) {
  5. myprint("the 1st one\n",13);
  6. }
  7. else {
  8. myprint("the 2nd one\n",13);
  9. }
  10. return 0;
  11. }

2.编译连接+执行(32位)

> ls

bar.c  foo.asm

> nasm -f elf32 -o foo.o foo.asm

> gcc -m32 -c -o bar.obar.c

> ld -m elf_i386 -s -o foobar foo.o bar.o

> ls

bar.c  bar.o  foo.asm  foobar  foo.o

> ./foobar

the 2nd one

3.代码解释

extern:EXTERN 伪操作告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号。如果本源文件没有实际引用该符号,该符号将不会被加入到本源文件的符号表中。

global:关键字,把符号导出到其他模块中。global是extern的对立面,如果一个模块声明一个extern的符号,然后引用它,为了防止链接错误,另外某一个模块必须确实定义了该符号,然后把它声明为global。

1.由于在bar.c中用到函数myprint(),所以要用关键字global将其导出

2.由于用到本文件外定义的函数choose(),所以要用关键字extern声明

3.myprint()和choose()遵循的都是C调用约定,后面的参数先入栈,并由调用者清理堆栈

dd:伪指令——定义双字。其后的每个操作数占用二个字(低字在前)。 DD还可以把其后的变量或标号的偏移地址和所在段首址存入存储器内指定 的双字单元(即DD前面的变量)中,第一个字中存放DD后的变量的偏移地址, 第二个字中存放该变量所在段的段首址。

push:入栈操作,遵守FILO原则(first in last out),而且必须是字操作。

dword:是双字,也就是32位,可以用来储存32位整数或者32位内存地址。[拓展:byte是字节,也就是8位,用来储存char或者char类型指针。word是字,也就是16位。用来储存16位整数或者16位地址]

add:操作数相加。ADD OPRD1,OPRD2。

1.OPRD1为任一通用寄存器或存储器操作数,可以是任意一个通用寄存器,而且还可以是任意一个存储器操作数。
   2.OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数。
   3.OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另一个为存储器也是允许的, 但不允许两个都是存储器操作数。
   4.加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响.以上标志也称为结果标志.加法指令适用于无符号数或有符号数的加法运算。

--------------------------------------------------------//32bit或64bit版本

生成的.o文件必须都是32位或者都是64位:

-------------------------------------gcc 命令行参数:

-m32:生成32位代码

-m64:生成64位代码

-------------------------------------连接时版本注明:

-m elf_i386 :32位

-m elf_x86_64:

-m elf32_x86_64:

-------------------------------------编译时版本注明:

-f elf64:64位

-f elf32:32位

---------------------------------------------------------//命令行

-c:只编译并生成目标文件

./:表示当前目录的全路径,一般不在系统环境变量path中的可执行文件 ,运行的时候都要这样运行,当然写成绝对路径也行

Ubuntu下用gcc与nasm联合编译相关推荐

  1. GCC跟NASM联合编译

    GCC跟NASM联合编译 GCC和NASM联合编译 GCC和NASM GCC不用说,C语言的编译器.NASM是一个x86的汇编器,用来编译汇编的.最近在研究GCC和NASM联合编译,为什么要研究二者的 ...

  2. qt程序在Linux下字体乱了,解决linux/Ubuntu下Qt creater 界面程序在编译运行后无法显示中文或中文乱码问题!...

    本文解决的主要是界面程序编译运行后无法显示中文的问题,如果在creater 中无法输入中文,下载个IBus或者搜狗之类的中文输入法即可解决! 首先说乱码问题,这个很好解决: 如果是在linux下打开W ...

  3. Ubuntu下安装并配置VS Code编译C++

    Ubuntu下安装并配置VS Code编译C++

  4. 【Linux入门到精通系列讲解】Ubuntu下使用gcc编译并运行C程序

    文章目录 1 hello 2 命令 3 linux下gcc编译多个源文件 1 hello 2 命令 在终端输入 Ubuntu命令 $ gcc hello.c -o hello $ ./hello == ...

  5. Ubuntu下使用GCC开发STM32的环境的搭建

    注:从ubuntu linux下建立stm32开发环境: GCC安装以及工程Makefile建立转载. 1.STM 32 GCC 安装 stm32 属于arm cortex-m系列thumb指令集,所 ...

  6. VScode使用记录二:Windows 7下安装GCC、使用VSCode编译代码

    目录 一.概述 二.安装 2.1 GCC编译器 2.2 安装VSCode 2.3 安装插件 三.编译文件 3.1 编译单个文件 3.2 编译多个文件 四.调试程序 一.概述 平时都是在keil下工作, ...

  7. C++和NASM联合编译

    有时候需要在C/C++里调用汇编代码,但又不想写内联asm,就需要一些特殊手段了. 在64位编译32位的代码 划重点,我用的是64位的Centos7.Ubuntu同理,但是安装的库不太一样,下面会提到 ...

  8. 黄聪:Ubuntu下使用低版g++编译器编译TSE

    由于高版本的g++编译器语法比较严格,所以在编译TSE原代码tse* 的时候会出现一些语法错误,导致编译不通过,经过再网上搜索资料,终于把这个问题解决了.以下是摘录的网上资料,最后面附着的红字部分是自 ...

  9. Ubuntu下使用gcc和makefile编写c语言程序

    文章目录 前言 一.gcc编写c语言程序 1.hello world的输出 2.简单程序的编译与运行 3.windows环境下的编译运行结果对比 二.makefile编写c语言程序 总结 前言 本文通 ...

最新文章

  1. 三维激光重建原理与实现HALCON
  2. Groovy安装与入门实例
  3. sitemesh的使用
  4. 用户操作-用户添加操作代码实现
  5. 现在的编译器还需要手动展开循环吗_DSP(知识点+思考题)
  6. 34观察者模式(Observer Pattern)
  7. oh-my-zsh扫描git仓库卡慢的解决方法
  8. Python绘制直方图案例一则
  9. javascript模板库jsrender加载并缓存外部模板文件
  10. GCC的__attribute__ ((constructor))和__attribute__ ((destructor))
  11. 我的技术博客开通了!
  12. 第一部分 第二章 答案合集(part 1)1006-1023
  13. NXP JN5169使用UART发送数据
  14. [译] 为什么你要学习 Go?
  15. 什么样的语言可以进行反编译
  16. 人工智能基础之美女和野人过河问题
  17. nodejs+vue+elementui鲜花销售商城管理系统410
  18. 为echarts的叠加柱状图设置颜色
  19. 基于BLE的IoT智能灯泡的安全漏洞利用
  20. mysql 外键唯一,关于mysql:外键可以引用非唯一索引吗?

热门文章

  1. 【错误记录】VMware 虚拟机报错 ( 向 VMWare 虚拟机中的 Ubuntu 系统拷贝文件时磁盘空间不足 )
  2. 【Groovy】编译时元编程 ( 编译时方法拦截 | 在 MyASTTransformation#visit 方法中进行方法拦截 )
  3. 【Android 应用开发】Canvas 精准绘制文字 ( 文本边界坐标解析 | 绘图位置 )
  4. 【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★
  5. 【Android 逆向】substrate 框架 ( substrate 简介 | substrate 相关文档资料 )
  6. 【错误记录】Mac 中 IntelliJ IDEA 运行 Python 程序报错 ( End of statement expected )
  7. 【OkHttp】OkHttp 源码分析 ( 同步 / 异步 Request 请求执行原理分析 )
  8. 【集合论】有序对 ( 有序对 | 有序三元组 | 有序 n 元祖 )
  9. 数据性能调校——查看最耗资源的各种SQL
  10. C# System.Reflection (反射)