You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86-64平台下GCC中"%d\n"格式字符串如何存储及传给printf?

关于x86-64下printf字符串参数传递的疑问

调试的C程序

#include <stdio.h>
#include <stdlib.h>

int main() {
  int a = 12;
  printf("%d\n", a);
}

对应的汇编代码

0x0000000000001139 <+0>:    push   rbp
   0x000000000000113a <+1>: mov    rbp,rsp
   0x000000000000113d <+4>: sub    rsp,0x10
   0x0000000000001141 <+8>: mov    DWORD PTR [rbp-0x4],0xc
   0x0000000000001148 <+15>:    mov    eax,DWORD PTR [rbp-0x4]
   0x000000000000114b <+18>:    mov    esi,eax
   0x000000000000114d <+20>:    lea    rax,[rip+0xeb0]        # 0x2004
   0x0000000000001154 <+27>:    mov    rdi,rax
   0x0000000000001157 <+30>:    mov    eax,0x0
   0x000000000000115c <+35>:    call   0x1030 <printf@plt>
   0x0000000000001161 <+40>:    mov    eax,0x0
   0x0000000000001166 <+45>:    leave
   0x0000000000001167 <+46>:    ret

疑问与解答

你对变量a的传递逻辑理解正确,而"%d\n"字符串并未存储在栈中,rdi寄存器里存放的是这个字符串在内存中的地址,它指向程序的只读数据段(.rodata)——这是编译阶段就确定的、专门存放常量字符串等只读数据的内存区域。

核心看这两行汇编指令:

  • lea rax,[rip+0xeb0]:通过RIP相对寻址计算出字符串的绝对内存地址,注释里的# 0x2004就是最终计算得到的地址值。
  • mov rdi,rax:将这个地址赋值给rdi,完全符合x86-64调用约定中第一个参数用rdi传递的规则。

采用RIP相对寻址是因为x86-64程序默认是位置无关代码(PIC),这样程序加载到任意内存地址时,都能通过当前指令地址(RIP)的偏移量找到目标字符串的位置。

你可以在GDB中执行x/s 0x2004,直接查看该地址存储的内容,就能看到"%d\n"字符串。

内容的提问来源于stack exchange,提问作者koiboi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 06:17:30