Assembly 如何在nasm 64位中跳转到寄存器间接
我在一个32位程序(一个Forth解释器)中有以下nasm代码 最后一条指令获取AX指向的地址并跳到该地址。 64位的等效代码不再汇编:Assembly 如何在nasm 64位中跳转到寄存器间接,assembly,64-bit,nasm,Assembly,64 Bit,Nasm,我在一个32位程序(一个Forth解释器)中有以下nasm代码 最后一条指令获取AX指向的地址并跳到该地址。 64位的等效代码不再汇编: MOV RBP, QWORD[USINI+(CW*(3))] ;Return stack ... LODSD ; NEXT JMP QWORD[RAX] 以NASM 64位指定此指令的正确方式是什么? 当然,这可能是nasm的一个缺陷,但我如何才能确定这一点呢 (在fa
MOV RBP, QWORD[USINI+(CW*(3))] ;Return stack
...
LODSD ; NEXT
JMP QWORD[RAX]
以NASM 64位指定此指令的正确方式是什么?
当然,这可能是nasm的一个缺陷,但我如何才能确定这一点呢
(在fasm中,完全相同的代码汇编效果良好。)
(第一个QWORD被nasm接受)
消息是:“ci86.lina64.asm:318:错误:地址大小不可能组合”318与JMP一致 nasm版本为:2012年6月14日编译的nasm版本2.10.01 省略“QWORD”会显示相同的错误信息,此外: “ci86.lina64.asm:318:错误:地址大小不可能组合”正如Jester指出的那样
jmp [rax]
是正确的,而
jmp qword[rax]
是允许的。
如果失败了,你就做错了别的事情
在这种情况下,问题在于缺少
第64位
关键词
为了获得一个64位的对象文件,您需要在调用nasm的命令行中指定-felf64作为体系结构,如下所示
nasm x.asm-felf64-g-o x.o
在这种情况下,位64是隐含的。当然,问题是,你永远无法通过装配,也无法发现错误 正如杰斯特指出的那样
jmp [rax]
是正确的,而
jmp qword[rax]
是允许的。
如果失败了,你就做错了别的事情
在这种情况下,问题在于缺少
第64位
关键词
为了获得一个64位的对象文件,您需要在调用nasm的命令行中指定-felf64作为体系结构,如下所示
nasm x.asm-felf64-g-o x.o
在这种情况下,位64是隐含的。当然,问题是,你永远无法通过装配,也无法发现错误 首先,
jmp[mem]
是一个内存间接跳转(set RIP=从内存加载的指针)jmp-rax
将是一个寄存器间接跳转,设置为RIP=rax
你没说哪条线是318号线。你确定这是jmp
?因为这一行的语法看起来没有什么问题
您的代码还在64位模式下使用32位指针吗?这是可能的,只要您坚持低4GB的地址空间,使地址适合32b。改变这一点需要重新调整存储指针的所有数据结构的大小
请注意,默认情况下堆栈地址不在低位32b。使用32位地址大小前缀(例如,mov-rdx[eax]
)符号扩展地址
MOV EBP, QWORD[USINI+(CW*(3))] ; you probably need RBP, or else this should still be a 32bit load. If it's 64bit, I hope you fixed the address calculations to account for each element being wider.
...
LODSD ; This a 32bit load, zeroing the upper32 of RAX.
JMP QWORD[RAX]
您是否需要递增
rsi
,或者您是否可以在jmp之前使用mov eax,[rsi]
lodsd
和lodsq
在Intel上只有2个UOP,因此如果您确实需要这两种效果,它们实际上不是一个坏选择。首先,jmp[mem]
是内存间接跳转(设置RIP=从内存加载的指针)jmp-rax
将是一个寄存器间接跳转,设置为RIP=rax
你没说哪条线是318号线。你确定这是jmp
?因为这一行的语法看起来没有什么问题
您的代码还在64位模式下使用32位指针吗?这是可能的,只要您坚持低4GB的地址空间,使地址适合32b。改变这一点需要重新调整存储指针的所有数据结构的大小
请注意,默认情况下堆栈地址不在低位32b。使用32位地址大小前缀(例如,mov-rdx[eax]
)符号扩展地址
MOV EBP, QWORD[USINI+(CW*(3))] ; you probably need RBP, or else this should still be a 32bit load. If it's 64bit, I hope you fixed the address calculations to account for each element being wider.
...
LODSD ; This a 32bit load, zeroing the upper32 of RAX.
JMP QWORD[RAX]
您是否需要递增
rsi
,或者您是否可以在jmp之前使用mov eax,[rsi]
lodsd
和lodsq
在Intel上只有2个UOP,因此如果您确实需要这两种效果,它们实际上不是一个坏选择。jmp[rax]
是一个64位跳转,因为所有间接跳转都是64位的。您不需要qword
,即使它确实有效。不过,还不清楚您是想jmprax
还是jmp[rax]
。你还忘了发布nasm版本和你得到的错误。我只会在尝试以32位的形式组装时得到这个错误。你确定你正确使用了64位吗?没错,杰斯特。我忘了从“第64位”开始。所有这些QWORDS都被接受了,我完全无法朝着这个方向思考。投票以“印刷错误”结束,如果只是这样的话。这是一个棘手的问题,花了我很多时间。将其视为单纯的印刷错误会使人们无法了解省略位64关键字会导致何种情况。jmp[rax]
是一种64位跳转,因为所有间接跳转都是64位的。您不需要qword
,即使它确实有效。不过,还不清楚您是想jmprax
还是jmp[rax]
。你还忘了发布nasm版本和你得到的错误。我只会在尝试以32位的形式组装时得到这个错误。你确定你正确使用了64位吗?没错,杰斯特。我忘了从“第64位”开始。所有这些QWORDS都被接受了,我完全无法朝着这个方向思考。投票以“印刷错误”结束,如果只是这样的话。这是一个棘手的问题,花了我很多时间。将其视为单纯的印刷错误会使人们无法了解省略BITS 64关键字会导致什么样的情况。当然,代码是按预期编写的。这是一个成熟的Forth解释器(2001年,自2008年以来为64位),有几十个程序解决了projecteuler.net问题,有时运行几天。@AlbertvanderHorst:所以你不把它移植到64位?从问题的措辞来看,我认为你是。您是否在为自己的项目借用它的代码块?我不明白是什么改变使它“停止工作”。我有一个系统,通过m4可以为d生成相同的汇编代码