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

64位进程中如何正确合并两个DWORD为QWORD?我的实现错在哪?

在64位进程中合并两个DWORD为QWORD的正确姿势

首先,咱们先捋清楚你操作里的核心逻辑:x86架构的栈是向下增长的(栈指针rsp往数值减小的方向移动就是栈顶)。当你先push高位DWORD,再push低位DWORD,栈里的布局(从rsp指向的低地址往高地址看)是:低位DWORD → 高位DWORD。这时候pop rax的话,rax会把这8字节全部读入,结果就是(高位DWORD << 32) | 低位DWORD——这本身是正确的合并逻辑。

那为什么你的操作会出问题?大概率是这几个原因:

1. 高低位顺序搞反了

如果你实际想要的是低位DWORD在QWORD的高32位、高位在低32位(这通常不是常规的大/小端合并逻辑),那你的push顺序就错了。常规的合并应该是高位在QWORD的高32位,低位在低32位,这时候你的push顺序是对的;但如果你的需求反过来,就要改成先push低位,再push高位,再pop rax。

2. 32位寄存器操作的零扩展陷阱

如果你的代码是用32位寄存器(比如eax)暂存DWORD值,要注意:在x86-64模式下,写入32位寄存器会自动把对应64位寄存器的高32位清零。比如:

mov eax, [high_dword]   ; rax的高32位被清零,eax=high_dword
push eax                ; 栈里压入正确的high_dword(4字节)
mov eax, [low_dword]    ; rax高32位再次清零,eax=low_dword
push eax
pop rax                 ; rax最终为 (high_dword << 32) | low_dword,结果正确

这段代码本身没问题,但如果你误以为mov eax, high_dword之后rax的高32位还保留着之前的值,可能会在其他关联操作中出错,但单就合并QWORD来说,这里是正确的。

3. 栈对齐的隐性坑

在x86-64的Windows或Linux系统中,调用函数时要求栈指针rsp是16字节对齐的。如果你只push了两个4字节(总共8字节),如果之前的栈是对齐的,那此时rsp的数值是原rsp - 8,不再是16的倍数。如果之后紧接着调用其他函数,就会触发未定义行为(比如崩溃)。但这不是合并QWORD本身的错误,而是后续操作的问题。

更高效的合并方式(不用栈)

其实用栈来合并是比较低效的,直接用寄存器操作更快:

; 方式1:基础mov+shl组合
mov eax, [low_dword]
mov edx, [high_dword]
shl rdx, 32
or  rax, rdx            ; rax = (high_dword <<32) | low_dword

; 方式2:用movzx避免意外清零
movzx rax, dword ptr [low_dword]   ; rax高32位清零,低32位=low_dword
movzx rdx, dword ptr [high_dword]  ; rdx高32位清零,低32位=high_dword
shl rdx, 32
or  rax, rdx

; 方式3:直接读内存(如果两个DWORD连续存放)
; 假设low_dword在低地址、high_dword在高地址(小端布局),直接读8字节
mov rax, qword ptr [low_dword]

总结一下:如果栈操作的结果不对,先检查高低位顺序是否符合你的需求,再排查是否有寄存器操作的误解。如果追求效率,直接用寄存器合并会比栈操作更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:32:25