例如,如果我们编写一个简单的hello world类型程序,.data部分可能包含以下内容:
section .data
msg     db      'Enter something: '
len     equ     $ - msg
这个例子中的$代表什么,为什么$ - msg等于字符串的长度?
16(%esp)真的违反直觉[esp+16]吗?是不是更合乎逻辑:
eax = 5
mov eax, 5
at at&t是:
mov 5, eax
5 = a (? wait what ?)
注意:我不是想乱跑.我只是不明白他们所做的设计选择,我试图了解他们为什么做了他们所做的.
考虑 x64 Intel 程序集中的以下变量引用,其中变量a在.data节中声明:
mov eax, dword ptr [rip + _a]
我很难理解这个变量引用是如何工作的。既然a是对应于变量运行时地址的符号(带重定位),如何[rip + _a]解引用正确的内存位置a?事实上,rip保存当前指令的地址,它是一个大的正整数,所以加法会导致错误的地址a?
相反,如果我使用 x86 语法(非常直观):
mov eax, dword ptr [_a]
,我收到以下错误:64 位模式不支持 32 位绝对寻址。
有什么解释吗?
  1 int a = 5;
  2 
  3 int main() {
  4     int b = a;
  5     return b;
  6 }   
编译gcc -S -masm=intel abs_ref.c -o abs_ref::
  1     .section    __TEXT,__text,regular,pure_instructions
  2     .build_version macos, 10, 14
  3 …为什么这段代码没有设置temp为1?我该怎么做呢?
int temp;
__asm__(
    ".intel_syntax;"
    "mov %0, eax;"
    "mov eax, %1;"
    ".att_syntax;"
    : : "r"(1), "r"(temp) : "eax");
printf("%d\n", temp);
我正在跟踪一些x86代码进行分配,我想知道究竟"cmpl"究竟是什么以及如何预测"jne"是否会被满足.
80484bf:    83 7d f0 07             cmpl   $0x7,-0x10(%ebp)
80484c3:    75 16                   jne    80484db
此外,这使用Intel语法.
谢谢.
我读过这个页面,其中包含了针对GAS的英特尔和AT&T语法之间的差异的良好列表,但它没有涵盖仅指定具有位移的地址的情况.
在这里,我用AT&T语法组装了四行:
                         .text
0000 48C7C008000000      mov    $8, %rax
0007 488B042508000000    mov    (8), %rax
000f 4889F0              mov    %rsi, %rax
0012 488B06              mov    (%rsi), %rax
正如预期的那样,前两行是不同的.第一个将立即值8移动到rax中,第二个将地址8的内容移动到rax中.但是使用Intel语法我会得到以下奇怪的行为:
                         .text
                         .intel_syntax
0000 48C7C008000000      mov    %rax, 8
0007 48C7C008000000      mov    %rax, [8]
000e 4889F0              mov    %rax, %rsi
0011 488B06              mov    %rax, [%rsi]
这里第一行和第二行汇编到相同的机器代码!首先我认为方括号是错误的,所以我在测试中添加了第三行和第四行,并且方括号对于内存寻址至少在涉及寄存器时起作用.
我读过的所有文档都显示了至少有一个基址或索引寄存器的内存寻址示例,有时还有一个比例和位移,但从不仅仅是位移.
我确实有使用NASM汇编程序的英特尔语法经验,它可以区分mov rax, 8和mov rax, [8].
这是GAS中的错误吗?或者如果没有,我如何指定NASM的等效物mov rax, [8]?
我意识到指定一个仅位移地址可能并不常见,但我希望通过这种语法完全理解所有内存寻址形式.
英特尔和AT&T语法中内存寻址的一般形式如下:
[base + index*scale + disp]
disp(base, index, scale)
我的问题如下:
base和index任意注册?scale采用什么值,是1,2,4和8(默认值为1)?index和disp可互换的(唯一的区别index是寄存器disp是一个常数)?我正在学习如何创建组装和链接的真实模式程序:
我使用没有指定前缀的Intel语法 .intel_syntax noprefix
我想将字符串的地址加载到SI寄存器中.我知道,如何在NASM中引用内存位置,但是当我在GNU汇编程序代码中执行相同操作时,它只将字符串的WORD移动到寄存器而不是标签的地址.
我的代码是:
.code16
.intel_syntax noprefix
mov cx, 11
mov si, name
mov di, 0x7E00
push di
rep cmpsb
pop di
je LOAD
当我用GCC编译它时,我可以在调试器中看到处理器执行的操作:
mov si, WORD ptr ds:0x7d2d
但我想将字符串的地址移入寄存器,而不是它指向的数据.
我还尝试在名称周围放置方括号,如下所示:
.code16
.intel_syntax noprefix
mov cx, 11
mov si, [name]
mov di, 0x7E00
push di
rep cmpsb
pop di
je LOAD
它没有任何区别.
从NASM我知道这个汇编代码有效:
mov si, name
NASM将生成将地址移动name到寄存器SI的指令.
我的问题:有没有办法强制GCC使用带有无前缀的英特尔语法将符号的地址加载到寄存器中?
我有以下代码,可以用 gcc 命令很好地编译gcc ./example.c。程序本身调用函数“add_two”,它只是将两个整数相加。要在扩展汇编指令中使用 intel 语法,我需要首先切换到 intel,然后再切换回 AT&T。根据 gcc 文档,可以使用gcc -masm=intel ./exmaple.
每当我尝试使用 switch 编译它时,-masm=intel它都不会编译,我不明白为什么?我已经尝试删除该指令,.intel_syntax但它仍然无法编译。
#include <stdio.h>
int add_two(int, int);
int main(){
     int src = 3;
     int dst = 5;
     printf("summe = %d \n", add_two(src, dst));
     return 0;
}
int add_two(int src, int dst){
    int sum;
    asm (
        ".intel_syntax;"  //switch to intel syntax
        "mov %0, %1;"
        "add %0, %2;"
        ".att_syntax;"  //switch to at&t syntax
        : "=r" (sum) //output
        : "r" (src), "r" …我想知道如何在Intel语法的某些指令中将标签名称与寄存器名称区分开。例如,call rdx通常意味着间接跳转,但是如果我们rdx在同一程序集文件中有标签怎么办?我认为可以将其解释为直接跳转到rdx。是否有任何符号告诉汇编器是哪个?