AT&T汇编语言初步

关于AT&T汇编语言,网上有许多语法介绍,大家可以移步参考。我这里主要介绍几个汇编实例,如何在linux系统编译,以及浮点数的输出。
一. 一个简单的汇编实例:输出hello,world!

.section .data                           #以下为数据段           
   output:                     			#标签(变量名):关联了当前地址
       .ascii "hello,world!\n"
       len = . - output  			#定义字符串的长度
.section .text  					#以下为代码段
.globl _start						#起始的函数名
_start:
     movl $4, %eax       #系统调用值 $4—输出(write)   $4---立即数(常量)
     movl $1, %ebx      # I/O设备:0-标准输入  1-标准输出  2-错误输出
     movl $output,%ecx   #输出内容的地址
     movl $len,%edx   #输出内容的长度
     int $0x80   #Linux 0x080号系统调用
     
 	 movl $1,%eax       #系统调用值 $1—退出(exit)
     movl $0,%ebx       #退出码    可以用echo $? 查看
     int $0x80       #Linux系统调用

二 . 如何运行AT&T代码
将代码存为helloworld.s,在命令行中输入:
在这里插入图片描述
第一行命令(as):将helloworld.s编译成二进制文件helloworld.o;
第二行命令(ld):将helloworld.o链接成可执行文件helloworld;
第三行命令:运行文件helloworld。

三. 调用C语言函数库输出字符串以及整型数
AT&T汇编语言允许调用C语言的函数库。下面介绍调用C的printf()函数输出字符串和整型数,
代码如下:

.section .data
	output:                     		
		.ascii"The number is %d\n"
.section .bss                #缓冲数据区,存放未初始化数据
	.lcomm buffer,18	            #声明18个字节的缓冲区
.section .text					
.globl _start						
_start:
	pushl $520            #$520为立即数,对应输出中的%d
	pushl $output
	call printf              #调用C语言printf函数
	addl $8,%esp        #堆栈指针加8
	pushl $0               #退出码
	call exit                 #调用C语言函数exit

输出结果:
在这里插入图片描述
注意:调用C语言函数,编译和链接过程都与上面的例子不太一样。链接的时候要指定C语言动态链接库。假设将文件命名为print.s。(由于命令比较长,下面直接以代码的形式给出)

as --32 -o  print.o print.s     
ld -dynamic-linker /lib/ld-linux.so.2 -lc -m elf_i386 -o print print.o
./print

(1)–32表示将目标代码编译成ia-32代码格式;
(2)-m elf_i386表示生成32 elf位elf格式文件;
(3)-dynamic-linker /lib/ld-linux.so.2指定C语言的动态链接库;
(4)-lc 使用gnu连接器的-l参数是为了链接libc.so文件,-c是指定库名称。

四. 浮点数的运算和利用printf输出
用一个题目来体现吧:在这里插入图片描述

.section .data
	array:
		.int 12,4,6,7,80,34,54,46,3,23        #声明一个类型为int的数组array
	str1:
		.ascii"The mean is: %f\n"
	str2:
		.ascii"The minimum is: %d\n"
	value:
		.int 12           #值为12的int型变量
	value2:
		.int 10      #值为10的int型变量
.section .bss
	.lcomm buffer,20
.section .text
.globl _start
_start:
	finit                                 #初始化浮点数寄存器st[x]
	fildl value                         #赋值,st[0] = 12,我们用st[0]存储和(浮点数形式)
	movl $0,%edi                #edi 相当于下标i
	movl array(,%edi,4),%eax       #可以理解为eax = array[i]
	movl %eax,%ebx          #ebx = eax,用ebx寄存器存最小值
start_loop:
	cmpl $23,%eax       #比较立即数23和eax寄存器内的值
	je exit_loop       #je 指令,最近一个运算结果若为相等,则跳转至exit_loop函数
	incl %edi             #i++
	movl array(,%edi,4),%eax        #eax = array[i]
	fiadd array(,%edi,4)               #st[0] = st[0] + array[i],浮点数加法指令
	cmpl %eax,%ebx          #比较指令
	jle start_loop             #jle指令,如果eax>=ebx,就跳转至start_loop函数
	movl %eax,%ebx        #eax

解释:浮点数的存储很特殊,必须使用专门的浮点数寄存器st[0],st[1]…浮点数有专门的栈,最后一个入栈的元素存放在st[0],同时,st[0]也是默认的运算寄存器。浮点数加减乘除都没有多余的参数,默认就是对st[0]。赋值时,我们可以直接将整数赋值给浮点数寄存器,会自动转为浮点数格式,但是不能用立即数进行赋值。
这道题实际是利用一个简单的循环,通过比较找到最小的数,以及累加得到浮点数类型的和,再用浮点数除法得到均值。相信有过汇编语言编程经历的同学都是可以看懂的。运行结果如下:
在这里插入图片描述

五. 总结
写这篇博客的目的主要是记录一下学习的过程。如果能给一些初学的同学一点启发,实在是我的荣幸。由于博主本人接触汇编语言时间也不久,很多知识也是自己摸索得到的,难免会有些不准确的描述,欢迎大佬们指正。

你可能感兴趣的:(学习笔记,AT&T汇编语言)