x64汇编中获取Windows API与本地函数地址的指令差异问询
打印Windows API与本地函数地址时,汇编为何用mov和lea两种指令?
我在Windows x64环境下用C语言学习底层时发现一个问题:打印Windows API CreateFileW 和本地函数 addfunc 的地址时,生成的汇编指令分别用了mov和lea,想知道两者的差异和原因。
对应的汇编代码如下:
printf("%x\n", CreateFileW); 00007FF60365276C mov rdx,qword ptr [__imp_CreateFileW (07FF603663000h)] 00007FF603652773 lea rcx,[string "%x\n" (07FF60365BEA0h)] 00007FF60365277A call printf (07FF603651208h) printf("%x\n", addfunc); 00007FF60365277F lea rdx,[addfunc (07FF60365137Fh)] 00007FF603652786 lea rcx,[string "%x\n" (07FF60365BEA0h)] 00007FF60365278D call printf (07FF603651208h)
核心差异:mov与lea的本质区别
mov:从指定内存地址读取数据到寄存器,是"读内存"操作。lea:计算指定内存符号的地址值并放到寄存器,不实际读取内存内容,只是做地址计算。
两种指令的使用原因
1. Windows API用mov的原因
Windows API属于动态链接库(如kernel32.dll)中的函数,编译程序时无法确定其真实内存地址:
- 程序通过**导入表(Import Table)**管理这些外部函数,
__imp_CreateFileW是导入表中的一个指针位置。 - 程序加载时,系统会将这个指针填充为
CreateFileW在内存中的真实地址。 - 用
mov rdx, qword ptr [__imp_CreateFileW],就是读取这个指针指向的真实函数地址,作为参数传给printf。
2. 本地函数用lea的原因
本地函数addfunc属于当前程序的编译单元,编译/链接阶段就已经确定了它的内存地址:
lea rdx, [addfunc]直接计算出addfunc的地址值,将这个地址存入rdx作为参数。- 编译器选择lea而非
mov rdx, addfunc(也可实现),是因为lea支持RIP相对寻址(x64下默认的寻址方式),编码更紧凑高效,或符合编译器的优化策略。
内容的提问来源于stack exchange,提问作者Stephen Francis
相关产品推荐
相关产品推荐

