我在32位程序中使用以下nasm代码(Forth解释器)
MOV EBP, LONG[USINI+(CW*(3))] ;Return stack
...
LODSD ; NEXT
JMP LONG[EAX]
最后一条指令从AX指向的地址获取地址并跳转到该地址。 64位的等效代码不再集合:
MOV RBP, QWORD[USINI+(CW*(3))] ;Return stack
...
LODSD ; NEXT
JMP QWORD[RAX]
在NASM 64位中指定此指令的正确方法是什么? 当然,这可能是一个缺陷,但我怎么能确定呢?
(完全相同的代码在fasm中组合起来效果很好。)
(第一个QWORD被nasm接受)
消息是:" ci86.lina64.asm:318:错误:地址大小不可能组合"
318是JMP的行。
nasm版本是:2012年6月14日编译的NASM版本2.10.01
退出" QWORD"给出相同的错误消息,另外: " ci86.lina64.asm:318:错误:地址大小的不可能组合"
答案 0 :(得分:2)
首先,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
只有2个uop,所以如果你确实需要两种效果,它们实际上并不是一个糟糕的选择。
答案 1 :(得分:1)
正如杰斯特指出的那样
jmp [rax]
是正确的,而
jmp qword[rax]
是允许的。 如果它失败了,你就会做错其他的事情。
在这种情况下,问题是缺少
BITS 64
关键字。
为了获得64位目标文件,您需要指定-felf64作为命令行中的体系结构,如此调用nasm
nasm x.asm -felf64 -g -o x.o
在这种情况下,暗示了BITS 64。问题当然是你永远不会过去聚会,也无法发现错误。