汇编 | AT&T和Intel规范的区别
概述
常见的指令集以及汇编语言规范: x86(IA-32)、x86-64指令集(常见于PC端),对应有2家公司发布的不同汇编语言规范:
- intel公司发布的汇编语言规范,称
intel 汇编
:Windows派系(Microsoft),比较著名的汇编器有微软的masm和开源的nasm。 - AT&T公司发布的汇编语言规范,称
AT&T 汇编
:Unix派系(或者说GNU),比如g++编译器等。
AT&T格式 和 Intel格式的区别
表格如下:
|AT&T格式|Intel格式|说明 |—— |pushl %eax|push eax|在AT&T汇编格式中,寄存器名要加上’ %‘作为前缀;而在Intel汇编格式中,寄存器名不需要加前缀 |pushl $1|push 1|在AT&T汇编格式中,用’$‘前缀表示一个立即操作数;而在Intel汇编格式中,立即数的表示不用带任何前缀 |addl $1, %eax|add eax, 1|AT&T和Intel格式中的源操作数和目标操作数的位置正好相反。在Intel汇编格式中,目标操作数在源操作数的左边;而在AT&T汇编格式中,目标操作数在源操作数的右边。 |movb val, %al|mov al, byte ptr val|在AT&T汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀’b’、‘w’、’l’分别表示操作数为字节(byte,8比特)、字(word,16比特)和长字(long,32比特);而在Intel汇编格式中,操作数的字长是用"byte ptr"和"word ptr"等前缀来表示的。 |ljump $section, $offset|jmp far section:offset|在AT&T汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上’‘作为前缀,而在Intel格式中则不需要。远程转移指令和远程子调用指令的操作码,在AT&T汇编格式中为"ljump"和"lcall",而在Intel汇编格式中则为"jmp far"和"call far" |lcall $section, $offset|call far section:offset|同上 |lret $stack_adjust|ret far stack_adjust|与之相应的远程返回指令 |section:disp(base, index, scale)|section:[base + indexscale + disp]|寻址方式的区别,无论形式如何,都是实现如下的地址计算:(其中base和index必须是寄存器,disp和scale可以是常数)disp + base + index * scale |—|—|— |movl -4(%ebp), %eax|mov eax, [ebp - 4]|内存操作数的例子 |movl array(, %eax, 4), %eax|mov eax, [eax4 + array]|内存操作数的例子 |movw array(%ebx, %eax, 4), %cx|mov cx, [ebx + 4eax + array]|内存操作数的例子 |movb $4, %fs:(%eax)|mov fs:eax, 4|内存操作数的例子
搭建Intel的环境
- ubuntu16.04 或 ubuntu18.04- vscode- dosbox- 文件后缀:.asm 安装dosbox
sudo apt-get install dosbox
下载vscode
插件MASM/TASM
Intel的hello.asm
;description
DATA SEGMENT USE16
MYWORD DB "hello world!!!"
DATA ENDS
;description
CODE SEGMENT USE16
ASSUME CS:CODE, DS:DATA ;代表谁是代码段,谁是数据段
main:
mov AX, DATA ;数据首地址赋值给AX, ax是寄存器
mov DS, AX ;使得DS等价于AX,同样指向数据段
LEA DX, MYWORD ;使DX寄存器指向数据变量word的首地址
mov AH, 09h ;AH输出数据
INT 21h ;执行AH的09h功能, 输出数据
mov AX, 4c00h ;设置寄存器的功能
INT 21h ;调用寄存器功能 程序结束
CODE ENDS
END main
在文件中点击鼠标右键运行程序
搭建AT&T的环境
- ubuntu16.04 或 ubuntu18.04- vscode- 文件后缀: .s- gcc
下载
vscode
插件GNU Assembler Language Support
AT&T的hello.s
#hello.s
.data#数据段声明
msg : .string "Hello, world\n" #要输出的字符串
len = . - msg #字串长度
.text #代码段声明
.global main #指定入口函数
main: #在屏幕上显示一个字符串
movl $len, %edx #参数三:字符串长度
movl $msg, %ecx #参数二:要显示的字符串
movl $1, %ebx #参数一:文件描述符(stdout)
movl $4, %eax #系统调用号(sys_write)
int $0x80 #调用内核功能
#退出程序
movl $0,%ebx #参数一:退出代码
movl $1,%eax #系统调用号(sys_exit)
int $0x80 #调用内核功能
编译运行
$ gcc hello.s -o hello_att
$ ./hello_att
通过objdump查看到的几种cpu架构
$ objdump --help
objdump:支持的体系结构: i386 i386:x86-64 i386:x64-32 i8086 i386:intel i386:x86-64:intel i386:x64-32:intel i386:nacl i386:x86-64:nacl i386:x64-32:nacl iamcu iamcu:intel l1om l1om:intel k1om k1om:intel plugin
下列 i386/x86-64 特定的反汇编器选项在使用 -M 开关时可用(使用逗号分隔多个选项):
x86-64 Disassemble in 64bit mode
i386 Disassemble in 32bit mode
i8086 在 16 位模式下反汇编
att 用 AT&T 语法显示指令
intel 用 Intel 语法显示指令
att-mnemonic
Display instruction in AT&T mnemonic
intel-mnemonic
Display instruction in Intel mnemonic
addr64 假定 64 位地址大小
addr32 假定 32 位地址大小
addr16 假定 16 位地址大小
data32 假定 32 位数据大小
data16 假定 16 位数据大小
suffix 在 AT&T 语法中始终显示指令后缀
amd64 Display instruction in AMD64 ISA
intel64 Display instruction in Intel64 ISA
汇编学习地址:http://c.biancheng.net/view/3463.html
--完--
- 原文作者: 留白
- 原文链接: https://zfunnily.github.io/2021/01/attandintel/
- 更新时间:2024-04-16 01:01:05
- 本文声明:转载请标记原文作者及链接