如何在nasm 64位中跳转到间接寄存器

时间:2016-01-18 14:43:51

标签: assembly 64-bit nasm

我在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:错误:地址大小的不可能组合"

2 个答案:

答案 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]?英特尔上lodsdlodsq只有2个uop,所以如果你确实需要两种效果,它们实际上并不是一个糟糕的选择。

答案 1 :(得分:1)

正如杰斯特指出的那样

jmp [rax]

是正确的,而

jmp qword[rax]

是允许的。 如果它失败了,你就会做错其他的事情。

在这种情况下,问题是缺少

BITS 64

关键字。

为了获得64位目标文件,您需要指定-felf64作为命令行中的体系结构,如此调用nasm

nasm x.asm -felf64 -g -o x.o

在这种情况下,暗示了BITS 64。问题当然是你永远不会过去聚会,也无法发现错误。