在我找到的所有文档中,都没有提到像这样的语法 offset[var+offset2]
在英特尔x86语法中,但GCC具有以下标志。
gcc -S hello.c -o - -masm=intel
该计划
#include<stdio.h>
int main(){
char c = 'h';
putchar(c);
return 0;
}
生产
.file "hello.c"
.intel_syntax noprefix
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
sub rsp, 16
mov BYTE PTR -1[rbp], 104
movsx eax, BYTE PTR -1[rbp]
mov edi, eax
call putchar@PLT
mov eax, 0
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Arch Linux 9.3.0-1) 9.3.0"
.section .note.GNU-stack,"",@progbits
我想强调一下这句话 mov BYTE PTR -1[rbp], 104
其中偏移量 -1
出现在方括号外。TBH,我只是猜测它是一个偏移,谁能指导我找到一个适当的文档来强调这一点?
下面是一个类似的问题。"方括号在x86 asm中的应用",来自IDA 其中有一条评论提到它是一个偏移量,但我真的很想得到一个合适的文档参考。
是的,这只是另一种写法。[rbp - 1]
和 -1
是一个 流离失所 在x86技术寻址模式术语中1.
GAS手册的章节 关于x86寻址模式 只说 [ebp - 4]
可能性,而不是 -4[ebp]
,但GAS是会组装的。
而用AT&T或英特尔的语法进行反汇编,则证实了它的意思。x86的寻址模式受到机器能编码的限制(引用一个内存位置的内容。(x86寻址模式)),所以在一些语法的含义上没有太多回旋余地。 (这个语法是由GCC发出的,所以我们可以放心地认为它是有效的。. 而且它的意思是相同的事情,因为 -1(%rbp)
它在AT&T语法模式下发出的)。)
脚注1:整个 rbp-1
有效地址为 偏移 seg:off地址的一部分。 在64位模式下,除了FS和GS之外,段基是固定为0的,即使在32位模式下,主流的操作系统也是采用扁平化的内存模型,所以你可以忽略段基。 我之所以指出这一点,只是因为x86术语中的 "offset "确实有与 "displacement "分开的特定技术含义,万一你在意使用的术语与Intel的手册相符呢?
由于某些原因,GCC对语法的选择取决于 -fno-pie
或不。 https:/godbolt.orgziK9jh6 (在现代GNULinux发行版上,比如你的Arch系统。-fpie
默认启用. 在Godbolt上不是)。)
启用优化后,如果你使用 volatile
强制写入堆栈变量,或者用指针做其他事情:比如说。https:/godbolt.orgz4P92Fk。. 它适用于任意的贬义,如 ptr[1 + x]
从函数args。
-fno-pie
选择 [rbp - 1]
和 [rdi+4+rsi*4]
-fpie
选择 -1[rbp]
和 4[rdi+rsi*4]
IDK为什么GCC的内部程序会根据PIE模式做出不同的选择。 没有明显的原因,也许是出于某种原因,他们只是在GCC的内部使用了不同的代码路径,或者是不同的格式字符串,他们只是碰巧做出了不同的选择。
无论是有PIE还是没有PIE,一个全局(静态存储)都会被引用为 glob[rip]
,不 [RIP + glob]
这也是支持的。 在这两种情况下,这意味着 glob
关于 RIP,其实不是RIP+符号的绝对地址。 但这是一个例外,适用于任何其他寄存器,或者没有寄存器的规则。
GAS .intel_syntax
是类似于MASM的,MASM当然也支持 symbol[register]
甚至我认为 1234[register]
. 这是更正常的位移。