ATT汇编格式

2024-06-07 16:48
文章标签 格式 汇编 att

本文主要是介绍ATT汇编格式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

绝大多数 Linux 程序员以前只接触过DOS/Windows 下的汇编语言,这些汇编代码都是 Intel 风格的。但在 Unix  Linux 系统中,更多采用的还是 AT&T 格式,两者在语法格式上有着很大的不同:

 AT&T 汇编格式中,寄存器名要加上 ' %' 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。例如:

AT&T 格式

Intel 格式

pushl %eax

push eax

 AT&T 汇编格式中,用 '$' 前缀表示一个立即操作数;而在 Intel 汇编格式中,立即数的表示不用带任何前缀。例如:

AT&T 格式

Intel 格式

pushl $1

push 1

AT&T  Intel 格式中的源操作数和目标操作数的位置正好相反。在 Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边。例如:

AT&T 格式

Intel 格式

addl $1, %eax

add eax, 1

 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀'b''w''l'分别表示操作数为字节(byte比特)、字(word16 比特)和长字(long32比特);而在 Intel 汇编格式中,操作数的字长是用 "byte ptr"  "word ptr" 等前缀来表示的。例如:

AT&T 格式

Intel 格式

movb val, %al

mov al, byte ptr val

 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上'*'作为前缀,而在 Intel 格式中则不需要。

远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为 "ljump"  "lcall",而在 Intel 汇编格式中则为 "jmp far"  "call far",即:

AT&T 格式

Intel 格式

ljump $section, $offset

jmp far section:offset

lcall $section, $offset

call far section:offset

与之相应的远程返回指令则为:

AT&T 格式

Intel 格式

lret $stack_adjust

ret far stack_adjust

 AT&T 汇编格式中,内存操作数的寻址方式是

section:disp(base, index, scale)

 

而在 Intel 汇编格式中,内存操作数的寻址方式为:

section:[base + index*scale + disp]

 

由于 Linux 工作在保护模式下,用的是 32 位线性地址,所以在计算地址时不用考虑段基址和偏移量,而是采用如下的地址计算方法:

disp + base + index * scale

 

下面是一些内存操作数的例子:

AT&T 格式

Intel 格式

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

 

 

Hello World!

真不知道打破这个传统会带来什么样的后果,但既然所有程序设计语言的第一个例子都是在屏幕上打印一个字符串 "Hello World!",那我们也以这种方式来开始介绍 Linux 下的汇编语言程序设计。

 Linux 操作系统中,你有很多办法可以实现在屏幕上显示一个字符串,但最简洁的方式是使用 Linux 内核提供的系统调用。使用这种方法最大的好处是可以直接和操作系统的内核进行通讯,不需要链接诸如 libc 这样的函数库,也不需要使用 ELF 解释器,因而代码尺寸小且执行速度快。

Linux 是一个运行在保护模式下的 32 位操作系统,采用 flat memory 模式,目前最常用到的是 ELF 格式的二进制代码。一个 ELF 格式的可执行程序通常划分为如下几个部分:.text.data  .bss,其中 .text 是只读的代码区,.data 是可读可写的数据区,而 .bss 则是可读可写且没有初始化的数据区。代码区和数据区在 ELF 中统称为 section,根据实际需要你可以使用其它标准的 section,也可以添加自定义 section,但一个 ELF 可执行程序至少应该有一个 .text 部分。下面给出我们的第一个汇编程序,用的是 AT&T 汇编语言格式:

1. AT&T 格式

#hello.s

.data                    # 数据段声明

        msg : .string "Hello, world!//n" # 要输出的字符串

        len = . - msg                   # 字串长度

.text                    # 代码段声明

.global _start           # 指定入口函数

       

_start:                  # 在屏幕上显示一个字符串

        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       # 调用内核功能

 

初次接触到 AT&T 格式的汇编代码时,很多程序员都认为太晦涩难懂了,没有关系,在 Linux 平台上你同样可以使用 Intel 格式来编写汇编程序:

2. Intel 格式

; hello.asm

section .data            ; 数据段声明

        msg db "Hello, world!", 0xA     ; 要输出的字符串

        len equ $ - msg                 ; 字串长度

section .text            ; 代码段声明

global _start            ; 指定入口函数

_start:                  ; 在屏幕上显示一个字符串

        mov edx, len     ; 参数三:字符串长度

        mov ecx, msg     ; 参数二:要显示的字符串

        mov ebx, 1       ; 参数一:文件描述符(stdout)

        mov eax, 4       ; 系统调用号(sys_write)

        int 0x80         ; 调用内核功能

                         ; 退出程序

        mov ebx, 0       ; 参数一:退出代码

        mov eax, 1       ; 系统调用号(sys_exit)

        int 0x80         ; 调用内核功能

 

上面两个汇编程序采用的语法虽然完全不同,但功能却都是调用 Linux 内核提供的 sys_write 来显示一个字符串,然后再调用 sys_exit 退出程序。在 Linux 内核源文件 include/asm-i386/unistd.h 中,可以找到所有系统调用的定义。

 

这篇关于ATT汇编格式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1039744

相关文章

easyui同时验证账户格式和ajax是否存在

accountName: {validator: function (value, param) {if (!/^[a-zA-Z][a-zA-Z0-9_]{3,15}$/i.test(value)) {$.fn.validatebox.defaults.rules.accountName.message = '账户名称不合法(字母开头,允许4-16字节,允许字母数字下划线)';return fal

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern

[数据集][目标检测]血细胞检测数据集VOC+YOLO格式2757张4类别

数据集格式:Pascal VOC格式+YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2757 标注数量(xml文件个数):2757 标注数量(txt文件个数):2757 标注类别数:4 标注类别名称:["Platelets","RBC","WBC","sickle cell"] 每个类别标注的框数:

一步一步将PlantUML类图导出为自定义格式的XMI文件

一步一步将PlantUML类图导出为自定义格式的XMI文件 说明: 首次发表日期:2024-09-08PlantUML官网: https://plantuml.com/zh/PlantUML命令行文档: https://plantuml.com/zh/command-line#6a26f548831e6a8cPlantUML XMI文档: https://plantuml.com/zh/xmi

汇编:嵌入式软件架构学习资源

成为嵌入式软件架构设计师需要掌握多方面的知识,包括嵌入式系统、实时操作系统、硬件接口、软件设计模式等。 以下是一些推荐的博客和网站,可以帮助你深入学习嵌入式软件架构设计: ### 1. **Embedded.com**    - **网址**: [Embedded.com](https://www.embedded.com/)    - **简介**: 这是一个专注于嵌入式系统设计的专业网

单精度浮点数按存储格式转为整数的程序

///#include<cstdio>//-----------------union int_char{unsigned char ch[4];float i;};void out_put(union int_char x)//x86是小端对其模式,即最数据的最低位存储在地址的最低位上。{printf("单精度浮点数值为:%f\n",x.i,x.i);printf("存储位置从左到右

[数据集][目标检测]智慧农业草莓叶子病虫害检测数据集VOC+YOLO格式4040张9类别

数据集格式:Pascal VOC格式+YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):4040 标注数量(xml文件个数):4040 标注数量(txt文件个数):4040 标注类别数:9 标注类别名称:["acalcerosis","fertilizer","flower","fruit","grey

spring事务属性的xml格式配置

实际是使用代理做的事务优化 <!--配置事务的属性--><tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!--匹配所有以add开头的方法--><tx:method name="add*" propagation="REQUIRED" /> <tx:metho

ORA-01861:文字与格式字符串不匹配

select t.*, t.rowid from log_jk_dtl t; insert into log_jk_dtl (rq,zy,kssj,jssj,memo)  values (to_date(sysdate,'yyyy-mm-dd'),'插入供应商', to_char(sysdate,'hh24:mi:ss'),to_char(sysdate,'hh24:mi:ss'),'备注'

Matplotlib图像读取和输出及jpg、png格式对比,及透明通道alpha设置

图像像素值 图像像素值一般size为3,也就是通道数,分别代表R,G,B,如果只有单一 一个值则表示灰度值,也就是说一张二维图片,当长和宽都为1080时,那么若是灰度图像,图像尺寸为(1080,1080,1)若是RGB图像则为(1080,1080,3), jpg、png图像格式 jpg图像的灰度值范围和RGB范围为[0,255],数值类型为uint8,也就是无符号整数 png图像的灰度值范