public
c++ hello world反汇编
linux/aarch64/hello_world.md
0x000000555555c5d8 <+0>: sub sp, sp, #0x30
0x000000555555c5dc <+4>: stp x29, x30, [sp, #32]
0x000000555555c5e0 <+8>: add x29, sp, #0x20
0x000000555555c5e4 <+12>: mov w8, wzr
0x000000555555c5e8 <+16>: str w8, [sp, #12]
0x000000555555c5ec <+20>: stur wzr, [x29, #-4]
0x000000555555c5f0 <+24>: stur w0, [x29, #-8]
0x000000555555c5f4 <+28>: str x1, [sp, #16]
=> 0x000000555555c5f8 <+32>: adrp x0, 0x5555565000
0x000000555555c5fc <+36>: ldr x0, [x0, #3136]
0x000000555555c600 <+40>: nop
0x000000555555c604 <+44>: adr x1, 0x555555640b
0x000000555555c608 <+48>: bl 0x555555c628 <_ZNSt6__ndk1lsB8ne180000INS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc>
0x000000555555c60c <+52>: nop
0x000000555555c610 <+56>: adr x1, 0x555555c69c <_ZNSt6__ndk14endlB8ne180000IcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_>
0x000000555555c614 <+60>: bl 0x555555c670 <_ZNSt6__ndk113basic_ostreamIcNS_11char_traitsIcEEElsB8ne180000EPFRS3_S4_E>
0x000000555555c618 <+64>: ldr w0, [sp, #12]
0x000000555555c61c <+68>: ldp x29, x30, [sp, #32]
0x000000555555c620 <+72>: add sp, sp, #0x30
0x000000555555c624 <+76>: ret
这是一段ARM64架构上的函数汇编代码。以下是逐行解释:
函数的主要功能
从汇编来看,这段代码涉及栈操作、寄存器保存/恢复以及函数调用。它可能是一个简单的 C++ 程序的函数实现,包含输出操作和结束返回值的设置。
逐行解释
函数的开头:栈帧初始化
0x000000555555c5d8 <+0>: sub sp, sp, #0x30
- 功能: 为栈帧分配空间,减少栈指针
sp的值 0x30(48 字节)。 - 目的: 为局部变量和保存寄存器留出空间。
0x000000555555c5dc <+4>: stp x29, x30, [sp, #32]
- 功能: 将当前帧指针
x29和返回地址x30保存到栈的第 32 字节位置。 - 目的: 保存上一个栈帧的上下文信息。
0x000000555555c5e0 <+8>: add x29, sp, #0x20
- 功能: 设置当前帧指针
x29,指向当前栈帧的第 32 字节位置。 - 目的: 建立新的栈帧。
局部变量初始化
0x000000555555c5e4 <+12>: mov w8, wzr
- 功能: 将寄存器
wzr(常数 0)赋值给w8。 - 目的: 初始化局部变量为 0。
0x000000555555c5e8 <+16>: str w8, [sp, #12]
- 功能: 将寄存器
w8的值(0)存储到栈中第 12 字节位置。 - 目的: 初始化栈中的某个局部变量。
0x000000555555c5ec <+20>: stur wzr, [x29, #-4]
- 功能: 将 0(
wzr的值)存储到当前帧指针x29的偏移 -4 位置。 - 目的: 初始化局部变量。
0x000000555555c5f0 <+24>: stur w0, [x29, #-8]
- 功能: 将
w0的值存储到当前帧指针x29的偏移 -8 位置。 - 目的: 保存函数的第一个参数(
w0)。
0x000000555555c5f4 <+28>: str x1, [sp, #16]
- 功能: 将
x1的值存储到栈中第 16 字节位置。 - 目的: 保存函数的第二个参数(
x1)。
代码段的主要逻辑
0x000000555555c5f8 <+32>: adrp x0, 0x5555565000
- 功能: 将内存页地址
0x5555565000加载到x0(高地址部分)。 - 目的: 用于定位某个全局变量或静态数据。
0x000000555555c5fc <+36>: ldr x0, [x0, #3136]
- 功能: 从
0x5555565000 + 3136位置加载数据到x0。 - 目的: 取出某个全局变量或静态变量的值。
函数调用:C++ 输出
0x000000555555c604 <+44>: adr x1, 0x555555640b
- 功能: 将字符串地址加载到寄存器
x1。 - 目的: 为函数调用准备参数(可能是 C++ 的
std::cout操作)。
0x000000555555c608 <+48>: bl 0x555555c628
- 功能: 跳转并链接到
0x555555c628,即调用一个函数。 - 目的: 执行输出操作。
栈帧清理与返回
0x000000555555c61c <+68>: ldp x29, x30, [sp, #32]
- 功能: 恢复帧指针
x29和返回地址x30。 - 目的: 恢复上一个栈帧的上下文。
0x000000555555c620 <+72>: add sp, sp, #0x30
- 功能: 释放栈空间,将栈指针恢复到调用之前的状态。
0x000000555555c624 <+76>: ret
- 功能: 返回调用者函数。
- 目的: 结束当前函数执行。
总结
这段代码主要完成以下任务:
- 初始化栈帧,保存上下文。
- 初始化局部变量和参数。
- 调用某个输出函数(可能是 C++ 的
std::cout)。 - 清理栈帧,返回调用者。
如果这段代码是反汇编的 C++ 函数,可能对应的逻辑是:
void example(int arg1) {
int x = 0;
std::cout << "Some string" << std::endl;
return x;
}
从汇编代码的特点可以判断出这是 ARM64 指令集架构。以下是具体的依据:
1. 寄存器命名规则
-
ARM64 使用
x和w系列寄存器:- 64位寄存器:
x0到x30。 - 32位寄存器:
w0到w30(对应x寄存器的低 32 位)。 - 例如:
这些寄存器(如mov w8, wzr stp x29, x30, [sp, #32]x29,x30,w8)是 ARM64 的典型特征。
- 64位寄存器:
-
特殊寄存器:
sp:栈指针(Stack Pointer)。x29:帧指针(Frame Pointer)。x30:链接寄存器(Link Register),存储返回地址。wzr和xzr:零寄存器,值固定为 0。
2. 指令格式
ARM64 的指令通常固定为 32 位长,并且遵循特定格式:
-
典型指令:
sub sp, sp, #0x30:调整栈指针,分配栈空间。stp x29, x30, [sp, #32]:一次性保存两个 64 位寄存器(x29 和 x30)。ldr x0, [x0, #3136]:从地址x0 + 3136处加载数据。
-
指令操作的范围:
- 常用的立即数范围较小(例如
#0x30)。 - 内存访问采用基于寄存器偏移的方式。
- 常用的立即数范围较小(例如
3. 栈操作习惯
-
ARM64 的栈指针遵循 16 字节对齐要求。
- 例如:
分配的栈空间为 48 字节,是 16 的倍数。sub sp, sp, #0x30
- 例如:
-
ARM64 通常使用
stp和ldp指令(Store Pair 和 Load Pair)保存/恢复多个寄存器。- 例如:
stp x29, x30, [sp, #32] ldp x29, x30, [sp, #32]
- 例如:
4. ADR 和 ADRP 指令
adr和adrp是 ARM64 特有的指令,用于处理地址:adr:加载当前指令附近的地址。adrp:加载当前页的基地址。- 例如:
adrp x0, 0x5555565000 ldr x0, [x0, #3136]adrp加载内存页基地址。ldr在基地址上加偏移量。
5. 链接和调用约定
-
ARM64 的函数调用遵循特定的 ABI(如 AArch64 ABI):
- 参数传递:
- 前 8 个参数用
x0到x7传递。 - 超过 8 个参数存放在栈中。
- 前 8 个参数用
- 返回值:
- 返回值通过
x0寄存器返回。
- 返回值通过
- 参数传递:
-
例如:
bl 0x555555c628bl是 ARM64 的函数调用指令(Branch and Link),会跳转到目标地址并保存返回地址到x30。
6. 代码风格
- ARM64 汇编代码中常见的模式:
- 栈帧管理(
sub sp, sp, ...和add sp, sp, ...)。 - 使用
wzr/xzr表示零值。 stp/ldp和adr/adrp指令的频繁出现。
- 栈帧管理(
总结
根据上述特点,这段代码显然是基于 ARM64(AArch64)架构 的汇编代码,而非其他架构(如 x86-64 或 ARM32)。