如何在 nasm 64 位中跳转到间接注册

How to do jump to register indirect in nasm 64 bit

我在 32 位程序(Forth 解释器)中有以下 nasm 代码

    MOV     EBP, LONG[USINI+(CW*(3))]    ;Return stack
    ...
    LODSD                  ; NEXT
    JMP      LONG[EAX]

最后一条指令取AX指向的地址,跳转到该地址。 64 位的等效代码不再 assemble:

    MOV     RBP, QWORD[USINI+(CW*(3))]    ;Return stack
    ...
    LODSD                  ; NEXT
    JMP      QWORD[RAX]

在 NASM 64 位中指定此指令的正确方法是什么? 当然,这可能是 nasm 中的一个缺陷,但我如何确定它呢?

(完全相同的代码 assembles 在 fasm 中效果很好。)

(第一个QWORD被nasm接受)

消息是:"ci86.lina64.asm:318: error: impossible combination of address sizes"
318是JMP的那一行。

nasm版本is:NASM版本2.10.01编译于Jun 14 2012

省略 "QWORD" 会给出相同的错误消息,此外: "ci86.lina64.asm:318: error: impossible combination of address sizes"

正如 Jester 指出的那样

jmp [rax]

是正确的,而

jmp qword[rax]

是允许的。 如果它失败了,你做错了什么。

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

BITS 64

关键字。

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

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

在这种情况下,隐含了 BITS 64。问题当然是您永远无法通过组装并且无法发现该错误。

首先,jmp [mem]是一个memory-indirect跳转(设置RIP=从内存加载的指针)。 jmp rax 将是 register-indirect 跳转,设置 RIP = RAX.

你没说第318行是哪一行,你确定是jmp吗?因为该行的语法看起来没有任何问题。

你的代码还在64位模式下使用32位指针吗?这是可能的,只要您坚持低 4GB 的地址 space,以便地址适合 32b。更改它需要 re-sizing 所有存储指针的数据结构。

请注意,默认情况下,堆栈地址 而不是 在低 32b 中。使用 32 位 address-size 前缀(例如 mov rdx, [eax])sign-extends 地址。

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 在 Intel 上只有 2 微指令,所以如果您确实需要这两种效果,它们实际上是一个不错的选择。