【nachos】nachos学习笔记(一) 基础汇编语句

因实验需要nachos,故开始学习分析nachos源码。在分析.s文件中遇到了汇编指令,在学习过程中遇到不少问题,以下是问题及其解答:

1.寄存器

eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。
EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器,作为函数返回值
EBX 是"基地址"(base)寄存器, 在内存寻址时存放基地址。
ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
EDX 则总是被用来放整数除法产生的余数。
ESI/EDI分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.
EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码:
  push ebp ;保存当前ebp
  mov ebp,esp ;EBP设为当前堆栈指针
  sub esp, xxx ;预留xxx字节给函数临时变量.
 这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作 mov esp,ebp/pop ebp/ret 即可.
ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。

2.函数调用堆栈和栈帧

 为单个过程分配的那部分栈就叫做栈帧。栈帧的最顶端以两个指针界定——帧指针(寄存器ebp)和栈指针(esp)。ebp指向函数头,位置固定不动,esp指向函数尾,随函数内部变量的增加或减少而移动。每一个被调用的函数都有一个自己的栈帧结构,并且栈帧结构是由函数自己形成的。需要注意的是:CPU中的寄存器ebp和esp都只有一个。程序地址空间分配图:

3.指令

(1)MOV、LEA和[]问题

  mov 将数据从源操作传到目的操作数中,操作数也可以是立即数。   当num是变量时:
          mov dx,num   按照变量名称,取来它的内容;
          mov dx,[num]   按照变量地址,取来它的内容。 两个是等价的  LEA同理。
以上mov为直接寻址。间接寻址 mov eax,[00400000]传的是地址400000这个地址里的值。
  lea指令用来将一个内存地址赋给目的操作数
        lea eax,[00400000]
那么eax寄存器中的值就是400000。lea第二操作数可以是复杂的表达式,用以代替较多的mov等操作。如
lea eas,[ebx+ecx*2+1]
等效于:
mov eax, ebx
add eax, ecx
add eax, ecx
add eax, 1

(2)rep stos dword ptr es:[edi]

  rep指令重复后面的指令. ecx储存着重复的次数,stos指令将eax中的值拷贝到es:edi指向的地址中,然后edi执行完成后增加或减少。

4.简单程序反编译尝试
 

#include<iostream>
using namespace std;

int f(int x,int y) {
	return x + y;
}
int main() {
	int a = 3;
	int b = f(5,6);
	return 0;
}
int main() {
011BC710  push        ebp               //保存ebp
011BC711  mov         ebp,esp           //令ebp等于esp
011BC713  sub         esp,0D8h          //esp下移0D8h,给栈帧分配空间
011BC719  push        ebx               //保存ebx
011BC71A  push        esi  
011BC71B  push        edi  
011BC71C  lea         edi,[ebp-0D8h]    //令edi的值等于ebp-0D8h,即栈帧的顶部
011BC722  mov         ecx,36h           //令ecx等于36h,即0D8h的四分之一
011BC727  mov         eax,0CCCCCCCCh    //int 3指令
011BC72C  rep stos    dword ptr es:[edi]//将ebp到ebp-0D8h中的内容赋值成int 3
	int a = 3;
011BC72E  mov         dword ptr [a],3   //给变量a赋值 dword ptr 代表为4个字节
	int b = f(5,6);
011BC735  push        6                 //参数6入栈
011BC737  push        5                 //参数5入栈
011BC739  call        f (011B1B09h)     //调用函数f
011BC73E  add         esp,8             //esp上移8个字节 局部变量5,6
011BC741  mov         dword ptr [b],eax //将eax中的返回值赋给b
	return 0;
011BC744  xor         eax,eax           //eax清零
}
011BC746  pop         edi               //弹出edi
011BC747  pop         esi  
011BC748  pop         ebx  
011BC749  add         esp,0D8h          //清空栈帧
011BC74F  cmp         ebp,esp           //比价ebp和esp是否相等,用于堆栈平衡检查
011BC751  call        __RTC_CheckEsp (011B145Bh)  //VS的检查
011BC756  mov         esp,ebp           //将ebp赋给esp
011BC758  pop         ebp               //还原ebp
011BC759  ret                           //返回



int f(int x,int y) {
011BC6D0  push        ebp  
011BC6D1  mov         ebp,esp  
011BC6D3  sub         esp,0C0h  
011BC6D9  push        ebx  
011BC6DA  push        esi  
011BC6DB  push        edi  
011BC6DC  lea         edi,[ebp-0C0h]  
011BC6E2  mov         ecx,30h  
011BC6E7  mov         eax,0CCCCCCCCh  
011BC6EC  rep stos    dword ptr es:[edi]  
	return x + y;
011BC6EE  mov         eax,dword ptr [x]  
011BC6F1  add         eax,dword ptr [y]  
}
011BC6F4  pop         edi  
011BC6F5  pop         esi  
011BC6F6  pop         ebx  
011BC6F7  mov         esp,ebp  
011BC6F9  pop         ebp  
011BC6FA  ret  

参考资料 :

https://bbs.pediy.com/thread-216976.htm

https://blog.csdn.net/jenaeli/article/details/53284408

https://blog.csdn.net/zhu2695/article/details/16813425

猜你喜欢

转载自blog.csdn.net/darord/article/details/83277407