[var] 和 var 之间的汇编区别
Assembly difference between [var], and var
我正在学习汇编程序,现在我对 [variable]
和 variable
之间的区别一无所知。正如教程所说,两者都是指针,那么这样做有什么意义呢?为什么我必须在 []
之前使用 type Identifier
?
我的汇编器:nasm x86_64 running on Linux--> Ubuntu
在 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:
将三个符号生成符号 table、variable1
、variable2
和 label1
。
当你在代码中使用它们中的任何一个时,比如 mov eax,<symbol>
,它没有信息是被 db
或 dw
定义还是作为标签,所以它不会当你做 mov [variable1],ebx
时给你任何警告(覆盖定义的第一个字节之外的 3 个字节)。
它只是内存中的一个地址。
(在 MASM 中除外,其中数据部分中标签后的 db 或 dd 确实与其关联的大小 "variable name"。)
当无法从指令操作数本身推导出类型时,类型标识符仅在大多数汇编器中是必需的。
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
一个使用寄存器和指针的小例子:
mov eax, 10
表示:将值 10 移入寄存器 EAX。在这种情况下,EAX 仅用于存储一些内容。 EAX 包含什么对程序员来说根本不重要,因为它无论如何都会被擦除。
mov [eax], 10
表示:将值10移动到EAX寄存器中存储的地址中。在这种情况下,存储在 EAX 中的值对我们来说很重要,因为它是一个 指针 ,这意味着我们必须去 EAX 寄存器看看包含什么,然后我们使用这个值作为访问地址。
使用指针时需要两个步骤:
转到 EAX,看看它包含什么值(例如 EAX = 0xBABA);
转到EAX指向的地址(在我们的例子中是0xBABA)并在其中写入10。
当然,指针不一定和寄存器一起使用,这个小例子只是为了解释它是如何工作的。
既然您已经了解 C++,我将通过向您展示这些表达式的 C 等价物来回答。
写的时候
[variable]
在汇编中,相当于
*variable
在 C 中。也就是说,将 variable
视为指针并取消引用该指针——获取指针指向的值。
类似地,'type identifiers' 就像将指针转换为不同的类型:
ASM:
dword ptr [variable]
C:
*((uint32_t*) variable)
ASM:
word ptr [variable]
C:
*((uint16_t*) variable)
我希望这可以帮助您理解这些表达式的含义。
(本节引用了已从原始问题中删除的附录)
我不完全确定你在使用 'conversion to ascii' 时遇到了什么问题,但我怀疑你只是对它在输出中的视觉呈现方式感到困惑。
例如,如果您有这样的代码:
myInteger db 41
mov AL, byte ptr [myInteger]
mov
会将值 41
从内存复制到 AL
寄存器中。数字 41
恰好是 )
字符的 ascii 表示,但这并没有改变任何东西。该值是被解释为 ascii 字符还是整数由您决定,因为它们是相同的值。
我正在学习汇编程序,现在我对 [variable]
和 variable
之间的区别一无所知。正如教程所说,两者都是指针,那么这样做有什么意义呢?为什么我必须在 []
之前使用 type Identifier
?
我的汇编器:nasm x86_64 running on Linux--> Ubuntu
在 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:
将三个符号生成符号 table、variable1
、variable2
和 label1
。
当你在代码中使用它们中的任何一个时,比如 mov eax,<symbol>
,它没有信息是被 db
或 dw
定义还是作为标签,所以它不会当你做 mov [variable1],ebx
时给你任何警告(覆盖定义的第一个字节之外的 3 个字节)。
它只是内存中的一个地址。
(在 MASM 中除外,其中数据部分中标签后的 db 或 dd 确实与其关联的大小 "variable name"。)
当无法从指令操作数本身推导出类型时,类型标识符仅在大多数汇编器中是必需的。
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
一个使用寄存器和指针的小例子:
mov eax, 10
表示:将值 10 移入寄存器 EAX。在这种情况下,EAX 仅用于存储一些内容。 EAX 包含什么对程序员来说根本不重要,因为它无论如何都会被擦除。
mov [eax], 10
表示:将值10移动到EAX寄存器中存储的地址中。在这种情况下,存储在 EAX 中的值对我们来说很重要,因为它是一个 指针 ,这意味着我们必须去 EAX 寄存器看看包含什么,然后我们使用这个值作为访问地址。
使用指针时需要两个步骤:
转到 EAX,看看它包含什么值(例如 EAX = 0xBABA);
转到EAX指向的地址(在我们的例子中是0xBABA)并在其中写入10。
当然,指针不一定和寄存器一起使用,这个小例子只是为了解释它是如何工作的。
既然您已经了解 C++,我将通过向您展示这些表达式的 C 等价物来回答。
写的时候
[variable]
在汇编中,相当于
*variable
在 C 中。也就是说,将 variable
视为指针并取消引用该指针——获取指针指向的值。
类似地,'type identifiers' 就像将指针转换为不同的类型:
ASM:
dword ptr [variable]
C:
*((uint32_t*) variable)
ASM:
word ptr [variable]
C:
*((uint16_t*) variable)
我希望这可以帮助您理解这些表达式的含义。
(本节引用了已从原始问题中删除的附录)
我不完全确定你在使用 'conversion to ascii' 时遇到了什么问题,但我怀疑你只是对它在输出中的视觉呈现方式感到困惑。
例如,如果您有这样的代码:
myInteger db 41
mov AL, byte ptr [myInteger]
mov
会将值 41
从内存复制到 AL
寄存器中。数字 41
恰好是 )
字符的 ascii 表示,但这并没有改变任何东西。该值是被解释为 ascii 字符还是整数由您决定,因为它们是相同的值。