scanf函数将输入值存储到哪个寄存器?附反汇编实例分析疑问
scanf输入值的存储位置说明
scanf不会将读取到的用户输入直接存储到通用寄存器中,所有写入目标都是调用方传入的内存指针指向的可写内存区域。对这段反汇编的误判来自对寄存器传参、栈帧分配逻辑的混淆,逐点拆解如下:
基础规则说明(x86_64 System V调用约定)
这段反汇编是x86_64架构下gcc生成的典型代码,遵循标准SysV函数调用规则:
- 函数调用时前6个指针/整型参数依次通过
rdi、rsi、rdx、rcx、r8、r9传递,超出6个的参数才会通过压栈传递。 - 函数开头的
sub rsp, 0x18已经一次性在栈上预留了24字节的栈帧空间,用来存放所有局部变量,不需要在调用scanf前额外执行push压栈操作。提前抬升栈指针一次性分配局部变量空间是编译器生成栈帧的常规操作,不需要靠逐个push分配空间。
scanf调用的参数逻辑
0x0000089c位置调用scanf前的参数准备完全符合上述约定:
- 第一参数(格式串):
lea rdi, str.u__u ; "%u %u",将格式字符串"%u %u"的地址存入rdi,表示需要读取2个无符号十进制整数。 - 第二参数(第一个输入值的存储指针):
mov rsi, rsp,将当前栈顶的内存地址存入rsi传给scanf。注意这里传递的是rsp中存储的地址值,不是让scanf写入rsp寄存器本身。 - 第三参数(第二个输入值的存储指针):
lea rdx, [var_4h],将栈上另一个4字节局部变量的地址存入rdx传给scanf。
后续指令的验证
scanf调用后的指令可以直接验证存储位置:
0x000008a1 mov eax, dword [rsp]:将rsp指向的栈内存中存储的4字节值读入eax寄存器,再与0x1336做比较,说明第一个用户输入的无符号整数,是被scanf写入rsp指向的栈内存位置,而非rsp寄存器中。- 第二个读入的无符号整数,会被scanf写入
rdx传入的var_4h对应的栈内存位置。
所有标准C库的输入读取函数(scanf、fscanf、fread等)都只会向传入指针指向的可写内存区域写入数据。通用寄存器没有用户态可直接访问的线性地址,永远不可能被这类函数直接写入。传参阶段寄存器中存储的都是指向存储位置的指针,不是输入值本身的存储目的地。
内容的提问来源于stack exchange,提问作者user18005111
相关产品推荐
相关产品推荐

