===汇编基础====
汇编语言程序由定义好的段构成,常用三个段:
数据段 初始值的数据元素
BSS段 使用零初始化的数据元素
文本段 程序代码
注明:
在BSS段中声明的数据,是不包含在可执行程序中的,但是
数据段必然包含在科执行程序中
汇编的编写有如下规则:
定义段 使用.section伪指令定义)
定义入口点 使用.globl伪指令定义,用于标明程序从哪个
开始执行程序,一般默认为.global _start
如果是GCC编译,定义为.globl main
====汇编伪指令====
.section 标明使用哪种类型的程序段
.data 标明是数据段
.text 标明是代码段
.globl 标明程序的入口点
.equ 定义静态符号,一般在文本段引用(使用$符号引用)
.comm 声明为初始化的数据的通用内存区域
.lcomm 声明为初始化的数据的本地内存区域
伪指令.comm, .lcomm两者格式均类似".comm symbol, length"
====数据类型指令====
.long long整型
.byte 字节值
.int 整型
.ascii 字符串
.asciz 以空字符结尾的字符串
.double 双精度浮点数
.float 单精度浮点数
.octa 16字节整数
.quad 8字节整数
.short 16位整数
====汇编栈帧====
汇编语言使用标签标明地址,例子如下
label_name:
assemble code
...
栈有个术语需要熟悉。一个是栈底,栈底表示栈的起始位置,位于高
地址;另一个是栈顶,栈顶表示栈的当前使用位置,位于低地址,数据不断的
入栈,出栈,使得栈顶一直处于活动状态;另外需要知道的是栈的增长是向低
地址方面
标准制定,%esp寄存器保存栈顶指针,%ebp寄存器保存栈底指针,这两个寄存器只能
用于这样的用途,用于其他用途都是不太明智的做法
====寻址方式====
直接寻址模式
exp: movl ADDRESS, %eax
变址寻址方式
exp: movl address_start(,%ecx,1), %eax
间接寻址模式
exp: movl (%eax), %ebx
# %ebx的值是一个地址
基址寻址模式
exp: movl 4(%eax), %ebx
立即数寻址
exp: movl $12, %eax
寄存器寻址
exp: movl %eax, %ebx
寻址方式可以概要表示为如下公式:
ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)
FINAL ADDRESS = ADDRESS_OR_OFFSET + %BASE_OR_OFFSET + MULTIPLIER * %INDEX
说明:
1.ADDRESS_OR_OFFSET和MULTIPLIER必须是常量
2.其余两个必须是寄存器,如果某一个值为空,留空就行
====汇编指令====
此处并未全部列出,列出自己所学所知
1.cmpl指令比较两个数,并设置%eflags寄存器的值,然后供下面的跳转指令使用
比较指令格式cm operand1, operand2,注意操作数的位置,尤其是和INTEL的
语法不一致
2.条件跳转指令
je 相等
jg 第二个数大于第一个数
jge 第二个数大于等于第一个数
jl 第二个数小于第一个数
jle 第二个数小于等于第一个数
jmp 无条件跳转
3.cpuid的指令使用单一寄存器%eax作为输入,返回的是一个字符串,地址从
低到高存储在%ebx, %ecx, %edx
%eax的值
0 厂商ID字符串
1 处理器类型
2 处理器缓存配置
3 处理器序列号
4 缓存配置
5 监视信息
====跳转分支====
跳转 汇编语言必须使用跳转实现很多功能
使用单一指令jmp location(一般是标签地址)
调用 使用call指令
中断 软中断+硬中断
exp1: int 0x80属于软中断
exp2: 硬件出现被除数为零中断程序属于硬中断
条件跳转
1.近跳转 16或32地址偏移
2.短跳转 8位地址偏移
3.不支持内存模式远跳转
====汇编函数====
1.定义方式
.type function_name, @function
function_name:
function_code
…
2.调用汇编函数
call function_name256
===命令行参数传递====
Linux程序启动的时候,命令行参数传递的栈帧结构如下
高地址 环境变量
命令行参数
指向环境变量的指针
分割 0x00000000
指向命令行参数N的指针
...
指向命令行参数2的指针
指向命令行参数1的指针
程序名称
参数数目
...
说明:参数数目永远不为0,大于等于1,因为程序名称总是存在
===系统调用===
linux内核系统调用
调用号存在vim /usr/include/asm/unistd.h
系统调用规定的输入值方式
%eax 系统调用号
%ebx 第一个参数
%ecx 第二个参数
%edx 第三个参数
%esi 第四个参数
%edi 第五个参数
如果超过6个参数,那么%ebx保存指向输入参数的内存位置指针,那么参数
内存要求存储连续性,系统调用的返回值是存储在%eax寄存器中
内联汇编使用asm(“asm code”)的方式嵌入,它可以自由嵌入汇编代码,不过
不能使用C代码中的局部变量,只能使用全局变量