首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

AT&T 汇编数据传递

2012-12-23 
AT&T 汇编数据传送注:以下内容为学习笔记,多数是从书本、资料中得来,只为加深印象,及日后参考。然而本人表达

AT&T 汇编数据传送

注:以下内容为学习笔记,多数是从书本、资料中得来,只为加深印象,及日后参考。然而本人表达能力较差,写的不好。因非翻译、非转载,只好选原创,但多数乃摘抄,实为惭愧。但若能帮助一二访客,幸甚!


一.定义数据
1.数据段
程序的数据段是最常见的定义数据元素的位置。使用.data命令声明数据段,.rodata中定义的数据只能按照只读模式访问。
在数据段中定义数据元素需要两个语句:一个标签和一个命令,标签用作引用数据元素所使用的标记,类似与C中的变量名,另外需要一个汇编命令定义为数据元素保留的字节数:
------------------------------------------------------
命令 数据类型
----------------------------------------------------
.ascii 文本字符串
.asciz 以空字符结尾的文本字符串
.byte 字节值
.double 双精度浮点数
.float 单精度浮点数
.int 32位整数
.long 32位整数(同.int)
.octa 16字节整数
.quad 8字节整数
.short 16位整数
.single 单精度浮点数(同.float)
-------------------------------------------------------
例子:
output:
.ascii "Hello AT&T\n"
这个代码片段会留出11字节的内存,把定义的字符串顺序放到内存字节中,且把标签output赋值为第一个字节地址。
可以在一行中定义多个值:
sizes:
.long 100, 101, 102, 103
上面的代码把4个长整数(4字节)按顺序放到内存中,可按相对地址访问每个值,如访问内存sizes+8访问102.

2.定义静态符号
.equ命令用于把常量值设置为可以在为本段中使用的符号:
.equ LINUX_SYS_CALL_WRITE  4
引用静态数据元素:
movl $LINUX_SYS_CALL_WRITE, %eax

3.BSS段
在bss段中定义数据无需声明特定的数据类型,只要声明为所需目的保留的原始部分即可。
上句感觉汉语版翻译的不太明白,英文原句:
Instead of declaring specific data types, you just declare raw segment of memory that are reserved fo whatever purpose you need them for.
GNU 汇编器使用两个命令声明缓冲区:
--------------------------------
命令 描述
-------------------------
.comm 声明未初始化的数据的通用内存区域
.lcomm 声明未初始化的数据的本地通用内存区域
--------------------------------
本地通用内存区域是为不会从本地汇编代码之外进行访问的数据保留的。
命令格式:
.comm symbol, length
例如:
.section .bss
.lcomm buffer, 100

二.数据传送
1.MOV 指令
格式:
mov* src, dst
GNU汇编器要求MOV指定传送的数据的长度mov*中的*:
---------------------------------------------------
l 32位
w 16位
b 8位
---------------------------------------------------
注:未包含字符串传递指令MOVS等
src、dst的值可以是内存地址、存储在内存中的数据值、指令语句中定义的数据值、寄存器。

2.把立即数传送到寄存器、内存
立即数前面要加$符号,寄存器前面要加%符号
1)立即数传送到寄存器:
movl $0x80, %eax
2) 立即数传送到指定内存地址
若数据段中有:
.section .data
height:
.int 10
则可用下面的方法将立即数传递到height表示的内存地址:
mvol $0x100, height
注:标签表示的是内存地址

3.在寄存器之间传送数据
8个通用寄存器:EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP,这些寄存器中的值可以传送给可用的任何其他类型的寄存器。
专用寄存器(控制、调试、段寄存器)的内容只能传送给通用寄存器,或从通用寄存器接收内容。
movl %eax, %ebx
movw %ax, %bx

4.在内存和寄存器之间传送数据
1)内存 -> 寄存器
movl value, %eax
该指令将value指定的内存开始的32位数据传送给eax。若数据长度小于4自己,则需使用movw或movb。
测试代码:

# An example of the xchg instruction.section .datavalues:.int105, 222, 54, 315, 145, 221, 32, 167, 111, 4len:.int10output:.asciz"%d\n"output_before:.asciz"before sort:\n"output_after:.asciz"after sorted:\n".section .text.global_start_start:nopmovl$0,%edipushl$output_beforecallprintfaddl$4,%espprint_datas:movlvalues(, %edi, 4),%eaxpushl%eaxpushl$outputcallprintfaddl$8,%espinc%edicmpllen,%edijneprint_datasbubble_sort:movl$values,%esimovllen,%ecxdec%ecxmovllen,%ebxdec%ebxloop:movl(%esi),%eaxcmp%eax,4(%esi)jgeskipxchg%eax,4(%esi)movl%eax,(%esi)skip:add$4,%esidec%ebxjnzloopdec%ecxjzendmovl$values,%esimovl%ecx,%ebxjmploopend:pushl$output_aftercallprintfaddl$4,%espmovl$0,%ediprint_datas_after:movlvalues(, %edi, 4),%eaxpushl%eaxpushl$outputcallprintfaddl$8,%espinc%edicmpllen,%edijneprint_datas_aftermovl$1,%eaxmovl$0,%ebxint$0x80
运行结果:
before sort:
105
222
54
315
145
221
32
167
111
4
after sorted:
4
32
54
105
111
145
167
221
222
315

五.堆栈

五.堆栈
pushx src
src可以是16/32位寄存器值,16/32位内存值,16位段寄存器值,8/16/32位立即数
popx dst
dst可以是16/32位寄存器值,16位段寄存器值,16/32位内存值


压入和弹出所有寄存器
----------------------------------------------------
指令                描述
-------------------------------------------------
PUSHA/POPA 压入/弹出所有16位通用寄存器
PUSHAH/POPAD 压入/弹出所有32位通用寄存器
PUSHF/POPF 压入/弹出EFLAGS寄存器的低16位
PUSHFD/POPFD 压入/弹出EFLAGS寄存器的全部32位
----------------------------------------------------





热点排行