乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

Windows平台使用QEMU搭建ARM+Linux开发环境

发表于 2021-02-02

起因

由于目前市面上很多模拟器诸如夜神,网易MUMU,基本上使用的是x86的架构,虽然运行ARM程序没有问题,但是如果想使用gdb对ARM程序进行调试的话,就显得力不从心了,各种问题层出不穷,

当然调试x86程序是没有问题的,

如果非要对ARM程序进行gdb调试的话,可以采用Android Studio原生的模拟器(原生ARM太卡),但是考虑到很多人并不是从事安卓开发,加上Studio中的模拟器本就基于QEMU, 那么为了方便,我们直接搭建QEMU的环境

实验环境

  • Windows宿主平台

  • QEMU安装包(这里使用的是20201124的版本):https://qemu.weilnetz.de/w64/

  • 树莓派系统镜像:http://downloads.raspberrypi.org/raspbian/images/raspbian-2020-02-14/

    树莓派是基于Debian的Linux系统

操作步骤

QEMU下载安装完毕后,其安装目录会包含很多不同架构的执行文件,这里我们选择qemu-system-arm.exe,打开命令窗口:

1
qemu-system-arm.exe -machine versatilepb -L  -m 128  -hda 2020-02-13-raspbian-buster.img

相关指令选项介绍:

  • -M :指定机器
  • -name:给虚拟系统起个名称
  • -cpu:指定cpu型号
  • -smp :指定cpu的个数 比如-smp 2
  • -m: 指定内存大小单位MB
  • -vga :指定显卡 比如 -vga vmware
  • -hda: 指定硬盘镜像
  • -initrd: 指定 RAM磁盘镜像
  • -fda : 指定软盘镜像
  • -L:bios位置
  • -cdrom:光盘镜像
  • -no-reboot: 不重启退出
  • -kernel :指定内核文件
  • -serial :设置串口 比如:-serial stdio 表示 重定向Guest 的串口到Host的标准输入输出
  • -boot :启动模式 一共有三种 , 分别为floppy(a), hard disk(c), CD-ROM(d)

上面这条指令显然无法启动系统,因为还缺少了相应kernel-qemu文件和配置:

kernel-qemu下载:

GitHub - dhruvvyas90/qemu-rpi-kernel: Qemu kernel for emulating Rpi on QEMU

我们选择里面的versatile-pb-buster.dtb 和kernel-qemu-5.4.51-buster 这两个文件进行下载,这是和系统版本一一对应的。下载后最好放在qemu的安装目录

然后输入以下指令:

1
qemu-system-arm -M versatilepb -cpu arm1176 -m 256 -drive "file=系统镜像路径,if=none,index=0,media=disk,format=raw,id=disk0" -device "virtio-blk-pci,drive=disk0,disable-modern=on,disable-legacy=off" -net "user,hostfwd=tcp::5022-:22" -dtb versatile-pb-buster.dtb -kernel kernel-qemu-5.4.51-buster -append "root=/dev/vda2 panic=1" -no-reboot -net nic

注意:需要按照以上指令运行,否则有可能出现系统启动不起来的情况

-net nic 可开启网络 方便远程连接

-net "user,hostfwd=tcp::5022-:22" 表示设置端口映射

系统安装完毕后,直接进入树莓派桌面,在弹出的设置窗口中可以更改系统语言为中文, 还可以设置系统密码

至此ARM+Linux环境搭建完毕

准备开发

接下来我们通过ssh连接树莓派终端,打开cmd命令窗口,输入:

1
ssh pi@127.0.0.1 -p 5022

回车后会提示输入密码,这里输入之前设置的系统密码

此时就进入树莓派的Linux终端,为什么不直接使用qemu中的LX终端? 还不是因为模拟器延迟卡顿

如果想往树莓派中传输文件,可以直接使用ftp工具,比如FileZilla或者 SecureCRT 选择sftp或者ssh2模式,其登陆参数如下:

  • 主机:127.0.0.1
  • 用户名:pi
  • 端口:5022,
  • 密码同上

程序调试

紧接着使用gdb+gdbserver对C程序进行调试

首先利用ftp工具将已经编译好的可执行文件和GCC包下arm-none-linux-gnueabi\libc\usr\bin目录中的gdbserver传送到模拟器中

然后执行以下命令:

1
./gdbserver :22349 test

开始监听端口, 但是问题来了,该模拟器的ip不在局域网段上,导致宿主机连接不上, 如果你也出现同样的问题,可以采用端口映射的办法来替代,方法很简单,只需要在模拟器启动时多追加加上一行参数hostfwd=tcp::22349-:22349,具体启动指令修改如下:

1
qemu-system-arm -M versatilepb -cpu arm1176 -m 256 -drive "file=2020-02-13-raspbian-buster.img,if=none,index=0,media=disk,format=raw,id=disk0" -device "virtio-blk-pci,drive=disk0,disable-modern=on,disable-legacy=off" -net "user,hostfwd=tcp::5022-:22,hostfwd=tcp::22349-:22349" -dtb versatile-pb-buster.dtb -kernel kernel-qemu-5.4.51-buster -append "root=/dev/vda2 panic=1" -no-reboot  -net nic

如此一来就可以在宿主gdb调试窗口中直接使用以下指令进行连接:

1
(gdb) target remote 127.0.0.1:22349

连接成功了,通过以上这种方式,我们只需要将模拟器启动使其后台运行,我们通过ssh进行登录连接,这样速度快了很多,而且相比一些安卓模拟器,QEMU占用系统资源也不高

另外我们发现,还存在声卡缺失,同时运行有延迟卡顿现象,我们接下来对这两方面进行优化

小问题

如果是raw格式,可能会有些风险警告,可以通过-drive format=raw进行指定处理:

1
qemu-system-arm.exe  -machine raspi2b -drive file=2020-02-13-raspbian-buster.img,format=raw,index=0,media=disk

附加内容

查看cpu信息:

1
lscpu

查看系统和内核版本:

1
uname -a

镜像备份模式

随着我们对系统的频繁操作我们发现系统镜像文件在不断增大,此时想要回到原来的状态,只能重新下载镜像安装了,如果你不想遭受重新下载的痛苦,那么建议你使用备份镜像的模式进行系统的安装

这时qemu-img.exe派上了用场,它不仅可以帮助你创建空镜像文件,而且还可以对已有的镜像文件进行格式转换,QEMU支持的镜像有以下:

Image format Argument for -f and -O options
VMDK (VMware) vmdk
QCOW2 (KVM, Xen) qcow2
VHD (Hyper-V) vpc
VHDX (Hyper-V) vhdx
RAW raw
VDI (VirtualBox) vdi

qemu-img 支持非常多种的文件格式,可以通过 qemu-img -h 查看.
其中 raw 和 qcow2 是比较常用的两种,

raw 是 qemu-img 命令默认的,qcow2 是 qemu 目前推荐的镜像格式,是功能最多的格式

创建空镜像文件:

1
qemu-img create -f qcow2 test.qcow2 10G
  • -f 选项用于指定镜像的格式,

  • qcow2 格式是 QEMU最常用的镜像格式,采用来写时复制技术来优化性能。

  • test.qcow2 是镜像文件的名字,

  • 10G是镜像文件最大值

镜像转换:

1
qemu-img.exe  convert -f raw system.img -O vmdk  system.vmdk

表示将原始格式的镜像文件转换成vmdk格式

使用备份镜像的方式启动镜像示例:

1
qemu-system-x86_64 -m 2048 -enable-kvm test.qcow2 -cdrom Centos-Desktop-x86_64-20-1.iso

附加镜像

  • openwrt:https://archive.openwrt.org/chaos_calmer/

  • Debian系统镜像:https://people.debian.org/~aurel32/qemu/

  • 谷歌安卓原生镜像:https://developers.google.cn/android/images

  • 树莓派x86镜像: https://www.raspberrypi.org/downloads/raspberry-pi-desktop/

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Clang编译C程序在安卓设备中执行

发表于 2021-02-01

由于Android NDK从r18开始就已经抛弃GCC,转而将Clang当作默认编译器,因此我们直接使用NDK工具包进行编译

实验环境

  • 安卓模拟器
  • android-ndk-r19c

实验步骤

第一步 源码编写

新建test.c文件

1
2
3
4
5
6
7
#include <stdio.h>  

int main()
{
printf("Hello world!\n");
return 0;
}

第二步 源码编译

在android-ndk-r19c目录下toolchains文件夹中的llvm文件夹即为clang编译工具包

在llvm的子目录bin下存放这针对各个架构的clang编译器,由于模拟器是ARM架构,这里我们使用armv7a-linux-androideabi23-clang

在命令窗口执行如下指令:

1
armv7a-linux-androideabi23-clang test.c -o test

由于clang已经指定了Android23版本的SDK,这里无需要像GCC那样指定-static编译

第三步 将编译后的可执行文件传至安卓设备

1
adb push test /data/

第四步 执行文件

直接在控制台输入文件名即可执行

1
./test

如果提示权限拒绝,那么

1
chmod 777 test

附加

如果C语言和汇编语言混合开发,同样也可使用clang编译:

1
armv7a-linux-androideabi23-clang aaa.s test.c -o test

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

xcode中三种编译器的区别

发表于 2021-02-01

在xcode中有三种编译器供我们选择,分别是GCC、LLVM GCC、LLVM compliler

三者区别

  • GCC :是一套由 GNU 开发的编程语言编译器。Linux/Unix操作系统的标准编译器。编译前端和后端皆使用GCC
  • LLVM GCC:编译前端使用GCC,后端使用LLVM
  • LLVM compliler :编译前端使用Clang,后端使用LLVM

为什么存在三种编译器

苹果公司最开始使用GCC编译器

为了实现对 Objective-C 新特性的支持,苹果公司结合LLVM改进GCC,从而衍生出了一个GCC分支,也就是LLVM GCC

由于LLVM GCC的笨重和局限性,苹果公司从零开始开发了一套自己的编译前端系统Clang,配合LLVM,就有了LLVM GCC

Clang的优势

相比GCC而言:

  • 编译速度快,占用内存小
  • 模块化设计,易于扩展,易于IDE集成
  • 错误提示人性化
  • 产出小

值得一提的是,Android NDK从r18开始就已经抛弃GCC,转而采用Clang编译,Clang未来可期

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

原生ARM环境中使用的编译工具集介绍

发表于 2021-02-01

这里说原生ARM环境指的是由ARM公司官方提供的的ARM编译工具集,主要包括以下几个工具:

  • armclang: 用于编译 c ,c++, GNU assembly language的源代码,不能编译ARM汇编代码

  • armasm:汇编器, 只能编译 arm汇编代码

  • armlink: 链接器,用来将目标代码,链接成可执行程序

  • armar: 打包,将目标代码打包成一个库

  • fromelf: 将可执行程序,转换为其他的镜像文件。

    以下是编译流程

这个编译器,和ARM-GCC编译器最大的区别在于,这个工具是要收费的,而ARM-GCC是不用收费的。

ArmClang编译器的参数介绍

1、–target选项

必选项,指定使用哪一种ARM指令集进行编译。只有两个选项:

  • –target=aarch64-arm-none-eabi : 指定使用aarch64

  • –target=arm-arm-none-eabi : 指定使用aarch32

2、–mcpu选项

通过指定特定的处理器型号进行编译。当指定了target,可以不指定这个。

如:

1
–mcpu=cortex-a53   #表示 指定处理器是cortex-a53,

如果要查看指定target下支持的处理器型号,可使用–mcpu=list指令选项,如下:

1
armclang –target=aarch64-arm-none-eabi  –mcpu=list #查看 aarch64下支持的处理器

3、–march选项

指定编译时针对哪一个架构进行编译。

可以使用armclang –target= aarch64-arm-none-eabi -march=list 查看aarch64下支持的架构,可以看出对于aarch64,总共支持3种架构。

而aarch32下支持的架构就多了,从armv6-armv8。

4、-g选项

表示编译器编译的时候,加上调试信息

1
armclang –target=aarch64-arm-none-eabi -g test.c

5、-Olevel选项

优化等级,level越高,优化等级越高。

  • -O0表示没有优化。

  • -Os表示减小代码密度,平衡代码大小和代码速度。

  • -Omax表示针对该target,使用最大的优化。

6、-marm -mthumb选项

-marm表示A32指令集 , -mthumb表示T32指令集

7、-Wpedantic选项

显示警告信息

8、-S选项

将c代码,或者.S代码,预处理,生成.s代码。

9、-c选项

只编译不链接,生成中间目标代码(.o)

例子:

ArmAsm汇编器的参数介绍

1、-I选项

指定搜索目录

2、–cpu选项

指定的指令集

如 –cpu=8-A.64 , 指定armv8架构的64bit的指令集

3、-g选项

汇编,加上调试信息

4、–predefine选项

定义一个宏,传递给汇编代码中使用。

例子:

Armlink连接器参数介绍

链接器,用来链接各个.o文件,得到最终的elf。

1、–ro_base选项

指定RO段的起始地址

2、–rw_base选项

指定RW段的起始地址

3、–zi_base选项

指定bss段的起始地址

4、–map –symbols选项

显示生成镜像的memory map,以及symbols信息

5、–scatter选项

指定链接脚本

6、–output选项

指定生成的文件

7、诊断信息

诊断信息的选项:

8、不使用链接脚本

使用armlink链接init.o 和 main.o,生成可执行文件。

其中:

  • 代码段起始地址是0,

  • 数据段起始地址是0x400000,

  • bss段的起始地址是0x405000。

init.o的init段,作为生成可执行文件的最开始段。

9、使用链接脚本

以下是使用链接脚本来进行链接。

下图中,链接脚本的格式。

外面指定LR1,是一个大段,从地址0x0000-0x2000。在这个RL1段,包括3个小段

  • ER_RO: 只读段,从0地址开始。其中init.o的INIT段作为这个段的开始,其他段放置在这个段的后面
  • ER_RW: 可读可写段,从0x400000开始
  • ER_ZI: bss段,从0x405000开始

10、#pragma pack(n)

#pragma用来指定打包数据时,各个数据的空间占据。

!

对于char型,占用1个字节, 对于short型,占用2个字节, 对于int型,占用4个字节。

fromelf工具介绍

反汇编工具。

1
fromelf  –text  –c  –a  elf文件  -o  文本文件

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用NDK下的GCC工具编译c代码至android设备中运行

发表于 2021-01-31

之前我们学过使用GCC子集之一arm-none-linux-gnueabi进行C代码编译,这次我们学习GCC另外一个子集arm-linux-androideabi,这是专门为android平台打造的一个GCC编译环境,该工具被包含在Android NDK库当中

实验环境

  • windows宿主机
  • 安卓模拟器(ARM架构+linux系统 已Root)
  • android-ndk-r9b

实验开始

第一步 编写测试代码 文件名为test.c

1
2
3
4
5
6
#include <stdio.h>

int main(){
printf("hello pangshu");
return 0;
}

第二步 将测试代码编译成可执行文件

如果直接编译:

1
arm-none-linux-androideabi-gcc.exe test.c -o main

则报错,提示:

1
clude-fixed\stdio.h:50:23: fatal error: sys/cdefs.h: No such file or directory

这是因为缺少相应的依赖库导致的,在我们使用arm-none-linux-gnueabi时直接在命令行后面添加-static即可,但是使用arm-linux-androideabi则不行

这里需要通过--sysroot指定依赖的库,指令改成如下:

1
arm-none-linux-androideabi-gcc.exe --sysroot=E:\android-ndk-r9b\platforms\android-19\arch-arm test.c -o main

此时编译通过,但是将生成的执行文件push到安卓设备上之后,却无法运行,提示:

1
error: only position independent executables (PIE) are supported.

因此我们需要借助-pie -fPIE将编译选项设置为PIE,指令最后改成如下:

1
arm-none-linux-androideabi-gcc.exe  -pie -fPIE --sysroot=E:\android-ndk-r9b\platforms\android-19\arch-arm test.c -o main

此时程序可正常执行

使用arm-linux-androideabi生成的可执行文件大小为6kB

使用arm-none-linux-gnueabi生成的可执行文件约为620KB

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

X86的安卓手机为什么可以运行ARM应用程序

发表于 2021-01-31

起因

从事android开发的小伙伴都知道,在我们进行so库适配的时候,只需要保留armabi这个库,就可以匹配市面上几乎所有的机型

但同时我们也知道,不同架构cpu只能执行与其对应架构编译出来的程序,也就是说x86设备只能执行x86程序,而不能执行ARM程序

那为什么x86的安卓设备却可以执行armabi的so库呢?

解答

我们知道从最一开始基于ARM的程序占据了几乎所有的Android生态环境。Inter为了顺利打入移动市场,一个至关重要的问题就是需要兼容ARM应用程序。

但是不同架构cpu对应的指令集不一致,为了解决这个问题,就需要一个中间翻译器,于是Inter开发了软件Houdini。Houdini可以把ARM指令集转化为X86指令集从而在Android X86设备上运行

同时由于市面上mips架构的安卓设备非常少,这也就是为什么只需一个armabi就可以通吃几乎所有设备,不过x86设备运行ARM程序虽然没什么问题,但是执行效率的损伤是必然的

附加

在adb shell模式下, 可以通过一下命令查看当前安卓设备支持的指令架构:

1
getprop

如果是x86的cpu,既可以运行x86的可执行文件,也可执行ARM架构的程序,具体的参考prop中对应的abi

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

GDB与GDBServer配合实现在安卓设备中进行程序调试

发表于 2021-01-30

实验环境

  • windows开发平台

  • 安卓模拟器(ARM架构+linux系统 已Root):

    可以通过adb shell getprop指令查看当前设备的cpu架构

  • arm-linux-androideabi编译工具 gdb和gdbserver皆存放在此开发包下

实验开始

第一步 编写测试代码 文件名为test.c

1
2
3
4
5
6
7
#include <stdio.h>

int main(){
char *a="he"
printf("hello pangshu");
return 0;
}

第二步 将测试代码编译成可执行文件

1
arm-linux-androideabi-gcc.exe -g test.c -o main -static #输出可执行文件名为main

第三步 将可执行文件传送到模拟器中

1
adb push main /data/local/tmp

第四步 将gdbserver工具传送到模拟器中

1
adb push gdbserver /data/local/tmp

第五步 进入模拟器shell窗口,使用gdbserver执行程序

1
./gdbserver 192.168.177.71:23946 main #这里的ip是宿主机的ip  23946为监听端口

第六步 在宿主机中运行gdb工具

1
gdb.exe main  #这里需要指定调试的执行文件

此时进入到gdb模式

第七步 在gdb模式下连接模拟器中的gdbserver

1
(gdb) target remote 192.168.0.1:23946  #这里的ip是模拟器的ip

连接成功后进入断点调试模式,该模式下可以使用~调试指令进行相关调试

开始调试

  1. 使用list指令列出所有源代码 可简写为l

    1
    (gdb) l
  2. 使用break指令设置断点位置 可简写为b

    1
    (gdb) b main #在main函数处打断点
  3. 使用continue指令运行到断点处 可简写为c

    1
    (gdb) c
  4. 使用step指令进行单步执行 可简写为s

    1
    (gdb) s   #会进入函数内部
  5. 使用next执行进行单步执行 可简写为n

    1
    (gdb) n  #不会进入函数内部
  6. 使用print指令打印变量的值 可简写为a

    1
    (gdb) p a #打印变量a的值
  7. 使用quit指令退出调试模式 可简写为q

    1
    (gdb) q

更多调试指令

GCC调试工具GDB的常用指令

关于arm-linux-androideabi的获取

建议下载Android NDK开发包,然后将里面的GCC套件单独抽出来使用,NDK提供了抽包脚本make-standalone-toolchain,在bulid目录的tools文件夹中可以找到,执行脚本自动抽取打包成压缩包到当前目录:

1
python make-standalone-toolchain.py --arch arm

附加

如果是在非安卓系统的ARM模拟器上,比如qemu模拟器,那么直接使用官方的arm-none-linux-eabi即可,即便是安卓设备,如果没有代码调试需求的话,仅仅是编译运行程序,也是完全够用了

但是你需要进行代码调试的话,由于android系统的安全策略,arm-none-linux-eabi包中的gdbserver无法运行,提示:

1
error: only position independent executables (PIE) are supported.

为了解决这个问题,我们因此采用arm-linux-androideabi,这里面的gdbserver可以正常运行

上面的例子中使用的NDKr17的版本

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Makefile的详细介绍和使用

发表于 2021-01-29

待完善。。。

makefile详细介绍和使用

Makefile定义规则

参考链接1:https://seisman.github.io/how-to-write-makefile/invoke.html

参考链接2:https://www.cnblogs.com/LittleHann/p/3855905.html

规则是makefile中最重要的概念,其告诉make 目标文件的依赖关系,以及如何生成及更新这些目标文件。在makefile文件规则有2种,一种是显式规则,另一种是隐式规则。

  1. 显示规则

显式规则用于说明何时及如何重新生成目标,其列出了目标依赖的文件信息,并通过调用命令来创建或更新目标,其语法一般为:

1
2
3
4
targets : prerequisites

recipe
…
  • targets:为要生成或更新的目标

  • prerequisites:为目标依赖的关系

  • recipe:为生成目标的命令,

    一个规则可以有多条recipe,比如

    1
    2
    3
    foo.o : foo.c defs.h

    cc -c -g foo.c

其中foo.o为target,foo.c defs.h 为prerequisites,cc -c -g foo.c为recipe。

示例讲解

1
2
3
4
5
6
7
8
9
10
test:main.o channle.o
gcc main.o channle.o -o test
main.o:main.c function.h
gcc -c main.c -o main.o
channle.o:channle.c WavHead.h
gcc -c channle.c -o channle.o -std=c99

.PHONY:clean
clean:
-rm -rf *.o

执行的过程简单说就是最终需要生成一个名为test的文件,这个文件需要main.o和channle.o,于是继续往下执行,然后通过命令gcc -c main.c -o main.o得到了main.o文件,同理再得到channle.o文件,最后通过命令gcc main.o channle.o -o test进行链接最终就会得到一个名为test的可执行文件了。

上面的代码在linux的命令窗口下输入make命令就可以执行了,最终会生成一个test的可执行文件。 如果需要清除生成的中间.o文件,输入make clean就可以全部清除了。

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

GCC工具的具体使用

发表于 2021-01-29

编译工具链

高级语言翻译成机器语言不是一步到位的,以C语言为例,通常要经历以下四个步骤:

1
2
3
预处理--->编译--->汇编--->连接

源代码--->汇编代码--->目标代码--->可执行程序

每一步都需要使用不同的工具,比如源代码需要借助编译工具翻译成汇编代码,汇编代码需要借助汇编器翻译成目标代码,最后还要借助连接器帮忙整理汇总, 那么这些个工具集合到一块就叫做工具链

GCC工具链

由GNU提供的一整套的工具集,这套工具集中包含了汇编器,编译器和链接器,二进制转换,调试工具等

通过GCC,我们可以一步完成源码到可执行文件的编译, 也可以单步独立进行,方便程序员获取中间代码代码,进行调试

GCC常用命令选项

假设只编译单个源文件test.c

  1. 无选项编译

    1
    2
    3
    gcc test.c  
    或者
    gcc test.o

    在当前目录下直接生成可执行文件,默认名称为a.out

  2. 选项-o

    1
    gcc test.c  -o test

    在当前目录下生成名为test的可执行文件

  3. 选项-E

    1
    gcc -E test.c  -o test.i

    在当前目录下生成名为test.i的预处理文件

  4. 选项-S

    1
    gcc -S test.c  -o test.s

    在当前目录下生成名为test.s的汇编文件,将源码转成汇编代码

  5. 选项-c

    1
    gcc -c test.c

    在当前目录下生成名为test.o的目标文件

  6. 选项-O数字

    1
    gcc -O1 test.c  -o test

    在当前目录下生成名为test的可执行文件,并且使用编译优化级别1编译程序。可选级别为1~3,级别越大优化效果越好,但编译时间越长。

多文件编译

比如一个汇编文件aaa.s一个C源文件test.c:

  1. 方式一 多文件同时编译

    直接追加文件名进行同时编译输出即可

    1
    gcc aaa.s test.c -o bbb

    如果要编译的文件都在同一个目录下,可以用通配符gcc *.c -o 来进行编译

  2. 方式二 多文件分开编译

    首先将源文件编译成目标文件

    1
    2
    3
    gcc -c aaa.s  //生成aaa.o

    gcc -c test.c //生成test.o

    然后将所有目标文件连接成可执行文件

    1
    gcc  test.o aaa.o -o test
  3. 方式三 编写makefile文件进行编译

    第一步 makefile文件编写

    1
    2
    3
    4
    # 我是注释
    SRC=aaa.s test.c
    main: $(OBJS) #指定需要生成的文件名称以及相应的依赖关系
    gcc -o main $(SRC) #生成所需要的指令

    第二步 使用bin包下的cs-make工具,直接在命令窗口中执行该指令,默认在当前目录虚招makefile文件

    1
    # cs-make

    该指令实际上执行的就是makefile中我们编写的指令gcc -o main aaa.s test.c

以上三种方法相比较,第一中方法编译时需要所有文件重新编译,而第二种方法可以只重新编译修改的文件,未修改的文件不用重新编译 ,第三种方法适用于文件较多依赖关系复杂的工程编译

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

汇编语言之行x86_32汇编

发表于 2021-01-28

两大汇编语法

两种语法主要是针对x86架构汇编而言,对于其他架构没有这么一个说法

  • Intel型语法: Intel官方语法,在Windows平台原生环境中采用该语法
  • AT&T型 :非Intel官方语法,在Unix/Linux的GCC编译环境中采用该语法

原生环境搭建

  • windows系统
  • RedAsm集成工具

指令和语法

在让我们看看 x86_64 平台提供了哪些寄存器给我们使用,

  • 16个通用寄存器,例如,rax,rbx,rcx,rdx等
  • 6个16位段寄存器,例如:cs,ds,等

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

1…262728…50

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

491 日志
143 标签
RSS
© 2025 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%