Ske*_*een 18 x86 assembly att intel-syntax
16(%esp)真的违反直觉[esp+16]吗?是不是更合乎逻辑:
eax = 5
mov eax, 5
Run Code Online (Sandbox Code Playgroud)
at at&t是:
mov 5, eax
5 = a (? wait what ?)
Run Code Online (Sandbox Code Playgroud)
注意:我不是想乱跑.我只是不明白他们所做的设计选择,我试图了解他们为什么做了他们所做的.
Tho*_*nin 26
1,2,3和5:符号有点多余,但我发现在汇编时发展是一件好事.冗余有助于阅读.关于"让汇编程序弄明白"的观点很容易变成"让读取代码的程序员把它弄清楚",而当我是那个读书的人时,我不喜欢它.编程不是只写任务; 甚至程序员自己也必须阅读自己的代码,语法冗余有很大帮助.
另一点是'%'和'$'意味着可以添加新的寄存器而不会破坏向后兼容性:添加时没有问题,例如,一个被调用的寄存器xmm4,因为它将被写出来%xmm4,不能与变量混淆被称为xmm4没有'%'的人.
至于打字的数量:通常,在组装编程时,瓶颈是大脑,而不是手.如果'$'和'%'减慢你的速度,那么要么你想要的速度比人们通常认为的那样快,或者更可能的是,你手头的任务太机械了,不应该用部件; 它应该留给自动代码生成器,通俗地称为"C编译器".
添加了'l'后缀来处理汇编程序"无法"弄明白的情况.例如,这段代码:
mov [esp], 10
Run Code Online (Sandbox Code Playgroud)
是不明确的,因为它不会告诉你是要写一个值为10的字节,还是一个具有相同数值的32位字.然后,英特尔语法要求:
mov byte ptr [esp], 10
Run Code Online (Sandbox Code Playgroud)
当你想到它时,这是非常难看的.AT&T的员工想要做出更合理的事情,所以他们想出了:
movb $10, (%esp)
Run Code Online (Sandbox Code Playgroud)
他们喜欢系统化,并且到处都有'b'(或'l'或'w')后缀.请注意,并不总是需要后缀.例如,你可以写:
mov %al, (%ebx)
Run Code Online (Sandbox Code Playgroud)
让GNU汇编程序"弄清楚",因为你在谈论'%al',所以移动是针对单个字节的.真的行 !然而,我仍然发现更好地指定大小(它确实有助于读者,程序员本人是他自己的代码的第一个也是最重要的读者).
对于"反转":反之亦然.英特尔语法模仿C中发生的事情,其中值在右侧计算,然后写入左侧的值.因此,考虑到从左到右的阅读,写作在"反向"方向上从右到左.AT&T语法恢复到"正常"方向.至少他们考虑过这样; 因为无论如何他们决定使用他们自己的语法,他们认为他们可以在他们认为的"正确的顺序"中使用操作数.这主要是一个惯例,但不是一个不合逻辑的惯例.C约定模仿数学符号,除了数学是关于定义值("让x是值5")而不是关于赋值(" 一个名为'x'的插槽.)AT&T的选择是有道理的.只有当你将C代码转换为汇编时才会感到困惑,这个任务通常应留给C编译器.
从历史的角度来看,问题5的最后一部分很有意思.用于x86的GNU工具遵循AT&T语法,因为当时他们试图在Unix世界中占据一席之地("GNU"意味着"GNU不是Unix")并与Unix工具竞争; Unix在AT&T的控制之下.这是在Linux甚至Windows 3.0之前; PC是16位系统.Unix使用AT&T语法,因此GNU使用AT&T语法.
那么好的问题是:为什么AT&T发现自己的语法很聪明?如上所述,他们有一些原因,这些原因并非没有价值.当然,使用自己的语法的成本是它限制了互操作性.在那些日子里,C编译器或汇编器作为一个单独的工具没有任何意义:在Unix系统中,它们应该由OS供应商提供.此外,英特尔在Unix世界中并不是一个重要的参与者; 大系统主要使用VAX或Motorola 680x0衍生产品.20年后,没有人发现MS-Dos PC将成为台式机和服务器领域的主导架构.
1-2,5:他们可能选择为寄存器加前缀,以便更容易解析; 你直接知道第一个字符是什么样的标记.
4:不.
6:同样,可能是为了让解析器更容易找出要输出的指令.
7:其实这更有意义的语法含义,移动什么到哪里.也许mov指令应该是ld指令.
不要误会我的意思,我认为AT&T的语法很糟糕.
GNU汇编程序的AT&T语法可以追溯到Unix汇编程序1,它本身的输入语法主要来自PDP-11 PAL-11汇编程序(约1970年).
任何人都可以向我解释为什么AT&T语法中的每个常量前面都有一个"$"?
它允许区分立即常量和内存地址.英特尔语法以相反的方式实现,内存引用为[foo].
顺便说一下,MASM(Microsoft汇编程序)不需要在语法级别上进行区分,因为它可以判断操作数是符号常量还是标签.x86的其他汇编程序主动避免这种猜测,因为它们可能会让读者感到困惑,例如:IDEAL模式下的TASM(它在内存引用上发出警告而不是括号内),nasm,fasm.
使用PAL-11 #为立即寻址模式,其中操作数遵循的指令.常量,不#表示相对寻址模式,其中相对地址跟随指令.
Unix使用与DEC汇编程序相同的语法来寻址模式,*而不是代替@,而$不是#,因为@它#显然不便于输入2.
为什么所有寄存器都有'%'?
在PAL-11中,寄存器定义为R0 =%0,R1 =%1,...,R6也称为SP,R7也称为PC.DEC MACRO-11宏汇编程序允许将寄存器称为%x,其中x可以是任意表达式,例如%3+1所指的%4.
这只是让我做很多蹩脚打字的另一种尝试吗?
不.
另外,我是唯一一个发现:16(%esp)与[esp + 16]相比真的违反直觉吗?
这来自PDP-11 索引寻址模式,其中通过将寄存器的内容与指令之后的索引字相加来形成存储器地址.
我知道它编译成同样的东西,但为什么有人想要输入很多'$'和'%'而不需要? - 为什么GNU选择此语法作为默认语法?
它来自PDP-11.
另一件事,为什么at&t语法中的每条指令前面都有一个:l? - 我知道它的操作数大小,但为什么不让汇编程序弄清楚呢?(我是否想要在不是那么大的操作数上做一个movl?)
天然气通常可以搞清楚.其他装配工在特定情况下也需要帮助.
PDP-11将b用于字节指令,例如:CLRvs CLRB.VAX-11中出现了其他后缀:lfor long,wfor word,ffor float,dfor double,qfor quad-word,...
Run Code Online (Sandbox Code Playgroud)Last thing: why are the mov arguments inverted?
可以说,由于PDP-11早于英特尔微处理器,它就是另一种方式.
| 归档时间: |
|
| 查看次数: |
1894 次 |
| 最近记录: |