Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 引用内存位置的内容。(x86寻址模式)_Assembly_X86_Masm_Addressing Mode - Fatal编程技术网

Assembly 引用内存位置的内容。(x86寻址模式)

Assembly 引用内存位置的内容。(x86寻址模式),assembly,x86,masm,addressing-mode,Assembly,X86,Masm,Addressing Mode,我有一个内存位置,其中包含一个我想与另一个字符进行比较的字符(它不在堆栈的顶部,所以我不能只popit)。如何引用内存位置的内容以便进行比较 基本上我是如何在语法上做到这一点的 有关寻址模式(16/32/64位)的更多详细讨论,请参阅第3.3节。对于符号和/或32位位置无关代码的重新定位,该指南比这个答案要详细得多。 当然,英特尔和AMD的手册中有关于ModRM(可选SIB和disp8/disp32字节)编码细节的完整章节,这清楚地说明了什么是可编码的以及存在限制的原因 另请参见:,包括间接跳转

我有一个内存位置,其中包含一个我想与另一个字符进行比较的字符(它不在堆栈的顶部,所以我不能只
pop
it)。如何引用内存位置的内容以便进行比较

基本上我是如何在语法上做到这一点的

有关寻址模式(16/32/64位)的更多详细讨论,请参阅第3.3节。对于符号和/或32位位置无关代码的重新定位,该指南比这个答案要详细得多。 当然,英特尔和AMD的手册中有关于ModRM(可选SIB和disp8/disp32字节)编码细节的完整章节,这清楚地说明了什么是可编码的以及存在限制的原因

另请参见:,包括间接跳转/调用。另请参见此答案底部的链接集合


x86(32位和64位)有多种寻址模式可供选择。它们都是这样的:

[base_reg + index_reg*scale + displacement]      ; or a subset of this
[RIP + displacement]     ; or RIP-relative: 64bit only.  No index reg is allowed
(其中比例为1、2、4或8,位移为有符号32位常量)所有其他形式(RIP relative除外)都是该类型的子集,它们省略了一个或多个组件。例如,这意味着您不需要使用归零的
索引来访问
[rsi]

在asm源代码中无论您编写东西的顺序是什么:
[5+rax+rsp+15*4+MY_ASSEMBLER\u MACRO*2]
工作正常。(所有常量的数学运算都发生在装配时,从而产生一个常量位移。)

寄存器必须彼此大小相同。与您所处的模式大小相同,除非需要额外的前缀字节。除了您可能希望忽略寄存器顶部的32位之外,窄指针很少有用,例如,不使用
movsxd
对寄存器中可能为负的32位偏移量进行签名,而是将寄存器中的32位偏移量扩展到64位指针宽度

如果需要,需要将其扩展为指针宽度的零或符号。(有时,在处理字节寄存器之前,将
rax
的高位置零是可能的,这是一种很好的方法。)


这些限制反映了机器代码中可编码的内容,与汇编语言一样。比例因子是2位移位计数。ModRM(和可选SIB)字节最多可以编码2个寄存器,但不能超过2个,并且没有任何减去寄存器的模式,只有加法。任何寄存器都可以是基址。除ESP/RSP之外的任何寄存器都可以是索引。有关编码详细信息,请参阅,例如为什么
[rsp]
总是需要SIB字节

除了使用
e/rsp*scale
的子集(显然在总是在
esp
中保留堆栈内存指针的“普通”代码中是无用的),一般情况下的每个可能子集都是可编码的

通常,编码的代码大小为:

  • 1B用于单寄存器模式(mod/rm(模式/寄存器或存储器))
  • 2B用于两种寄存器模式(mod/rm+SIB(刻度索引基)字节)
  • 位移可以是0、1或4字节(符号扩展为32或64,具体取决于地址大小)。因此,从
    [-128到+127]
    的置换可以使用更紧凑的
    disp8
    编码,比
    disp32
    节省3个字节
ModRM始终存在,其位表示SIB是否也存在。 与disp8/disp32类似。代码大小异常:

  • [reg*scale]
    本身只能用32位位移(当然可以是零)进行编码。智能汇编程序通过将
    leaeax[rdx*2]
    编码为
    leaeax[rdx+rdx]
    来解决这个问题,但这种技巧只适用于按2的比例扩展。无论哪种方式,除了ModRM之外,还需要SIB字节

  • 不可能将
    e/rbp
    r13
    编码为没有位移字节的基址寄存器,因此
    [ebp]
    编码为
    [ebp+字节0]
    。使用
    ebp
    作为基址寄存器的无位移编码意味着没有基址寄存器(例如对于
    [disp+reg*scale]

  • [e/rsp]
    即使没有索引寄存器,也需要SIB字节。(无论是否有位移)。mod/rm编码将指定
    [rsp]
    ,这意味着有一个SIB字节

有关特殊情况的详细信息,请参阅英特尔ref手册中的表2-5及相关章节。(它们在32位和64位模式下是相同的。添加RIP相对编码与任何其他编码都没有冲突,即使没有REX前缀。)

就性能而言,仅仅为了获得较小的x86机器代码而花费额外的指令通常是不值得的。在带有uop缓存的英特尔CPU上,它比一级I$小,是一种更宝贵的资源。最小化融合域UOP通常更为重要


它们是如何使用的 (这个问题被标记为MASM,但其中一些答案谈到了NASM版本的Intel语法,特别是在x86-64 RIP相对寻址不同的地方。不包括AT&T语法,但请记住,这只是相同机器代码的另一种语法,因此限制是相同的。)

此表与可能寻址模式的硬件编码不完全匹配,因为我区分使用标签(例如,全局或静态数据)与使用小的恒定位移。因此,我将介绍硬件寻址模式+链接器对符号的支持

(注意:当源代码是字节时,通常需要
movzx-eax,byte[esi]
movsx
,但
mov-al,byte_-src
进行汇编,在旧代码中很常见,合并到eax/RAX的低字节中。请参阅和)

如果您有一个
int*
,如果您有一个元素索引而不是字节偏移量,则通常会使用比例因子按数组元素大小来缩放索引。(首选字节偏移或
mov       dword [rsi + 10], 123   ; NASM
mov   dword ptr [rsi + 10], 123   ; MASM and GNU .intex_syntax noprefix

movl      $123, 10(%rsi)         # GNU(AT&T): operand size from mnemonic suffix
+------------------------+----------------------------+-----------------------------+
| Mode                   | Intel                      | AT&T                        |
+------------------------+----------------------------+-----------------------------+
| Absolute               | MOV EAX, [0100]            | movl           0x0100, %eax |
| Register               | MOV EAX, [ESI]             | movl           (%esi), %eax |
| Reg + Off              | MOV EAX, [EBP-8]           | movl         -8(%ebp), %eax |
| Reg*Scale + Off        | MOV EAX, [EBX*4 + 0100]    | movl   0x100(,%ebx,4), %eax |
| Base + Reg*Scale + Off | MOV EAX, [EDX + EBX*4 + 8] | movl 0x8(%edx,%ebx,4), %eax |
+------------------------+----------------------------+-----------------------------+
MOV EAX, [ EBP - 4 ]