关于 AT&T x86 语法设计的问题

2024-03-05

  1. 谁能向我解释为什么 AT&T 语法中的每个常量前面都有一个“$”?
  2. 为什么所有寄存器都有“%”?
  3. 这是否只是又一次试图让我做很多蹩脚的打字?
  4. 另外,我是唯一一个发现:16(%esp)相比之下确实违反直觉[esp+16]?
  5. 我知道它编译成同样的东西,但为什么有人想在不需要的情况下输入大量“$”和“%”? - 为什么 GNU 选择这个语法作为默认语法?
  6. 另外,为什么 at&t 语法中的每条指令前面都有一个:l? - 我确实知道它的操作数大小,但是为什么不让汇编器弄清楚呢? (我是否想对不是那么大小的操作数执行 movl 操作?)
  7. 最后一件事:为什么 mov 参数要颠倒?

不是吗more逻辑上认为:

eax = 5
mov eax, 5

其中 at&t 是:

mov 5, eax
5 = a (? wait what ?)

笔记: 我并不是想恶搞。我只是不明白他们所做的设计选择,我试图了解他们为什么这样做。


1、2、3 和 5:这种表示法有些多余,但我发现在汇编开发时这是一件好事。冗余有助于阅读。关于“让汇编器弄清楚”的观点很容易变成“让阅读代码的程序员弄清楚”,而我不喜欢当我是一个阅读者时。编程不是只写任务;即使程序员本人也必须阅读自己的代码,语法冗余也有很大帮助。

另一点是“%”和“$”意味着可以在不破坏向后兼容性的情况下添加新寄存器:添加没有问题,例如,一个名为xmm4,因为它将被写成%xmm4,不能与名为的变量混淆xmm4写时不带“%”。

至于打字量:通常,在汇编编程时,瓶颈是大脑,而不是手。如果“$”和“%”让你放慢速度,那么要么你的思考速度比通常被认为是人类可行的速度快得多,要么更可能的是,你手头的任务太机械化,不应该在集会;它应该留给自动代码生成器,即俗称的“C 编译器”。

添加“l”后缀是为了处理汇编器“无法”弄清楚的某些情况。例如,这段代码:

mov  [esp], 10

是不明确的,因为它不告诉你是要写入一个值为 10 的字节,还是一个具有相同数值的 32 位字。 Intel 语法要求:

mov  byte ptr [esp], 10

当你想到这一点时,这是相当丑陋的。 AT&T 的人们想要做出更理性的事情,所以他们想出了:

movb   $10, (%esp)

他们更喜欢系统化,并带有“b”(或“l”或“w”)后缀到处。请注意,后缀并不总是required。例如,你可以写:

mov   %al, (%ebx)

让 GNU 汇编器“弄清楚”既然你正在谈论 '%al',那么移动是针对单个字节的。真的行 !然而,我仍然发现指定大小更好(这确实对读者有帮助,程序员本人是他自己代码的首要读者)。

对于“反转”来说:恰恰相反。 Intel 语法模仿 C 语言中的情况,其中值在右侧计算,然后写入左侧。因此,考虑到阅读是从左到右进行的,所以写入是从右到左,即“相反”方向。 AT&T 语法恢复为“正常”方向。至少他们是这么认为的;因为无论如何他们决定使用自己的语法,所以他们认为可以按照他们认为的“正确的顺序”使用操作数。这主要是一种惯例,但并非不合逻辑。 C 约定模仿数学符号,只不过数学是关于defining值(“让 x 为值 5”)而不是关于指派值(“我们写下值 5into一个名为“x”的槽”)。AT&T 的选择是有道理的。只有当您将 C 代码转换为汇编语言时才会感到困惑,而这项任务通常应该留给 C 编译器。

从历史的角度来看,问题 5 的最后一部分很有趣。 x86 的 GNU 工具遵循 AT&T 语法,因为当时他们试图在 Unix 世界占据一席之地(“GNU”的意思是“GNU is Not Unix”)并与 Unix 工具竞争; Unix 处于 AT&T 的控制之下。这是在 Linux 甚至 Windows 3.0 之前的时代; PC是16位系统。 Unix 使用 AT&T 语法,因此 GNU 使用 AT&T 语法。

那么好问题是:为什么 AT&T 发现发明自己的语法是明智之举?如上所述,他们有一些理由,但也不无道理。当然,使用自己的语法的代价是它限制了互操作性。在那些日子里,C 编译器或汇编器作为一个单独的工具并没有真正的意义:在 Unix 系统中,它们应该由操作系统供应商提供。此外,Intel 在 Unix 世界中并不是一个大玩家。大型系统大多使用VAX或Motorola 680x0衍生品。没有人想到二十年后 MS-Dos PC 会成为桌面和服务器领域的主导架构。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于 AT&T x86 语法设计的问题 的相关文章

  • 推送 64 位 intel osx

    我想将 64 位地址压入堆栈 如下所示 asm pushq 0x1122334455667788 但我得到编译错误 我只能按以下方式推送 asm pushq 0x11223344 有人可以帮助我理解我的错误吗 我是装配新手 所以如果我的问题
  • 汇编语言中的全局_start是什么?

    这是我的汇编级代码 section text global start start mov eax 4 mov ebx 1 mov ecx mesg mov edx size int 0x80 exit mov eax 1 int 0x80
  • ARM 调用约定是否允许函数不将 LR 存储到堆栈中?

    正如标题所示 我在理解 ARM 架构的调用约定时遇到问题 特别是 我仍然很难知道当你调用子程序时 LR 寄存器会发生什么 我认为 当您进入子程序时 处理 LR 寄存器的最明显 最安全的方法是将其存储到堆栈中 但该行为没有出现在文档中 因此我
  • DASM 汇编器中的 ASCII 到 C64 屏幕代码

    我正在通过 C64 模拟器学习 6502 micro 的汇编 目前正在尝试将字符串输出到屏幕 这是我的代码 processor 6502 org 1000 ldx 00 using x register as column counter
  • 使用 gdb 调试反汇编库

    在Linux和Mac OS X中可以使用strapi和next来调试应用程序而无需调试信息 在 Mac OS X 上 gdb 显示在库内部调用的函数 尽管有时会在每个 stepi 指令中推进多个汇编程序指令 在 Linux 上 当我进入动态
  • 编写 AMD64 SysV 程序集时使用哪些寄存器作为临时寄存器?

    我正在使用实现一个功能cpuid根据 AMD64 SysV ABI 进行组装 我需要在函数本身中使用 2 个临时寄存器 第一个用于累积返回值 第二个用作计数器 我的功能目前如下所示 zero argument function some c
  • 在 REP MOVSW 之前 PUSH CS / POP DS 的目的是什么?

    为什么在下面的代码中我们压入代码段 PUSH CS 然后将其弹出到数据段 POP DS 我将这些行明确指定为 line1 和 line2 请告诉我 MOVSW 在这里是如何工作的 IF HIGHMEMORY PUSH DS MOV BX D
  • 为什么我可以使用 ret 退出 main?

    我即将弄清楚程序堆栈到底是如何设置的 我了解到用以下方式调用该函数 call pointer 实际上等同于 mov register pc programcounter add register 1 where 1 is one instr
  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们
  • 遍历内存编辑每个字节

    我正在编写汇编代码 提示用户输入一串小写字符 然后输出包含所有大写字符的相同字符串 我的想法是迭代从特定地址开始的字节 并从每个字节中减去 20H 将小写变为大写 直到到达具有特定值的字节 我对 Assembly 相当缺乏经验 所以我不确定
  • 为什么 SSE 对齐读取 + 随机播放在某些 CPU 上比未对齐读取慢,而在其他 CPU 上则不然?

    在尝试优化有限差分代码所需的未对齐读取时 我更改了未对齐的负载 如下所示 m128 pm1 mm loadu ps H k 1 进入这个对齐的读取 随机播放代码 m128 p0 mm load ps H k m128 pm4 mm load
  • AVX512 掩码寄存器(k1...k7)的 GNU C 内联 asm 输入约束?

    AVX512 为其算术命令引入了 opmask 功能 一个简单的例子 上帝螺栓 org https godbolt org z P7xWD8 include
  • orpd等SSE2指令有什么意义?

    The orpd指令是 压缩双精度浮点值的按位逻辑或 这不是做完 全相同的事情吗por 按位逻辑或 如果是这样 拥有它还有什么意义呢 请记住 SSE1orps https www felixcloutier com x86 orps首先 实
  • CALL指令是否总是将EIP指向的地址压入堆栈?

    x86架构中函数调用时是否存在返回地址不入栈的情况 No CALL根据定义 将在跳转到目标地址之前将返回地址压入堆栈 该返回地址是EIP or RIP sizeof call instruction 通常为 5 个字节 英特尔 64 和 I
  • NASM 轮班操作员

    您将如何在寄存器上进行 NASM 中的位移位 我读了手册 它似乎只提到了这些操作员 gt gt lt lt 当我尝试使用它们时 NASM 抱怨移位运算符处理标量值 您能解释什么是标量值并举例说明如何使用 gt gt and lt lt 另外
  • Visual Studio 2017 上的简单装配程序

    386 model flat c stack 100h printf PROTO arg1 Ptr Byte data msg1 byte Hello World 0Ah 0 code main proc INVOKE printf ADD
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • 使用 Easy 68K (68000) 组装范围内的随机数

    我正在使用 Easy 68K 模拟器创建一个简单的黑杰克游戏 需要使用随机数来分配牌 我的牌必须在 2 到 11 的范围内 我似乎每次都得到相同的数字 但它不在我预期的范围内 我的卡值需要以 D3 结束 因此我有以下随机数代码 CLR L
  • 68HC11计算sin(x)的汇编代码

    68HC11 使用泰勒级数或查找表计算正弦值的汇编代码是什么 显示值只能是整数 查找表如何工作 在这种情况下 如何使用它来实现泰勒级数 http en wikipedia org wiki Taylor series 如果您正在寻找浮点解决
  • 寄存器寻址模式与直接寻址模式

    我在试卷中遇到过这个问题 它指出 哪种给定的寻址模式更快 为什么 寄存器寻址方式 直接寻址方式 现在根据我的说法 寄存器寻址模式应该更快 因为寄存器是计算机中最快的存储位置 这是正确答案吗 请帮忙 谢谢 两种寻址模式之间的区别是 地址的来源

随机推荐