AT&T 汇编

2023-05-16

1. 基础

  • x86 的寄存器为32位,x64 的寄存器为64位。寄存器间对应关系:

    64位寄存器	低32位	低16位	低8位
    rax			eax		ax		al
    rbx			ebx		bx		bl
    rcx			ecx		cx		cl
    rdx			edx		dx		dl
    rsi			esi		si		sil
    rdi			edi		di		dil
    rbp			ebp		bp		bpl
    rsp			esp		sp		spl
    r8			r8d		r8w		r8b
    r9			r9d		r9w		r9b
    r10			r10d	r10w	r10b
    r11			r11d	r11w	r11b
    r12			r12d	r12w	r12b
    r13			r13d	r13w	r13b
    r14			r14d	r14w	r14b
    r15			r15d	r15w	r15b
    
  • 在引用寄存器时,需要加上 % 前缀,如,%rax

  • 立即数以 $ 作为前缀,如,$0x1

  • 源操作数在前,目的操作数在后。

  • 指令后缀

    后缀		大小(字节)
    b		1
    w		2
    l		4
    q		8
    

    如,

    movl $0x4, %eax	# %eax = $0x4
    

2. 寻址

  • 通用寻址格式:偏移量(%基址寄存器, %索引寄存器, 比例因子);比例因子为1、2、4、8。
  • 有些项是可以被省略的,比例因子默认为1。
  • 最终地址为:偏移量 + %基址寄存器 + %索引寄存器 x 比例因子。
0x8(%edx)
(%edx, %ecx)
(%edx, %ecx, 4)
0x80(, %ecx, 4)

3. 过程调用

x86-32

寄存器使用惯例

  • 调用者负责保存和恢复的寄存器:%eax, %edx, %ecx
  • 被调用者负责保存和恢复的寄存器:%ebx, %esi, %edi
  • %eax 保存返回值。

栈帧

  • %esp 指向栈顶(低地址),%ebp 指向栈帧(高地址),%ebp ~ %esp 之间的区域就是栈帧。
  • 栈帧保存的内容(从 %ebp%esp):
    • 【此处是父过程的栈帧,与当前栈帧相关的内容包括:当前过程的输入参数(从右往左压入栈)、返回地址】 ;
    • 父过程的栈帧起始地址(旧的 %ebp);
    • 被保存的寄存器值;
    • 当前过程所用到的局部变量;
# set up
pushl %ebp		# 旧的 %ebp
movl %esp, %ebp	# 新的 %ebp
pushl %ebx		# 保存用到的寄存器

movl 12(%ebp), %ecx	# 第二个参数
movl 8(%ebp), %ecx	# 第一个参数

 ...

# finish
movl -4(%ebp), %ebx	# 恢复用到的寄存器
movl %ebp, %esp
popl %ebp
ret

x86-64

寄存器使用惯例

  • 被调用者负责保存和恢复的寄存器:%rbx, %rbp, %r10, %r12, %r13, %r14, %r15
  • 前六个参数依次位于 %rdi, %rsi, %rdx, %rcx, %r8, %r9 寄存器中,这些寄存器由调用者负责保存和恢复;如果参数大于六个,则余下参数还是从右往左压入栈;
  • %rax 保存返回值。

栈帧

完全基于 %rsp 完成。

# 保存用到的寄存器
movq %rbx, -16(%rsp)
movq %r12, -8(%rsp)

# 分配栈帧
subq $16, %rsp

 ...

# 恢复用到的寄存器
movq (%rsp), %rbx
movq 8(%rsp), %r12

# 释放栈帧
addq $16, %rsp

4. 系统调用

  • 通过执行中断 int $0x80 来实现。
  • 系统调用号保存在 %eax 中。
  • 系统调用参数按序放到 %ebx, %ecx, %edx, %esi, %edi 中。
  • 如果参数个数大于 5 个,则所有参数放到一个连续的内存区域中,然后将指向该区域的指针放到 %ebx 中。
  • 系统调用返回值放在 %eax 中。

5. 静态链接

  • 每个源文件都有自己的代码段和数据段,在程序链接期间,链接器会将多个文件的代码段和数据段集成为单一的代码段和数据段,如此之后,程序便有了一个统一的内存布局。
  • 接着将 .o 文件中的符号解析为地址,并将所有的符号引用更新为地址。
  • 静态链接库:由多个源文件生成多个 .o 对象文件,然后将这些对象文件打包归档成一个 .a 文件;在静态链接期间,如果 .a 文件中的某个成员能够匹配一个外部符号,则将该成员链接入可执行文件中。

6. Hello, World!

.data
msg:
	.string "Hello, World!\n"
	len = .-msg
	
.text
.global _start
_start:
	movl	$4, %eax	# 系统调用号,write 为 4
	movl	$1, %ebx	# fd = 1,表示 stdout
	movl	$msg, %ecx	# buf = $msg
	movl	$len, %edx	# count = $len
	int	$0x80

	movl	$1, %eax
	movl	$0, %ebx
	int	$0x80

64 位汇编:

$ as -o helloworld.o helloworld.s
$ ld -o helloworld helloworld.o
$ ./helloworld 
Hello, World!

64 位环境下生成 32 位汇编:

$ as --32 -o helloworld.o helloworld.s
$ ld -m elf_i386 -o helloworld helloworld.o
$ ./helloworld 
Hello, World!

7. 命令行参数

输出命令行参数:

.text
.global _start
_start:
	popl	%ecx	# argc
next_arg:
	popl	%ecx	# argv[i]
	test	%ecx, %ecx	# argv[i] == NULL
	jz	exit
	movl	%ecx, %ebx
	xorl	%edx, %edx	# strlen(argv[i])
strlen:
	movb	(%ebx), %al
	inc	%edx
	inc	%ebx
	test	%al, %al
	jnz	strlen
	movb	$10, -1(%ebx)	# ascii('\n') == 10

	movl	$4, %eax
	movl	$1, %ebx
	int	$0x80
	jmp	next_arg

exit:
	movl	$1, %eax
	xorl	%ebx, %ebx
	int	$0x80
$ ./arg hello world
./arg
hello
world

8. C程序 -> 汇编代码

64 位汇编:

$ gcc -S -O2 hello.c

64 位环境下生成 32 位汇编:

$ sudo apt install g++-multilib
$ gcc -S -O2 -m32 hello.c

9. 反汇编

反汇编对象文件:

$ gcc -c main.c -o main.o -m32 -g

# -D: Display assembler contents of all sections
# -S: Intermix source code with disassembly
# -r: Display the relocation entries in the file
$ objdump -DSr main.o

反汇编可执行文件:

$ gcc -o main main.c -g
$ objdump -DS main

10. 汇编指示

  • .text:代码段。

  • .data:带有初始值的数据段;声明一个数据元素时,需要指明数据类型及初始值;因为它具有初始值,所以它在可执行文件中实实在在具有指定大小的空间来保存这些值。

  • .bss:不带有初始值的数据段;声明一个数据元素时,不需要指明数据类型及初始值,只需声明保留一段内存即可;因为它不具有初始值,所以它在可执行文件中并没有分配指定大小的空间,而是在程序运行时才分配声明的内存。

  • .rodata:只读数据段。

  • .section:把代码划分为若干个区,当程序被加载进内存时,不同的区会被加载到不同的地方,且不同的区具有不同的读、写、执行权限;例如,.section .data.section .text

  • .p2align 4:按 2 的 4 次方,即 16 字节对齐。

  • .align 4:按 4 字节对齐。

  • .string "hello, world!":定义一个字符串,内容为 “hello, world!”。

  • .long 10:定义一个 long 类型的数据,值为 10。

  • .comm buffer, 1000:声明一个大小为 1000 字节的内存区域,并把区域的起始地址付给 buffer;该内存区域是未初始化的、全局可见的。

  • .lcomm buffer, 1000:声明一个大小为 1000 字节的内存区域,并把区域的起始地址付给 buffer;该内存区域是未初始化的、只局部可见的。

  • 符号:表示数据(变量)或指令(函数)的地址,后跟 :

  • .global main:表示 main 符号是全局可见的(同一程序的其他模块可访问),如果没有 .global 修饰,则该符号不是全局可见的。

  • .:表示当前地址。

  • .equ SYS_OPEN, 5:定义一个符号常量 SYS_OPEN,其值为 5。

  • .include "record.s":包含 record.s 文件至当前文件。

  • .rept n xxx .endr:重复 n 次 xxx。

    # 重复 31 次 .byte 0 
    # 用作数据填充
    .rept 31
    .byte 0
    .endr
    

11. gcc 内联汇编

基本格式:

asm [volatile] (
	assembler template 
  	: [output operands]
  	: [input operands]
  	: [list of clobbered registers]
)
  • volatile 告诉 gcc 不要优化掉这些汇编代码。

  • 每条汇编指令需要放在 "assembler template" 中,且需要以 \n 结尾。

  • 在汇编代码中,如果使用到寄存器,则需要使用两个 %,如,%%eax

  • 操作数约束:在输出、输入操作数中,可以通过操作数约束来限制操作数应该放在哪个寄存器或直接使用内存:"约束"(变量)

    +---+--------------------+
    | r |    Register(s)     |
    +---+--------------------+
    | a |   %eax, %ax, %al   |
    | b |   %ebx, %bx, %bl   |
    | c |   %ecx, %cx, %cl   |
    | d |   %edx, %dx, %dl   |
    | S |   %esi, %si        |
    | D |   %edi, %di        |
    | r |   任何一个通用寄存器  |
    | m |   使用内存          |
    +---+--------------------+
    
  • 修饰符 =, +, & 只能用于输出部分;= 表示当前输出表达式的属性为只写,+ 表示当前输出表达式的属性为可读可写,& 告诉 gcc 不得为任何输入操作表达式分配与此输出操作表达式相同的寄存器。

  • 数字占位符:在汇编代码中,可以使用 %0, %1, ... 来依次引用输出、输入中的寄存器。

    #include <stdio.h>
    
    int main() {
            int a = 1;
            int b = 2;
            int c;
    
            asm volatile (
                    "addl %1, %2\n"
                    "movl %2, %0\n"
                    : "=a"(c)				// 变量 c 放在寄存器 eax(%0) 中
                    : "b"(a), "c"(b)		// 变量 a, b 分别放在 eax(%1) 和 ebx(%2) 中
                    :
            );
    
            printf("c = %d\n", c);
    
            return 0;
    }
    
  • 名称占位符:此时表达式的格式为 [name] "约束"(变量),在汇编代码中可以使用 %[name] 来引用该操作数。

    int main() {
            int a = 1;
            int b = 2;
            int c;
    
            asm volatile (
                    "addl %[a], %[b]\n"
                    "movl %[b], %[c]\n"
                    : [c] "=a"(c)
                    : [a] "b"(a), [b] "c"(b)
                    :
            );
    
            printf("c = %d\n", c);
    
            return 0;
    }
    
  • clobbered registers 列表告诉 gcc 我们会使用和修改这些寄存器(不包括输入、输出寄存器),如,"eax, ecx";另外,如果汇编代码修改了内存,则还需要加上 memory 约束。

    #include <stdio.h>
    
    void my_memset(void* buf, char c, size_t count) {
            asm volatile (
                    "cld\n"
                    "rep stosb\n"
                    :
                    : "a"(c), "D"(buf), "c"(count)
                    : "memory"
            );
    }
    
    int main() {
            char buf[8];
            my_memset(buf, 'a', sizeof(buf));
    
            for (int i = 0; i < sizeof(buf); i++) {
                    printf("%c", buf[i]);
            }
            printf("\n");
    
            return 0;
    }
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AT&T 汇编 的相关文章

  • nohub 和 & 在linux上不间断后台运行程序

    1 nohub xff08 没安装的要先安装 xff09 用途 xff1a 不挂断地运行命令 语法 xff1a nohup Command Arg amp 无论是否将 nohup 命令的输出重定向到终端 xff0c 输出都将附加到当前目录的
  • AT&T语法

    在linux内核编写中 为了维持与gcc输出汇编程序的兼容性 as汇编器使用AT amp T系统的V的汇编语法 下面简称为AT amp T语法 这种语法与Intel汇编程序使用的语法 简称Intel语法 很不一样 他们之间的主要区别有以下几
  • Maven Helper插件下载&Maven导入jar包(依赖管理)

    1 maven Helper插件 1 1搜索 File gt Settings gt Plugins gt 搜索Maven Helper 发现没有 1 2 安装 点击Browse reositories gt 选择maven Helper
  • ESP实验02-读取DS1307&eerom34c32

    1 模块介绍 本实验主要用到两个模块 esp32 tinyRTC 模块的图片如下所示 xff1a esp32模块型号为ESP32Devkitc v4 xff0c 是启明云端官方的开发板 与乐鑫官方的完全一致 xff0c 引脚顺序 xff0c
  • VFH & VFH+ & VFH*—— Path Planning

    版权声明 xff1a 本文为博主原创博文 xff0c 未经允许不得转载 xff0c 若要转载 xff0c 请说明出处并给出博文链接 最近在学习VFH算法 xff0c 感觉蛮神奇 xff0c 特意从维基百科扒来了资料 xff0c 供学习研究
  • LLVM/clang & lib路径 & 测试代码

    部分转载自 xff1a Ubuntu编译安装llvm clangUbuntu14 04 Linux安装LLVM clang 3 7 xff08 带有标准库 libc 43 43 xff0c libc 43 43 abi xff09 所需即所
  • 【CCF推荐专区】计算机类优质SCI&EI好刊,期刊质量高,部分期刊仅有少量版面

    x1f308 智能传感类 xff08 TOP xff09 CCF C类 期刊简介 IF 7 0 8 0 xff0c JCR1区 xff0c 中科院2 1区 检索情况 SCI amp EI 双检 xff0c 正刊 xff0c CCF C类 征
  • AUTOSAR E2E & SecOC Comparison

    AUTOSAR E2E amp SecOC Comparison 前面已经介绍过了E2E 和 SecOC CMAC 了 xff0c 既然2者都可以进行数据完整性保护 xff0c 那么2者有什么区别呢 下面基于我的经验所总结 欢迎补充 xff
  • ORB-SLAM3测试:数据集(单目/双目/imu)& ROS (D435 T265)

    ORB SLAM3环境配置 安装各种依赖库 orb slam3非常友好 xff0c 不用自己下载各种依赖库 xff0c 因为他们全部在thirdParty文件夹中 xff0c 编译orb slam3的同时会自动编译各种依赖库 Eigen3
  • Liunx下源代码安装&&make&&makefile

    Linux下安装软件的方式分为源代码安装和二进制安装 源代码安装 xff0c 即使用应用程序源代码进行编译安装二进制安装 xff0c 例如red hat发行的 rpm包 debian发行的 deb包 源代码安装 用c语言为例 include
  • Linux下rpm&yum&apt-get

    RPM简介 RPM命名 RedHat Package Manager xff0c 简称则为RPM 属于Red Hat阵营的 xff0c 与其并列的则是debian centos中大部分我们安装都是使用yum install xff0c 而d
  • 【浅墨著作】《逐梦旅程:Windows游戏编程之从零开始》勘误&配套源代码下载...

    I 39 m back 恩 xff0c 几个月不见 xff0c 大家还好吗 xff1f 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧 woxiangnifrr童鞋说每天都在来浅墨的博客逛一下看有没有更新 xff0c
  • 2013&2014

    2013总结 2013 毕业了 xff0c 算是正式工作半年 xff0c 2013年7月开始 xff0c 算是我的生活 xff0c 工作之外的时间都是自己的 一 收获 1 压力测试 差不多算是一个月的时间 xff0c 疯狂的一个月 xff0
  • PX4模块设计之一:SITL & HITL模拟框架

    PX4模块设计之一 xff1a SITL amp HITL模拟框架 1 模拟框架1 1 SITL模拟框架1 2 HITL模拟框架 2 模拟器类型3 MAVLink API4 总结 基于PX4开源软件框架简明简介的框架设计 xff0c 逐步分
  • C++编程(五)--- Cmake详解&Makefile详解

    C C 43 43 程序员肯定离不开Makefile和Cmake xff0c 因为如果对这两个工具不熟悉 xff0c 那么你就不是一个合格的C C 43 43 程序员 本文对Makefile和Cmake xff0c 及它们的使用进行了详细的
  • 对‘cv Mat Mat()’未定义的引用‘cv imread(cv String const&, int)’未定义的引用 ...的解决办法

    对 cv Mat Mat 未定义的引用 cv imread cv String const amp int 未定义的引用 的解决办法 视觉SLAM十四讲的ch5的部分代码 xff0c 运行时出现了大面积的报错 xff0c 说相应的函数没有定
  • STM32&nbsp;HAL库&nbsp;STM3…

    原文地址 xff1a STM32 HAL库 STM32CUBEMX KEIL TIM1 PWM 四路输出可调 一 作者 xff1a 用户2797410335 硬件 xff1a TM32F407VET6 8M晶振 xff0c JLINK JT
  • ROS速成之发送&接收消息

    人真的老了 xff0c 扔了个周末 xff0c 完全不记得干了什么 论纪录的重要性啊 xff0c 当时觉得明白的很 xff0c 你扔两天试试 xff1f 扔一年试试 xff1f 扔几年试试 xff1f 最近参加的各种项目脑疼眼乏 xff0c
  • Docker数据卷&&自定义Docker镜像

    目录 宿主机与容器之间的文件拷贝 引言 xff1a 利用MySQL镜像安装MySQL服务 从容器中拷贝文件到宿主机 从宿主机拷贝文件到容器 数据卷 数据卷容器 Dockerfile自定义镜像 自定义tomcat8 xff08 熟悉几乎所有的
  • linux中断&poll&selcet按键处理机制

    在上一篇linux按键中断处理中 xff0c 我们采用按键中断处理获取按键 xff0c 在read函数中阻塞读取 xff0c 当按键发生时 xff0c read自动解除阻塞 xff0c 实现应用层读取到相应的按键值 在上一节中如果没有按键到

随机推荐

  • 浅析鹅鸭杀中服务端的技术实现和要点

    在朋友的介绍下 xff0c 我下载了这款游戏 由于之前玩过 Among Us xff0c 我本以为这款游戏不会达到正宗的太空狼人杀的水平 xff08 毕竟是免费的 xff09 但实际游玩后 xff0c 我被它更加丰富的设定和玩法所吸引 接下
  • nginx代理静态网站css解析异常

    今天在使用ecs进行部署网页时 xff0c 出现了一个问题 使用nginx代理到页面index html路径下 xff0c 同路径的资源都可以加载到 xff0c 但是却无法正确加载到页面样式 打开f12 xff0c 网络和控制台都没有资源异
  • 为什么mysql的delete操作不释放磁盘空间

    在 InnoDB 中 xff0c delete 操作并不会真的删除数据 xff0c mysql 实际上只是给要删除的数据打了标记 xff0c 标记为删除 磁盘所占空间不会变小 xff0c 即表空间并没有真正被释放 一 MySQL 删除数据几
  • docker start :FAIL Hypervisor framework fails

    mac 上启动 Docker 提示 FAIL Hypervisor framework fails 提示环境变量出错 我这台 mac 是自己攒的生产力 xff0c 由于软件是直接从旧的 mac 上迁移过来的 xff0c 我怀疑可能是系统版本
  • 在google设置静态页面 CDN加速

    一 创建bucket xff0c 设置bucket 链接 xff1a https console cloud google com storage browser 创建bucket 设置bucket公开访问 在bucket列表中 xff0c
  • Google Cloud Storage CORS跨域允许,忽略访问控制来源标头

    google storage origin https xxx com has been blocked by CORS policy No Access Control Allow Origin header is present on
  • 聊天记录存储实践

    公司的某款游戏在1月初接入微软小冰AI聊天功能 为了保存聊天记录并为后续的统计功能做好准备 xff0c 决定将聊天记录存放在服务端 最初并不清楚聊天数据量的大小以及玩家对聊天功能的使用情况 xff0c 所以采用了价格和性能相对宽容的MySQ
  • 将本地服务通过ssh代理给外部访问(如何使用 ssh 将本地服务代理给外部访问并保持 SSH 会话的连接性)

    如何使用 ssh 将本地服务代理给外部访问并保持 SSH 会话的连接性 1 外部服务器 nginx 配置 server span class token punctuation span listen localhost 80 span c
  • Go 单元测试高效实践

    敏捷开发中有一个广为人知的开发方法就是 XP xff08 极限编程 xff09 xff0c XP 提倡测试先行 xff0c 为了将以后出现 bug 的几率降到最低 xff0c 这一点与近些年流行的 TDD xff08 测试驱动开发 xff0
  • 操作系统—分段与分页

    1 地址重定位 所谓的地址重定位 xff08 也叫地址翻译 xff09 就是修改程序中的内存地址 xff0c 使得程序被载入内存后 xff0c 那些地址能够指向正确的内存空间 例如 xff0c 程序中包含 call 40 语句 xff0c
  • putty连接被拒的原因分析

    1 xff1a 检查防火墙 2 xff1a PING虚拟机 3 xff1a SSHD etc init d sshd start开启服务 4 xff1a IP字段问题 ifconfig eth0 新IP xff08 更改为字段和主机一样的I
  • Charles+Postern抓包遇到的问题(已解决)

    问题描述 Charles的代理配置和Postern的代理配置的都是正确的 xff0c 但是当在手机上打开Postern中的开启VPN时 xff0c Charles上没有任何反应 解决方法 xff1a 我在多次配置实验无果的情况下 xff08
  • 4. ROS编程入门--PID控制器

    介绍 xff1a 这篇教程是交给大家怎么在ROS里写一个PID控制器 xff0c PID控制器有三部分 比例部分 xff08 P xff09 积分部分 xff08 I xff09 微分部分 xff08 D xff09 PID的输出是这三部分
  • 6. ROS编程入门--路径跟随(Trajectory following)

    Task 本次实验才采用 Follow the carrot 算法去跟随定义好的路径 控制的目标点在机器人行走的路径上 xff0c 距离机器人是个常数距离 机器人计算自己的方向角和目标点角度之间的相差度数 控制这个差角为0 为了在探测时候能
  • 位姿矩阵求逆

    位姿矩阵求逆 位姿矩阵分析位姿矩阵求逆矩阵 为了更好的说明问题 xff0c 我们先来看一下位姿矩阵的定义 位姿矩阵分析 如下图所示 xff1a 如果在B坐标系下有一点PB xff0c 我们需要知道该点在坐标系A下的坐标PA xff0c 怎么
  • UNIX环境高级编程

    环境配置 1 下载apue 3e文件夹 xff0c 可以通过http www apuebook com code3e html现在源码 2 解压后执行进入apue 3e中执行make指令 如果出现 96 96 96 collect2 err
  • C#连接SQL Server 数据库

    C 是如何跟SQL Server进行连接的 xff1f 在C NET程序设计中 xff0c 离不开ADO NET ADO NET是 NET连接数据库的重要组件 使用其可以很方便地访问数据库 xff0c ADO NET还可以访问Oracle数
  • 冒烟测试和回归测试的区别

    每次新的版本出来的时候 xff0c 老大就让我们 冒烟 虽然不知道冒烟测试的含义 xff0c 但由于没有给用例 xff0c 我就随便跑跑 跑完冒烟后 xff0c 老大就让做 回归测试 xff0c 把bug回归掉 但是其实对2个概念还是不太理
  • Webpack——02——打包html资源

    1 在src中创建webpack的入口文件index js xff0c index html 2 src的同级目录下创建webpack config js 3 下载插件html webpack plugin 老规矩 初始化 xff0c 下w
  • AT&T 汇编

    1 基础 x86 的寄存器为32位 xff0c x64 的寄存器为64位 寄存器间对应关系 xff1a 64位寄存器 低32位 低16位 低8位 rax eax ax al rbx ebx bx bl rcx ecx cx cl rdx e