gpt4 book ai didi

assembly - 设计 AT&T 汇编语法的最初原因是什么?

转载 作者:行者123 更新时间:2023-12-04 06:32:24 25 4
gpt4 key购买 nike

在 x86 或 amd64 上使用汇编指令时,程序员可以使用“Intel”(即 nasm 编译器)或“AT&T”(即 gas 编译器)汇编语法。 “Intel”语法在 Windows 上更流行,但“AT&T”在 UNIX(类)系统上更流行。

但是 Intel 和 AMD 手册,即芯片创建者创建的手册,都使用“Intel”语法。

我想知道,“AT&T”语法设计背后的最初想法是什么?远离处理器创建者使用的符号有什么好处?

最佳答案

长期以来,UNIX 是在 PDP-11 上开发的,PDP-11 是来自 DEC 的 16 位计算机,具有相当简单的指令集。几乎每条指令都有两个操作数,每个操作数都可以具有以下八种寻址模式之一,此处以 MACRO 16 汇编语言显示:

0n  Rn        register
1n (Rn) deferred
2n (Rn)+ autoincrement
3n @(Rn)+ autoincrement deferred
4n -(Rn) autodecrement
5n @-(Rn) autodecrement deferred
6n X(Rn) index
7n @X(Rn) index deferred

可以通过巧妙地重新使用 R7 上的一些寻址模式(程序计数器)来编码立即数和直接地址:
27  #imm      immediate
37 @#imm absolute
67 addr relative
77 @addr relative deferred

作为 UNIX tty 驱动程序使用 @#作为控制字符, $被替换为 #*@ .

PDP11 指令字中的第一个操作数指的是源操作数,而第二个操作数指的是目标操作数。这反射(reflect)在汇编语言的操作数顺序中,即源,然后是目标。例如,操作码
011273

指的是指令
mov (R2),R3

移动 R2 指向的单词至 R3 .

此语法适用于 8086 CPU 及其寻址模式:
mr0 X(bx,si)  bx + si indexed
mr1 X(bx,di) bx + di indexed
mr2 X(bp,si) bp + si indexed
mr3 X(bp,di) bp + di indexed
mr4 X(si) si indexed
mr5 X(di) di indexed
mr6 X(bp) bp indexed
mr7 X(bx) bx indexed
3rR R register
0r6 addr direct

哪里 m如果没有索引,则为 0, m如果存在一字节索引,则为 1, m如果有两字节索引和 m,则为 2如果使用寄存器而不是内存操作数,则为 3。如果存在两个操作数,则另一个操作数始终是寄存器并在 r 中编码数字。否则, r对操作码的另外三位进行编码。

在这种寻址方案中,立即数是不可能的,所有采用立即数的指令都在其操作码中编码该事实。立即数拼写为 $imm就像在 PDP-11 语法中一样。

而英特尔总是使用 dst, src其汇编器的操作数顺序,没有特别令人信服的理由来适应这个约定,UNIX 汇编器被编写为使用 src, dst PDP11 中已知的操作数顺序。

他们在 8087 浮点指令的实现中与这种顺序存在一些不一致,可能是因为英特尔为非交换浮点指令的两个可能方向提供了不同的助记符,这些助记符与 AT&T 语法使用的操作数顺序不匹配。

PDP11 指令 jmp (跳跃)和 jsr (跳转到子程序)跳转到其操作数的地址。因此, jmp foo会跳转到 foojmp *foo将跳转到存储在变量 foo 中的地址, 类似于 lea在 8086 中工作。

x86 的语法 jmpcall指令的设计就好像这些指令在 PDP11 上工作一样,这就是 jmp foo跳转到 foojmp *foo跳转到地址 foo 处的值,即使 8086 实际上没有延迟寻址。这具有在语法上区分直接跳转和间接跳转而不需要 $ 的优点和便利。每个直接跳转目标的前缀,但在逻辑上没有多大意义。

语法被扩展为使用冒号指定段前缀:
seg:addr

引入 80386 时,该方案使用四部分通用寻址模式适应其新的 SIB 寻址模式:
disp(base,index,scale)

哪里 disp是位移,base 是基址寄存器, index索引寄存器和 scale是 1、2、4 或 8,以按这些数量之一缩放索引寄存器。这等同于 Intel 语法:
[disp+base+index*scale]

PDP-11 的另一个显着特点是大多数指令都以字节和字的形式提供。您使用的是哪一个 bw操作码的后缀,它直接切换操作码的第一位:
 010001   movw r0,r1
110001 movb r0,r1

这也适用于 AT&T 语法,因为大多数 8086 指令确实也可用于字节模式和字模式。后来 80386 和 AMD K6 引入了 32 位指令(后缀 l 表示 long)和 64 位指令(后缀 q 表示四路)。

最后但并非最不重要的一点是,最初的约定是在 C 语言符号前加上下划线(在 Windows 上仍然如此),以便您可以区分名为 ax 的 C 函数。来自注册 ax .当 Unix System Laboratories 开发 ELF 二进制格式时,他们决定摆脱这种装饰。由于无法区分直接地址和寄存器,否则 %前缀被添加到每个寄存器:
mov direct,%eax # move memory at direct to %eax

这就是我们如何获得今天的 AT&T 语法。

关于assembly - 设计 AT&T 汇编语法的最初原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42244028/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com