【问题标题】:PTR Directive in ASM, how does it work?ASM 中的 PTR 指令,它是如何工作的?
【发布时间】:2017-02-09 15:57:51
【问题描述】:

我有这个带有一些变量和 1 条指令的 ASM 代码块:

.data
g BYTE 32h
a DWORD 11111111h
h BYTE 64h
.code
mov ebx, DWORD PTR g

谁能解释一下为什么 ebx 的值不是 11 11 11 32 而不是 00 00 00 32 或者至少 PTR 是如何工作的?

我认为 PTR 指令会将操作数表示为 32 位操作数?

提前致谢。

【问题讨论】:

  • ebx 之后应该是 11111111h,因为您刚刚加载了 a32 ,它是 g 的一部分,在内存中较早,不能在 ebx 中。
  • stackoverflow.com/q/41562732/4271923 记下双关语 cmets,它基本上解释了 PTR 的工作原理 - 它没有,由于语法,当您指定参数宽度时,它只需要 3 个字母。至少在 TASM/MASM 汇编器中。例如,在 NASM 中,根本不使用“PTR”,因为它实际上并没有做任何事情。 (当然,即使是为了有意义的事情,也可能有一些完全其他的汇编程序使用 PTR,但我猜你问的是 MASM/TASM 之一)

标签: pointers assembly x86 masm32


【解决方案1】:

如果你的代码真的和你发布的一样,请查看@Jester 的评论。


但从你的问题来看,我猜你的代码实际上包含这一行:

mov ebx, DWORD PTR g

我认为 PTR 指令会将操作数表示为 32 位操作数?

这取决于你的意思。当大小不明确时,DWORD PTR 将用作大小说明符。
例如,指令mov [eax], 0 将是模棱两可的,因为汇编器不知道您是否要写一个字节、一个字、一个双字等。所以在这种情况下,您可以使用DWORD PTR 来声明您想要将DWORD 写入内存:mov DWORD PTR [eax], 0

如果要从内存中读取一个字节并将其转换为DWORD,则需要使用movzxmovsx

movzx ebx, BYTE PTR g   ; if g should be treated as unsigned
movsx ebx, BYTE PTR g   ; if g should be treated as signed

【讨论】:

  • DWORD PTR 也可用于覆盖数据类型的大小,例如 xyz dw 05678h,01234h ... mov ebx,dword ptr xyz,这会将 012345678h 加载到 ebx 中。在这种情况下,操作数大小是已知的,但如果不使用“dword ptr”覆盖,MASM 和其他汇编程序将产生错误。
  • @rcgldr 是的,但是如果您遵循有效的 Intel 语法,即使在 MASM 中,mov ebx,[xyz] 也会在没有 DWORD PTR 的情况下编译?我猜。我不知道。我在“理想”模式下使用 TASM,它确实可以这样工作,寄存器宽度足够,并且正确使用了大括号。
  • ptr 可能不表示指针的一种情况是带有推送立即数,例如push dword ptr 012345678h,因为立即数可能表示指针以外的东西。
  • @Ped7g - 如果没有覆盖,Microsoft MASM / ML 会抱怨。在加载 128 位 xmm 寄存器时,程序员几乎不得不使用它。 abc dq 00123456789abcdefh,0fedbca9876543210h ... movdqa xmm0, xmmword ptr abc 。 (movdqa = 移动双四字对齐),因为 MASM 没有 ddq 或 dx 之类的东西来生成 128 位数据。
  • @Michael 感谢您的回复。还有一件事,如果我想将 eax (具有某些值)与 8 位操作数(例如 g )进行比较,我必须将 g 移动到 32 位操作数进行比较吗? PTR 有什么用处吗?
【解决方案2】:

不幸的是,x86 的汇编语言太通用了,使用

mov ebx,a

如果您查看指令编码(如果您正在编写/学习程序集,您应该有一个方便的参考并打开)您会发现这可能意味着读取地址 8 处的字节,或地址 a 处的 16 位字或可能是地址 a 的 32 位字。它可能会也可能不会更进一步,是否允许符号扩展。因此,为了获得您想要的正确指令,您需要添加更多内容。

汇编语言不是一些标准,它是由汇编程序定义的,程序读取 ASCII 文件,因此同一指令集的一种汇编语言并不规定另一种是什么。 x86 特别是从 intel vs AT&T 开始,然后是 gcc vs masm vs nasm 等等。自然而然地,对于 gcc 和 AT&T 以及其他故意不想与已经存在的东西一起使用的人,您如何指定这是字节读取、字读取或双字读取会有所不同。同样,如果您没有指定所需的内容,则会生成默认指令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 2022-01-09
    相关资源
    最近更新 更多