0%

转载:AT&T 和 Intel 规范的区别

概述

常见的指令集以及汇编语言规范:

  • x86(IA-32)、x86-64指令集(常见于PC端),对应有2家公司发布的不同汇编语言规范:
    • intel公司发布的汇编语言规范,称intel 汇编:Windows派系(Microsoft),比较著名的汇编器有微软的masm和开源的nasm。
    • AT&T公司发布的汇编语言规范,称AT&T 汇编:Unix派系(或者说GNU),比如g++编译器等。
  • ARM指令集(常见于嵌入式、移动端设备,粗略统计覆盖95%左右的手段):ARM公司发布的汇编语言规范,称ARM 汇编(目前常见的是ARM 64汇编),见官网文档

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 + index*scale + disp] 寻址方式的区别,无论形式如何,都是实现如下的地址计算:(其中base和index必须是寄存器,disp和scale可以是常数)disp + base + index * scale
movl -4(%ebp), %eax mov eax, [ebp - 4] 内存操作数的例子
movl array(, %eax, 4), %eax mov eax, [eax*4 + array] 内存操作数的例子
movw array(%ebx, %eax, 4), %cx mov cx, [ebx + 4*eax + array] 内存操作数的例子
movb $4, %fs:(%eax) mov fs:eax, 4 内存操作数的例子

搭建Intel的环境

  • ubuntu16.04 或 ubuntu18.04
  • vscode
  • dosbox
  • 文件后缀:.asm

安装dosbox

1
$ sudo apt-get install dosbox

下载vscode插件MASM/TASM

Intel的hello.asm

hello.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
;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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.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 #调用内核功能

编译运行

1
2
$ gcc hello.s -o hello_att
$ ./hello_att

通过objdump查看到的几种cpu架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ 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

汇编学习地址:第一个汇编语言程序


版权声明:本文为CSDN博主「线条君」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39503880/article/details/113462657