Linux汇编基础

===汇编基础====
汇编语言程序由定义好的段构成,常用三个段:
数据段  初始值的数据元素
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代码中的局部变量,只能使用全局变量

 
 

你可能感兴趣的:(linux)