Assembly [var]和var之间的程序集差异

Assembly [var]和var之间的程序集差异,assembly,x86,nasm,Assembly,X86,Nasm,我正在学习汇编程序,现在我对[variable]和variable之间的区别一无所知。正如教程所说,两者都是指针,那么这有什么意义呢?为什么我必须在[]之前使用类型标识符? 我的汇编程序:nasm x86\u 64在Linux-->Ubuntu上运行在x86英特尔语法中[expression]表示地址expression处的内存内容 (在MASM中,当表达式是数值文字或eq常量且无寄存器时除外) 表达式不带括号取决于您使用的汇编程序 NASM风格(NASM,YASM): MASM风格(也包括T

我正在学习汇编程序,现在我对
[variable]
variable
之间的区别一无所知。正如教程所说,两者都是指针,那么这有什么意义呢?为什么我必须在
[]
之前使用
类型标识符

我的汇编程序:
nasm x86\u 64在Linux-->Ubuntu上运行
在x86英特尔语法中
[expression]
表示地址
expression
处的内存内容
(在MASM中,当
表达式
是数值文字或
eq
常量且无寄存器时除外)


表达式
不带括号取决于您使用的汇编程序

NASM风格(NASM,YASM):


MASM风格(也包括TASM,甚至GCC/GAS
。英特尔语法noprefix
):

GAS(AT&T语法):它不是Intel语法,请参阅。GAS还使用不同的指令(如
.byte
而不是
db
),即使在
.intel\u语法
模式下也是如此


在所有情况下,
变量
都是标记内存中标签出现的特定位置的符号别名。因此:

variable1  db  41
variable2  dw  41
label1:
在符号表中生成三个符号,
variable1
variable2
label1

当您在代码中使用它们中的任何一个时,例如
mov eax,
,它不知道它是由
db
dw
定义的,还是作为标签的,因此当您使用
mov[variable1],ebx
(在定义的第一个字节之外覆盖3个字节)时,它不会给您任何警告

它只是内存中的一个地址

(在MASM中除外,在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

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

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

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

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

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

  • 转到EAX指向的地址(在我们的例子中是0xBABA)并在其中写入10


  • 当然,指针不一定要用寄存器,这个小例子只是解释它是如何工作的。

    < P>既然你已经知道C++,我将通过向你展示这些表达式的C等价物来回答。 当你写作时

    [variable]
    
    在汇编中,它相当于

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

    类似地,“类型标识符”类似于将指针投射到不同的类型:

    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字符还是整数取决于您,因为它们是相同的值。

    您以前使用过C吗?还是其他系统编程语言?(如果我们了解了您先前的知识,它将帮助我们给出您可以理解的答案)您使用的是什么汇编程序?您正在学习什么类型的装配?有很多种,我可以编程PASCAL和C++。我知道如何使用指针,我正在使用64位版本的Nasm汇编程序。对不起,我没有告诉:)@MichaelPetch:这一个似乎更多的是关于符号名而不是寄存器。这里的答案没有提到mov eax,sym作为mov immediate。他们是高度相关的,但我认为他们都需要相互联系,以获得对这两个问题的完整答案。我认为这个问题可能是更好的规范问题,因为简单,但是IDK。我在我的文章中提到了一些NASM与MASM的内容,其中也包括寄存器直接(非内存)操作数。好的,这很有帮助。谢谢。但是对于整数ASCII问题(在顶部描述):你有线索吗?这是一个QA网站,不是一个论坛。这意味着通常每个线程有一个问题。我强烈建议您编辑您的问题并删除第二个问题,然后用新问题打开一个新线程。mov将把值41从内存复制到AL寄存器中。数字41恰好是字符的ascii表示形式,但这不会改变任何东西。值是解释为ascii字符还是整数取决于您,因为它们是相同的值。是的,但我想让用户看到'41'。我该怎么做?顺便说一句:很好answer@TheFrenchPlaysHdMicraftn:您必须生成两个(或更多)字节,这些字节将保存字符“4”和“1”(正好是0x34和0x31)的ASCII值。因此,一种可能性是取
    41
    并将其除以10直到零,用余数(
    或余数,0x30
    获得ASCII数字)从头到尾构建字符串
    ASM:
        dword ptr [variable]
    C:
        *((uint32_t*) variable)
    
    ASM:
        word ptr [variable]
    C:
        *((uint16_t*) variable)
    
    myInteger db 41
    mov AL, byte ptr [myInteger]