GCC 80x86/80x64的嵌入汇编以及栈帧结构

80x86寄存器

通用寄存器

  • AX,BX,CX,DX 称作为数据寄存器:

AX (Accumulator):累加寄存器,也称之为累加器;

BX (Base):基地址寄存器;

CX (Count):计数器寄存器;

DX (Data):数据寄存器;

  • SP 和 BP 又称作为指针寄存器:

SP (Stack Pointer):堆栈指针寄存器;

BP (Base Pointer):基指针寄存器;

  • SI 和 DI 又称作为变址寄存器

SI (Source Index):源变址寄存器;

DI (Destination Index):目的变址寄存器;

控制寄存器

IP (Instruction Pointer):指令指针寄存器;

FLAG:标志寄存器;

段寄存器

CS (Code Segment):代码段寄存器;
DS (Data Segment):数据段寄存器;
SS (Stack Segment):堆栈段寄存器;
ES (Extra Segment):附加段寄存器;
FS(Data Segment):数据段寄存器;
GS(Data Segment):数据段寄存器;

内存管理寄存器

GDTR:全局描述符表寄存器
IDTR:中断描述符表寄存器
LDTR:局部描述符表寄存器
TR:任务寄存器
在这里插入图片描述段选择符结构
在这里插入图片描述RPL:请求特权级
TI:表指示标志,=0表示描述符在GDT中,=1表示描述符在LDT中
Index:索引值

逻辑地址、线性地址和物理地址之间的变换,分段机制把逻辑地址转换成线性地址,而分页则把线性地址转换成物理地址。
在这里插入图片描述

控制寄存器

CR0:控制处理器模式和状态的系统控制标志
CR1:保留
CR2:含有导致页错误的线性地址
CR3:含有页目录表物理内存基地址
在这里插入图片描述

系统指令

LLDT/SLDT:加载/保存局部描述符寄存器LDTR
LGDT/SGDT:加载/保存全局描述符表寄存器GDTR
LTR/STR:加载/保存任务寄存器TR,把TR中的TSS加载到任务寄存器中/保存到内存或通用寄存器中
LIDT/SIDT:加载/保存中断描述符表寄存器IDTR
MOV CRn:加载和保存控制寄存器CR0、CR1、CR2和CR3
LMSW/SMSW:加载/保存机器状态字,用于兼容80286处理器
CLTS:清除CR0中的任务已切换标志TS,用于处理设备不存在异常
LSL:加载段限长
HLT:停止处理器执行

寻址方式

立即数寻址/寄存器寻址

MOV AX, 1 ;AX = 1
MOV AX, BX ;AX = BX

直接寻址

MOV AX, [1234H];BX、SI、DI默认段DS,BP默认使用段SS,AX = *(DS << 4 + 1234H)
MOV AX, ES:[1234H];AX = *(ES << 4 + 1234H),把ES数据段中偏移地址为1234H数据复制

寄存器直接寻址

MOV AX, [BX];AX = *(DS << 4 + BX),把DS段中BX指向的字单元复制
MOV AX, CS:[BX];AX = *(CS << 4 + BX)

寄存器相对寻址

MOV AX, [BX + 1234H];AX = *(DS << 4 + (BX + 1234H))
MOV AX, 100H[BX]; AX = *(DS << 4 + (BX + 100H)),把DS段中BX+100H的字单元复制

基址变址寻址

基址变址寻址就是使用两个寄存器{BX/BP} + {SI/DI}(一组只能出现一个),如果出现BP寄存器则默认使用SS寄存器

MOV AX, [BX + SI];AX = *(DS << 4 + (BX + SI))

相对基址变址寻址

MOV AX, [BX + SI + 1234H]; AX = *(DS << 4 + (BX + SI +1234H))

地址属性修饰符

BYTE PTR、WORD PTR和DWORD PTR是属性修饰符,指明地址对应的数据属性

MOV BYTE PTR[BP], 20H;把立即数20H放到DS段中对应BP偏移处,即 *(DS << 4 + BP) = 20H

指令系统

数据传送指令

t通用数据传送指令:MOV、PUSH、POP、XCHG
累加器专用传送指令:IN、OUT、XLAT
地址传送指令:LEA、LDS、LES
标志寄存器传送指令:LAHF、SAHF、PUSHF、 POPF

算术指令

加法指令:ADD、ADC、INC
减法指令:SUB、SBB、DEC、NEG、CMP
乘法指令:MUL、IMUL
除法指令:DIV、IDIV
符号扩展指令:CBW、CWD
十进制调正指令:DAA、DAS、AAA、AAM、AAD

逻辑指令

逻辑运算指令:AND、OR、NOT、XOR、TEST
移位指令:SHL、SAL、SHR、SAR、ROL、ROR、RCL、RCR

串处理指令

设置方向标志指令:CLD、STD
串处理指令:MOVSB/MOVSW、STOSB/STOSW、LODSB/LODSW、CMPSB/CMPSW、SCASB/SCASW
串重复前缀:REP、REPE/REPZ、REPNE/REPNZ

控制转移指令

无条件转移指令:JMP
条件转移指令:JZ/JE、JNZ/JNE、JS、JNS、JO、JNO、JP、JNP、JB、JNB、JBE、JNBE、JL、JNL、JLE、JNLE、JCXZ
循环指令:LOOP、LOOPZ/LOOPE、LOOPNZ、LOOPNE
子程序调用何返回指令:CALL、RET
中断与中断返回指令:INT、INTO、IRET

处理器控制指令

标志位处理指令:CLC、CMC、STC、CLD、STD、CLI、STI
处理机控制指令:NOP、HLT、WAIT、ESC、LOCK

嵌入汇编格式

asm( “汇编语句”
:输出寄存器
:输入寄存器
:会被修改的寄存器);

输入输出寄存器编号

顺序从输出寄存器序列从左到右从上到下以“%0”开始,分别记为%0,%1,…,%9

常用寄存器加载代码说明

“a” 使用寄存器eax
“b” 使用寄存器ebx
“c” 使用寄存器ecx
“d” 使用寄存器edx
“S” 使用esi
“D” 使用edi
“q” 使用动态分配字节可寻址寄存器(eax、ebx、ecx或edx)
“r” 使用任意动态分配的寄存器
“g” 使用通用有效的地址即可(eax、ebx、ecx、edx或内存变量)
“m” 使用内存地址
“o” 使用内存地址并可以加偏移量
“I” 使用常数0-31
“J” 使用常数0-63
“K” 使用常数0-255
“L” 使用常数0-65535
“M” 使用常数0-3
“N” 使用1字节常数(0-255)
“O” 使用常数0-31
“A” 使用eax与edx联合(64位)
“+” 表示操作数可读可写
“=” 输出操作数,输出值将替换前值
“&” 早期会变得操作数,表示使用完操作数之前,内容会被修改

案例

#define get_seg_byte(seg, addr)
({
register char __res;
asm(“push %%fs;
mov %%ax, %%fs;
movb %%fs:%2, %%a1;
:”=a"(__res)
:“0”(seg), “m”(*(addr))); __res;
})

栈帧结构

寄存器ebp(帧指针) 寄存器esp(斩指针),因此函数对大部分数据得访问都基于帧指针ebp进行。
在这里插入图片描述对于函数A调用函数B,转递给B的参数(入栈顺序与函数申明的参数顺序相反,即函数最后一个参数首先压入栈中,第一个参数则是最后一个入栈)包含在A的栈帧中,函数A的返回地址被压入栈,该位置也指明A栈帧的结束处。而B的栈帧从随后的栈部分开始,即图中保存栈帧指针ebp的地方开始,随后用于保存寄存器以及函数的临时值。

80x64寄存器

新增寄存器

新增加寄存器r8到r15,加上x86的原有8个(rax,rbx,rcx,rdx,esi,edi,rbp,rsp),一共16个寄存器。
其中在gcc编译器下:

  • rax 作为函数返回值使用
  • rsp 栈指针寄存器,指向栈顶
  • fastcall规范参数传递规范,使用rcx、rdx、r8、r9寄存器传递函数所需的前4个参数(实数型数据XMM0、XMM1、XMM2、XMM3),并用栈传递其余参数
  • System V AMD64 ABI(泛指Linux、各种BSD和Mac OS X)系统的函数调用使用rdi,rsi,rdx,rcx,r8,r9 作函数参数,依次对应第1参数,第2参数。。。,如果参数超出寄存器,使用栈传递
  • rbx,rbp,r12,r13,r14,r15 用作数据存储,遵循被调用者使用规则,简单说就是随便用,调用子函数之前要备份它,以防他被修改
  • r10,r11 用作数据存储,遵循调用者使用规则,简单说就是使用之前要先保存原值
  • r8~ r15寄存器可以使用相应的32位(r8d~ r15d)、16位(r8w~ r15w)、8位(r8l~ r15l)助记符
  • 平台的指针都是64位指针
  • MSVC使用ECX寄存器传递this指针,而GCC则把this指针作为被调用方函数的第一个参数传递

栈帧结构

MSVC未开启优化选项,会把传递参数的寄存器和帧重新推送到被调用函数帧栈中,这种现象叫做“阴影空间”,具有两个优点:1)避免浪费寄存器资源;2)便于调试器中断时找到函数参数。大型参数可能把输入参数保存在阴影空间里,但是小型函数可能就不会使用阴影空间。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值