6.AT&T汇编

常见的寄存器

  • rax、rbx、rcx、rdx、rsi、rdi、rbp、rsp
  • r8、r9、r10、r11、r12、r13、r14、r15

寄存器的具体用途

  1. rax、rdx常作为函数返回值使用
  2. rdi、rsi、rdx、rcx、r8、r9等寄存器常用于存放函数参数
  3. rsp、rbp用于栈操作
  4. rip作为指令指针,存储着CPU下一条要执行的指令的地址,一旦CPU读取一条指令,rip会自动指向下一条指令(存储下一条指令的地址)

寄存器访问和使用

  1. 首先AT&T汇编有一个特点就是寄存器的访问和使用前面要加%,而立即数(就是具体的数字)访问要加$
  2. 拿寄存器rax来举例子,如果我遇到rax,我只想使用其中的一半(或者为了兼容32位的),常常会将rax取出来一半,然后叫eax,同样如果我还是再取出一半的一半使用,那我们就用ax,同理还有ah,al,都是为了拿出ax寄存器的一部分来使用

指令

  1. mov 指令
perl 复制代码
movl $123, %eax          # 立即数 → 寄存器
movl %eax, %ebx          # 寄存器 → 寄存器
movl (%eax), %ebx        # 内存 → 寄存器
movl %eax, (%ebx)        # 寄存器 → 内存
movl $123, (%eax)        # 立即数 → 内存

另外可以看到的mov后面的l是代表的什么意思呢?l代表操作的是32位的数据。 b是byte的意思,w是word就是双字节的意思,而l是long单词的缩写。而q是Quad缩写,意思是四个字。

bash 复制代码
movb    # 传送字节 (8位)
movw    # 传送字 (16位)
movl    # 传送双字 (32位)
movq    # 传送四字 (64位)

2.add 加法指令

perl 复制代码
addl $10, %eax           # %eax = %eax + 10
addl %ebx, %eax          # %eax = %eax + %ebx
addl (%ebx), %eax        # %eax = %eax + [%ebx]

3.sub 减法指令

perl 复制代码
subl $10, %eax           # %eax = %eax - 10
subl %ebx, %eax          # %eax = %eax - %ebx

4.乘法和除法

perl 复制代码
imull %ebx, %eax         # %eax = %eax * %ebx
idivl %ebx               # %eax = %eax / %ebx (商)

5.自增自减

perl 复制代码
incl %eax                # %eax++
decl %eax                # %eax--
  1. 位运算
perl 复制代码
andl $0xFF, %eax         # %eax = %eax & 0xFF
orl $0xFF, %eax          # %eax = %eax | 0xFF
xorl %ebx, %eax          # %eax = %eax ^ %ebx
notl %eax                # %eax = ~%eax

7.移位指令

perl 复制代码
shll $2, %eax            # 逻辑左移 2 位
shrl $2, %eax            # 逻辑右移 2 位
sarl $2, %eax            # 算术右移 2 位
roll $2, %eax            # 循环左移 2 位
rorl $2, %eax            # 循环右移 2 位

8.比较指令

perl 复制代码
cmpl $10, %eax           # 比较 %eax 和 10
cmpl %ebx, %eax          # 比较 %eax 和 %ebx
testl %eax, %eax         # 测试 %eax 是否为零

9.条件跳转

bash 复制代码
je label                 # 相等时跳转 (ZF=1)
jne label                # 不相等时跳转 (ZF=0)
jl label                 # 小于时跳转 (SF≠OF)
jle label                # 小于等于时跳转 (ZF=1 或 SF≠OF)
jg label                 # 大于时跳转 (ZF=0 且 SF=OF)
jge label                # 大于等于时跳转 (SF=OF)

10.无条件的跳转

r 复制代码
jmp label                # 无条件跳转
call function            # 调用函数
ret                      # 返回

11.push 和pop指令

perl 复制代码
pushl %eax               # 压栈
popl %eax                # 出栈
pushl $123               # 压入立即数

寻址相关的指令

  1. 立即数寻址
perl 复制代码
movl $123, %eax          # 将立即数 123 加载到 %eax
movl $0xABCD, %ebx       # 将十六进制立即数加载到 %ebx
movl $'A', %ecx          # 将字符 'A' 的 ASCII 码加载到 %ecx

2.寄存器寻址

perl 复制代码
movl %eax, %ebx          # 将 %eax 的值复制到 %ebx
addl %ecx, %edx          # %edx = %edx + %ecx
xorl %esi, %edi          # %edi = %edi ^ %esi

3.直接寻址 (Direct Addressing)

perl 复制代码
movl variable, %eax      # 将变量 variable 的值加载到 %eax
movl %eax, variable      # 将 %eax 的值存储到变量 variable

4.间接寻址

perl 复制代码
movl (%eax), %ebx        # 将 %eax 指向的内存地址的值加载到 %ebx
movl %ebx, (%eax)        # 将 %ebx 的值存储到 %eax 指向的内存地址

5.基址偏移寻址

perl 复制代码
movl 4(%eax), %ebx       # %ebx = [%eax + 4]
movl -8(%eax), %ebx      # %ebx = [%eax - 8]
movl 0x100(%eax), %ebx   # %ebx = [%eax + 0x100]

示例

perl 复制代码
movl 4(%eax), %ebx       # %ebx = [%eax + 4]
movl -8(%eax), %ebx      # %ebx = [%eax - 8]
movl 0x100(%eax), %ebx   # %ebx = [%eax + 0x100]

6.基址变址寻址

perl 复制代码
movl (%eax,%ebx), %ecx   # %ecx = [%eax + %ebx]
movl (%esi,%edi), %eax   # %eax = [%esi + %edi]

数组访问示例:

perl 复制代码
movl $array, %eax        # 数组基地址
movl $2, %ebx            # 索引 (第3个元素)
movl (%eax,%ebx,4), %ecx # %ecx = array[2] (假设是int数组,每个元素4字节)
  1. 比例寻址
perl 复制代码
movl (%eax,%ebx,1), %ecx # %ecx = [%eax + %ebx * 1]
movl (%eax,%ebx,2), %ecx # %ecx = [%eax + %ebx * 2]
movl (%eax,%ebx,4), %ecx # %ecx = [%eax + %ebx * 4]
movl (%eax,%ebx,8), %ecx # %ecx = [%eax + %ebx * 8]

不同数据类型的数组访问:

perl 复制代码
# char 数组 (1字节)
movl $char_array, %eax
movl $5, %ebx
movb (%eax,%ebx,1), %cl  # %cl = char_array[5]

# short 数组 (2字节)
movl $short_array, %eax
movl $3, %ebx
movw (%eax,%ebx,2), %cx  # %cx = short_array[3]

# int 数组 (4字节)
movl $int_array, %eax
movl $2, %ebx
movl (%eax,%ebx,4), %ecx # %ecx = int_array[2]

# double 数组 (8字节)
movl $double_array, %eax
movl $1, %ebx
fldl (%eax,%ebx,8)       # 加载 double_array[1]
  1. 基址变址偏移寻址
perl 复制代码
movl 4(%eax,%ebx,4), %ecx # %ecx = [%eax + %ebx * 4 + 4]
movl -8(%esi,%edi,2), %eax # %eax = [%esi + %edi * 2 - 8]

总结:立即数 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 ( a , b ,立即数 1(a,b,立即数 </math>1(a,b,立即数2)表示的是 b * 立即数2 + a - 立即数1 ,然后获取的值作为地址,去找这个地址的值

AT&T中重要规律

  • 内存地址格式为:0x4bdc(%rip),一般是全局变量,静态变量,字符串字面量,常量数组,全局区(数据段)
ini 复制代码
// C 代码
int global_var = 42;
static int static_var = 100;

int main() {
    // 这些变量会被编译为 0x4bdc(%rip) 格式的地址
    int x = global_var;
    int y = static_var;
}
  • 内存地址格式为:-0x78(%rbp),一般是局部变量,栈空间

  • 内存地址格式为:0x10(%rax),一般是堆空间,rax是通用寄存器,通常用存储指针值。

c 复制代码
// C 代码
struct Person {
    int id;
    char name[20];
    int age;
};

int main() {
    struct Person *p = malloc(sizeof(struct Person));
    
    // 这些访问会被编译为 0x10(%rax) 格式
    p->id = 1;              // 偏移 0
    strcpy(p->name, "John"); // 偏移 4
    p->age = 25;            // 偏移 24 (0x18)
}
相关推荐
qqxhb2 小时前
系统架构设计师备考第12天——计算机语言组成和分类
系统架构·汇编语言·机器语言·执行顺序·高级语言·数据运算·数据组织
思考着亮6 天前
5.8086 汇编中栈平衡和函数调用过程分析
汇编语言
数据智能老司机15 天前
实现逆向工程——汇编指令演练
安全·逆向·汇编语言
Jooolin17 天前
【教你一招】反汇编有啥用?
c++·ai编程·汇编语言
danzongd22 天前
浅谈C++ const
c++·内存·优化·汇编语言·计算机系统·寄存器
CYRUS_STUDIO1 个月前
OLLVM 混淆 + VMP 壳照样破!绕过加壳 SDK 的核心检测逻辑
android·逆向·汇编语言
CYRUS_STUDIO2 个月前
Android 下内联汇编开发指南:从基础语法到多架构适配全掌握
android·android studio·汇编语言
CYRUS_STUDIO2 个月前
深入 Android syscall 实现:内联汇编系统调用 + NDK 汇编构建
android·操作系统·汇编语言
小墙程序员2 个月前
一文了解汇编语言
汇编语言