Assembly 使用偏移量表的x64汇编程序jmp
为了提高效率,我想使用一个地址表,我可以通过一个寄存器将其索引到jmp,以在汇编程序例程中实现 举个例子可能会让这更清楚Assembly 使用偏移量表的x64汇编程序jmp,assembly,64-bit,Assembly,64 Bit,为了提高效率,我想使用一个地址表,我可以通过一个寄存器将其索引到jmp,以在汇编程序例程中实现 举个例子可能会让这更清楚 .CODE ... AppendByte PROC XOR RAX, RAX MOV AL, CL ; Get this 0-7 index from somewhere else JMP QWORD PTR[RAX + OFFSET APPENDBYTETABLE] AppendByte ENDP App
.CODE
...
AppendByte PROC
XOR RAX, RAX
MOV AL, CL ; Get this 0-7 index from somewhere else
JMP QWORD PTR[RAX + OFFSET APPENDBYTETABLE]
AppendByte ENDP
AppendByte_7:
; Do stuff...
RET
AppendByte_6:
; Do stuff...
RET
...
AppendByte_0:
RET
.DATA
APPENDBYTETABLE QWORD AppendByte_0, AppendByte_1, AppendByte_2,
AppendByte_3, AppendByte_4, AppendByte_5,
AppendByte_6, AppendByte_7
END
这将在VS2017中编译,但随后我得到一个链接器错误。
我认为这与使用远地址有关。如何生成近偏移量并对数据段中存储在表中的偏移量执行短jmp
请注意,如果我将AppendByte_x标签放在进程中,编译器就会发出嘎嘎声
决心!编辑后,建议从引信
XOR RAX, RAX
MOV AL, REG_PREFIXCODEBITS
LEA RCX, APPENDBYTETABLE
JMP QWORD PTR [RCX + RAX * 8]
虽然我对微软的工具链不是很熟悉,但我认为主要的问题是,在SIB(缩放/索引/基)寻址模式中,例如
[RAX+OFFSET APPENDBYTETABLE]
,位移被限制为一个或四个字节。Microsoft链接器希望使您的程序可以从任何地址加载,包括前4 GB地址空间以上的地址,需要完整的8字节来表示地址。显然,4个字节不足以容纳8个字节,因此链接器有理由抱怨
要解决此问题,必须首先加载地址为APPENDBYTETABLE
的寄存器,然后将其索引到表中。执行此操作的一般方法是使用lea
(加载有效地址)指令lea-rax,foo
类似于mov-rax,foo
,但不是在foo
处加载内存,而是返回foo
的地址。这可与rip
(指令指针)相对寻址模式结合使用,以获取APPENDBYTETABLE
的地址,尽管位移再次限制为4字节。这是因为链接器假定每个程序或DLL各自小于2 GB,因此有符号的32位偏移量始终足以找到变量或函数相对于当前指令位置的地址。当您直接访问变量而不使用索引寄存器或SIB寻址模式时,汇编程序会隐式选择rip
相对寻址模式:
lea rax, APPENDBYTETABLE ; load address of APPENDBYTETABLE rip-relative
当然,您也可以使用
mov reg,offset foo
加载foo
的地址。这使用了一种带有8字节立即数的mov
。但是,此指令的编码比lea reg,foo
长,速度可能较慢,并且可能需要加载程序在运行时修补正确的地址,从而减慢程序的启动速度。如果没有很好的理由不这样做,只需坚持使用lea
。你到底得到了什么链接器错误?“我得到一个错误”不是一个有用的错误描述。道歉,谢谢你的快速响应!错误:1>first.obj:error LNK2017:'ADDR32'重新定位到'APPENDBYTETABLE'无效,没有/LargeAddressWare:NO 1>链接:致命错误LNK1165:链接因修复错误而失败,我知道问题出在哪里了;让我写一个答案。试着用learcx,APPENDBYTETABLE
替换jmp-qword-ptr[rcx+offset-APPENDBYTETABLE]
,然后jmp-qword-ptr[rcx+rax]
。这行得通吗?我通过观察编译器生成什么样的程序集以及从互联网上的无数资源中获取了大部分信息。我还没有真正学习过这方面的教程。