【问题标题】:Assembly difference between [var], and var[var] 和 var 之间的汇编区别
【发布时间】:2017-01-21 07:25:01
【问题描述】:

我正在学习 Assembler,并且我实际上对 [variable]variable 之间的区别一无所知。正如教程所说,两者都是指针,那么这有什么意义呢?为什么我必须在[] 之前使用type Identifier? 我的汇编程序:nasm x86_64 running on Linux--> Ubuntu

【问题讨论】:

  • 你以前用过C吗?还是其他系统编程语言? (如果我们了解您已有的知识,它将帮助我们给出您可以理解的答案)
  • 你用的是什么汇编程序?你正在学习什么类型的组装?种类很多。
  • 我可以编程 pascal 和 c++。我知道如何使用指针
  • 我正在使用 64 位版本的 Nasm 汇编器。对不起,我没有告诉:)
  • @MichaelPetch:这似乎更多的是关于符号名称而不是寄存器。那里的答案没有提到mov eax, sym 为mov-immediate。它们高度相关,但我认为它们都需要相互链接才能完整回答这两个问题。由于简单,我认为这个问题可能是更好的规范问题,但是 IDK.我在x86 addressing modes answer 中提到了一些 NASM 与 MASM 的内容,它也涵盖了寄存器直接(非内存)操作数。

标签: assembly x86 nasm


【解决方案1】:

在 x86 Intel 语法中,[expression] 表示地址 expression 处的内存内容。
(除非在 MASM 中 expression 是数字文字或 equ 没有寄存器的常量,then it's still an immediate


expression 不带括号取决于您使用的汇编程序。

NASM 风格(NASM、YASM):

mov eax,variable      ; moves address of variable into eax
lea eax,[variable]    ; equivalent to the previous one (LEA is exception)
mov eax,[variable]    ; loads content of variable into eax

MASM 风格(也是 TASM 甚至 GCC/GAS .intel_syntax noprefix):

mov eax,variable      ; load content of variable (for lazy programmers)
mov eax,OFFSET variable   ; address of variable
lea eax,[variable]    ; address of variable
mov eax,[variable]    ; content of variable

GAS(AT&T 语法):这不是 Intel 语法,请参阅 the AT&T tag wiki。 GAS 也使用不同的指令(例如 .byte 而不是 db),即使在 .intel_syntax 模式下也是如此。


在所有情况下,variable 是符号标记内存中特定位置的别名,标签出现的地方。所以:

variable1  db  41
variable2  dw  41
label1:

在符号表中生成三个符号,variable1variable2label1

当您在代码中使用它们中的任何一个时,例如mov eax,<symbol>,它没有任何信息是由dbdw 定义的还是作为标签定义的,所以当您使用@ 时它不会给您任何警告987654344@(覆盖定义的第一个字节之外的 3 个字节)。

它只是内存中的一个地址。

(在 MASM 中除外,其中数据部分中标签后的 db 或 dd 确实将大小与其“变量名称”相关联。)


类型标识符在无法从指令操作数本身推断出类型时在大多数汇编程序中是必需的。

mov [ebx],eax ; obviously 32 bits are stored, because eax is 32b wide
mov [ebx],1   ; ERROR: how "wide" is that immediate value 1?
mov [ebx],WORD 1 ; NASM syntax (16 bit value, storing two bytes)
mov WORD [ebx],1 ; NASM syntax (16 bit value, storing two bytes)
mov WORD PTR [ebx],1 ; MASM/TASM syntax

【讨论】:

  • GAS .intel_syntax noprefix 在这方面很像 MASM,您使用 OFFSET 来获取地址作为立即数,而一个裸符号名称是一个负载。 (即使是.set sym, 1234,因为它是哪种符号并没有魔法)
  • 另外,您在回答这个问题之前是否搜索过重复项?这不可能是第一次被问和回答这个问题:(如果有旧版本的答案更差,我们可以将它们作为副本关闭。
  • @PeterCordes:不。我现在试过了,但失败了很多次,用 SO 搜索搜索 [] 字符有点徒劳(虽然我不知道 SO 搜索引擎的任何扩展功能,也许有可能)。
  • 显然你 can search for code:[] 在代码块中寻找它。也许我会回到这个并自己寻找副本,可能会搜索“括号”之类的东西。
  • 可以在@RossRidge 对类似(但不重复)问题的回答中找到对 MASM 语法及其特性的更深入讨论:stackoverflow.com/a/25130189/3857942
【解决方案2】:

既然您已经了解 C++,我将通过向您展示这些表达式的 C 等价物来回答。

当你写作时

[variable]

在汇编中,相当于

*variable

在 C 中。也就是说,将 variable 视为指针并取消引用该指针 - 获取指针指向的值。

同样,“类型标识符”就像将指针转换为不同的类型:

ASM:
    dword ptr [variable]
C:
    *((uint32_t*) variable)

ASM:
    word ptr [variable]
C:
    *((uint16_t*) variable)

我希望这可以帮助您理解这些表达的含义。


(此部分指的是一个已从原始问题中删除的附录)

我不完全确定您在“转换为 ascii”时遇到了什么问题,但我怀疑您只是对它在输出中的视觉呈现方式或其他内容感到困惑。

例如,如果您有这样的代码:

myInteger db 41
mov AL, byte ptr [myInteger]

mov 会将值41 从内存复制到AL 寄存器中。数字 41 恰好是 ) 字符的 ascii 表示,但这并没有改变任何东西。该值是被解释为 ascii 字符还是整数取决于您,因为它们是相同的值。

【讨论】:

  • mov 会将值 41 从内存复制到 AL 寄存器中。数字 41 恰好是 ) 字符的 ascii 表示,但这并没有改变任何东西。该值是解释为 ascii 字符还是整数取决于您,因为它们是相同的值。是的,但我希望用户看到'41'。我怎样才能做到这一点?顺便说一句:很好的答案
  • @TheFrenchPlaysHdMicraftn:您必须生成两个(或更多)字节,它们将保存字符“4”和“1”(恰好是 0x34 和 0x31)的 ASCII 值。因此,一种可能性是采用41 并继续将其除以10 直到零,然后用余数从末尾构建字符串(OR remainder,0x30 以获取ASCII 数字)。
  • @TheFrenchPlaysHdMicraftn 您需要使用数字到字符串的转换函数,例如 C 标准库中的 sprintf。我不确定在组装中最简单的方法是什么。 C 库函数是否可用取决于您的汇编程序与哪些库链接。也许谷歌“sprintf组装”(或者你可以使用我上面提到的算法Ped7g)
  • 好的。为了计算它们,我不需要转换它们,对吗?
  • @TheFrenchPlaysHdMicraftn “计算它们”是指“与它们进行算术运算”吗?
【解决方案3】:

一个使用寄存器和指针的小例子:

mov eax, 10 表示:将值 10 移入寄存器 EAX。在这种情况下,EAX 仅用于存储某些内容。 EAX 包含的内容对程序员来说根本不重要,因为无论如何它都会被删除。

mov [eax], 10 表示:将值 10移入 EAX 寄存器中存储的地址。在这种情况下,存储在 EAX 中的值对我们来说很重要,因为它是一个指针,这意味着我们必须去 EAX 寄存器查看其中包含的内容,然后我们使用这个值作为地址访问。

使用指针时需要两个步骤:

  1. 转到 EAX,查看它包含的值(例如 EAX = 0xBABA);

  2. 转到 EAX 指向的地址(在我们的例子中为 0xBABA)并在其中写入 10。

当然,指针不一定和寄存器一起使用,这个小例子只是为了说明它是如何工作的。

【讨论】:

  • 好的,这很有帮助。多谢。但是对于 Integer-ASCII 问题(在顶部描述):你有线索吗?
  • 这是一个 QA 站点,而不是一个论坛。这意味着通常每个线程都有一个问题。我强烈建议您编辑您的问题并删除第二个问题,然后使用新问题打开一个新线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多