是否有任何汇编指令来对齐特定的堆栈数据变量?
例如,假设一个MASM函数有这些初始值为 的局部变量LOCAL beginStack:QWORD ; ffffffffdeadbeef
LOCAL myLocalA:QWORD ; ffffffffffffffff
LOCAL myLocalB:QWORD ; 0000000000000000
LOCAL myArrayA[10]:BYTE ; AAAAAAAAAA
LOCAL myArrayB[10]:BYTE ; BBBBBBBBBB
LOCAL endStack:QWORD ; ffffffffbaadf00d
内存堆栈有这样的布局,但注意endStack
是不对齐的
00000048`51effb60 baadf00d000906ec ; baadf00d
00000048`51effb68 42424242ffffffff ; ffffffff
00000048`51effb70 4141424242424242
00000048`51effb78 4141414141414141
00000048`51effb80 0000000000000000
00000048`51effb88 ffffffffffffffff
00000048`51effb90 ffffffffdeadbeef
对齐endStack
,我试图将局部变量与对齐pad[4]
混合
LOCAL beginStack:QWORD
LOCAL myLocalA:QWORD
LOCAL myLocalB:QWORD
LOCAL myArrayA[10]:BYTE
LOCAL myArrayB[10]:BYTE
LOCAL pad[4]:BYTE
LOCAL endStack:QWORD
正确对齐endStack
0000005b`950ff950 ffffffffbaadf00d ; aligned
0000005b`950ff958 42424242ffdaf38f ; pad[4] is ffdaf38f
0000005b`950ff960 4141424242424242
0000005b`950ff968 4141414141414141
0000005b`950ff970 0000000000000000
0000005b`950ff978 ffffffffffffffff
0000005b`950ff980 ffffffffdeadbeef
另一种方法(如果适用)是根据降序层次结构重新洗牌堆栈变量QWORD
->DWORD
→WORD
→BYTE
GCC有这个__attribute__ ((aligned (8)))
来对齐变量,但是否有汇编语言的等效方法?
感觉像C/c++这样的高级语言有一个很大的优化技巧工具箱,但不幸的是没有移植到较低级的汇编语言。
目前为止的部分答案是定义一个MASM宏aligned
,它向DWORD和WORD变量插入填充字节,使它们在64位中保持8字节对齐。
这个粗宏接受一个DWORD或WORD变量,然后决定填充字节数。为了防止重复的符号错误,它定义了一个本地num
,它在每次调用宏时生成唯一的标签。输出是局部变量本身,后跟填充符:DWORD为LOCAL pad??0001[4]
, WORD为LOCAL pad??0001[6]
。
aligned MACRO var
LOCAL num
IF @InStr(1,<var>,<:DWORD>) NE 0
padBytes = 4
ELSEIF @InStr(1,<var>,<:WORD>) NE 0
padBytes = 6
ENDIF
var
@CatStr(<LOCAL pad>,<num>,<[padBytes]:BYTE>)
ENDM
为了与其他C/c++对齐保持类似,LOCAL的前缀是aligned
宏调用
main proc
aligned LOCAL AppleA:WORD
aligned LOCAL AppleB:DWORD
aligned LOCAL AppleC:WORD
aligned LOCAL AppleD:DWORD
LOCAL OrangeA:WORD
LOCAL OrangeB:DWORD
LOCAL OrangeC:WORD
LOCAL OrangeD:DWORD
mov AppleA,1
mov AppleB,2
mov AppleC,3
mov AppleD,4
mov OrangeA,5
mov OrangeB,6
mov OrangeC,7
mov OrangeD,8
ret
main endp
end
运行代码的内存堆栈显示
00000030`f1b1fb10 00077ff600000008 ; OrangeD 8 is misaligned
00000030`f1b1fb18 00057ff600000006 ; OrangeB 6 is misaligned
00000030`f1b1fb20 000000040000001f ; AppleD 4 is aligned
00000030`f1b1fb28 0003000000000000 ; AppleC 3 is aligned
00000030`f1b1fb30 0000000200000000 ; AppleB 2 is aligned
00000030`f1b1fb38 00017ff6915ae298 ; AppleA 1 is aligned
指出
如注释所述,这个宏还不能解析数组。一个解决方案是使用MASM MOD运算符,当expression1除以expression2时,返回余数(取模)的整数值。我们的想法是接受一个数组,比如aligned LOCAL myArrayA[10]:BYTE
,提取10的arraySize
,然后使用
padBytes = (8 - (arraySize MOD 8))
Michael Petch提出了一个非常聪明和独特的方法,将所有的局部元素放在一个结构中。一个结构可以接受一个对齐值(例如:8或QWORD),它将相应地对齐元素。这是一点额外的工作,但它会达到目的。示例如下:pastebin.com/4cLWm0f1
.code
main PROC
main_locs STRUC QWORD ; 8 byte (QWORD) alignment
beginStack DQ ?
myLocalA DQ ?
myLocalB DQ ?
myArrayA BYTE 10 DUP (?)
myArrayB BYTE 10 DUP (?)
endStack DQ ?
main_locs ENDS
LOCAL stack_vars: main_locs
lea rcx, stack_vars
mov [rcx][main_locs.beginStack], 0ffffffffdeadbeefh
mov [rcx][main_locs.myLocalA], 0ffffffffffffffffh
mov [rcx][main_locs.myLocalB], 00000000000000000h
;Fill myArrayA with 10 As
mov rax, "AAAAAAAA"
mov QWORD PTR[rcx][main_locs.myArrayA], rax
mov WORD PTR[rcx][main_locs.myArrayA+8], ax
;Fill myArrayB with 10 Bs
mov rax, "BBBBBBBB"
mov QWORD PTR[rcx][main_locs.myArrayB], rax
mov WORD PTR[rcx][main_locs.myArrayB+8], ax
mov [rcx][main_locs.endStack], 0ffffffffbaadf00dh
ret
main ENDP
end