x86汇编一直存在两种不同的语法,intel语法和AT&T语法,在intel的官方文档中使用intel语法,Windows也使用intel语法,而UNIX平台的汇编器一直使用AT&T语法。
linux下,x86汇编AT&T语法用GAS编译,Intel语法用NASM编译。
AT&T和Intel语法没有好坏之分,只是语法有差异而已。
GAS的语法主要有:
* 寄存器名前缀%
* 操作数是源在前,目的在后。与Intel语法刚好相反。
* 操作数长度在指令名后缀,b表示8位,w表示16位,l表示32位,如movl %ebx,%eax。
* 立即操作数(常量)用$标示,如addl $5,%eax
* 变量加不加$有区别。如movl $foo, %eax表示把foo变量地址放入寄存器%eax。movl foo,%eax表示把foo变量值放入寄存器%eax。
hello_world例子
NASM (hello.asm)
section .text ;section declaration ;we must export the entry point to the ELF linker or global _start ;loader. They conventionally recognize _start as their ;entry point. Use ld -e foo to override the default._start:;write our string to stdout mov edx,len ;third argument: message length mov ecx,msg ;second argument: pointer to message to write mov ebx,1 ;first argument: file handle (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel;and exit mov ebx,0 ;first syscall argument: exit code mov eax,1 ;system call number (sys_exit) int 0x80 ;call kernelsection .data ;section declarationmsg db "Hello, world!",0xa ;our dear stringlen equ $ - msg ;length of our dear string
GAS (hello.S)
.text # section declaration # we must export the entry point to the ELF linker or .global _start # loader. They conventionally recognize _start as their # entry point. Use ld -e foo to override the default._start:# write our string to stdout movl $len,%edx # third argument: message length movl $msg,%ecx # second argument: pointer to message to write movl $1,%ebx # first argument: file handle (stdout) movl $4,%eax # system call number (sys_write) int $0x80 # call kernel# and exit movl $0,%ebx # first argument: exit code movl $1,%eax # system call number (sys_exit) int $0x80 # call kernel.data # section declarationmsg: .ascii "Hello, world!\n" # our dear string len = . - msg # length of our dear string
Fornasmexample:
$ nasm -f elf hello.asm
Forgasexample:
$ as -o hello.o hello.S
This makeshello.oobject file.
Second step is producing executable file itself from the object file by invoking linker:
$ ld -s -o hello hello.o
看一些例子:
+-----------------------------------+---------------------------------------------+
| Intel Code | AT&T Code |
+-----------------------------------+---------------------------------------------+
| mov eax,1 | movl $1,%eax |
| mov ebx,0ffh | movl $0xff,%ebx |
| int 80h | int $0x80 |
| mov ebx, eax | movl %eax, %ebx |
| mov eax,[ecx] | movl (%ecx),%eax |
| mov eax,[ebx+3] | movl 3(%ebx),%eax |
| mov eax,[ebx+20h] | movl 0x20(%ebx),%eax |
| add eax,[ebx+ecx*2h] | addl (%ebx,%ecx,0x2),%eax |
| lea eax,[ebx+ecx] | leal (%ebx,%ecx),%eax |
| sub eax,[ebx+ecx*4h-20h] | subl -0x20(%ebx,%ecx,0x4),%eax |
+-----------------------------------+----------------------------------------------+cmp eax,ebx ---- cmpl %ebx,%eax参考:
|