【滴水基础】1.汇编语言(中) 您所在的位置:网站首页 汇编语言dword 【滴水基础】1.汇编语言(中)

【滴水基础】1.汇编语言(中)

2023-12-22 04:05| 来源: 网络整理| 查看: 265

【滴水基础】1.汇编语言(中)

十、内存

   寄存器位于cpu之中,如8个32/64位的通用寄存器,存储数据较少。为此,引入内存。

---每个程序都会有自己独立的4G内存空间(os分配)

---这个4G内存是假的(不是真正的内存,而是映射),是空头支票

---1Byte=8bit;1KB=1024Byte;1M=1024kb;1GB=1024MB

    内存地址:在内存中存储/读取数据,需要用到内存地址,是一种32位编号。

---八个十六进制,一块内存对应8bit,即1Byte==2个十六进制字符

---min:0000 0000,对应十进制:0

---max:FFFF FFFF,对应十进制:16^8

---对应的GB大小:16^8Byte=16^8/1024KB=16^8/1024/1024MB=4GB

    (1)立即数写入内存(MOV指令)

---如:将32位内存写满,需要使用dword

(2)寄存器写入内存

---但是之前1块内存的大小为1Byte=8bit,要存储32bit的立即数,需要4块内存(注意:是连续分配的内存)

---在堆栈中编号间隔4位

---在内存中,编号间隔8*4*4位

---在CPU的进程中,间隔编号的大小不同

---猜测是每个指令占用的内存不同,所以每行程序的执行地址间隔也不同

---将寄存器的内容存入内存(32位)

---换成16位

---换成8位

---注意:AH和AL都存储在堆栈中的低位

(3)内存写入寄存器

---如果内存中存在寄存器ESP/EBP,就使用SS:[]

---否则使用ds:[]

(4)内存写入内存

---在汇编中,一般不允许内存到内存(可以使用MOVS指令)

---但是可以内存到寄存器,再从寄存器到内存

十一:内存地址的五种形式

C语言在汇编中的显示

---先在关键函数处按F9下断点,再按F5开始调试。

---接着,Alt+8出现反汇编窗口,或点击查看-->提示窗口->Disassembly:

---可以看到这里将堆栈中EBP的前32位空间,存储立即数2

---return 0:eax xor eax,为0,并且将0存储入eax

---一般eax存储的都是函数调用的结果(在这之前应该将原来eax的值存储入堆栈,在调用函数结束后,将堆栈中的原eax的值赋值给eax寄存器)

---这里缺少了ss:[],是不标准的写法

---内存地址的表示形式:不一定是内存编号,可以是寄存器,也可以是寄存器的四则运算等等

(1)[立即数]

---读取内存的值/向内存中写入数据

(2)[reg]: reg为寄存器,可以是八个通用寄存器的1个

---读取内存的值

---向内存中写入数据

(3)[reg+立即数]

---读取内存的值

---向内存中写入

(4)[reg+reg*[1,2,4,8]]

---注意,只能为1,2,4,8,因为堆栈中的地址之间间隔4

---读取内存的值

---反正EAX的移动距离只能是4的倍数,如这里2*4=8(下移2个堆栈)

---向内存中写入数据

(5)[reg+reg*[1,2,4,8]+立即数]

---读取内存

---向内存中写入数据

十二:数据的存储模式

---1个内存块(编号)是8bit,但是在堆栈内存中,一个堆栈编号是32bit

---所以1个堆栈内存=4个连续的内存块

---那么,数据的存储在内存中是从高位开始存储还是低位存储

Mov word ptr ds:[0000 0000],0x1A2C

---这里从0000 0000开始,但是word有16位,1个内存地址不够存

---就从0000 0000开始占2个内存地址(Dword就是四个)

---0x1A2C中,1A是数据高位,2C是数据低位

---那么,数据的高位、低位在内存中是如何存储的?

---可以发现,上图是小端模式存储

---arm的cpu(手机)的存储模式多为大端存储

---X86的cpu(电脑) 的存储模式多为小端存储,但是不是绝对的

---如:mov dword ptr ds:[0000 0000],1A2C3E4F

---大端模式

---小端模式

#程序内存地址的查看

---内存地址的查看,只能看堆栈中已经分配的地址

---查看19D008的内存

---查看一个字节,用db

---发现数据的低位是21

---后面的43、65、87分别是08、09、0A、0B的1byte的内存低位

---以2byte的形式查看

---以4byte的形式查看,发现和堆栈的表现形式一样

---向内存中写入4byte数据,观察存储形式

---以byte查看,发现内存的低位44=数据的低位

---此电脑的存储方式是小端存储

#总结

---数据的存放:寄存器、内存

---数据的存储方式:小端存储

---数据的存储:以补码的形式存储

---无符号数:原码=反码=补码;有符号数:补码=反码+1

十三:常用的汇编指令

#相关符号

---r:通用寄存器,如r8为8位通用寄存器

---imm:立即数,如imm8位8位立即数

---m:内存,如m8位8位内存

#简单指令

(1):MOV指令(不能内存到内存)

(2):ADD指令

(3):SUB指令

---前面的寄存器减去后面的

---将结果存储到前面的寄存器

(4):AND指令

---两者都为1时才为1

(5)OR指令

---只有存在1个1,就为1

(6)XOR指令

---两个不一样(一公一母)才为1

(7)NOT指令

---对EDX取反

#较复杂的指令

---EDI(destination index):目的地址寄存器,存储目的地址的内存编号

---ESI(source index):源地址寄存器,存储源地址的内存编号

(1)MOVS指令(从内存到内存移动数据)

---简写:MOVSB

---注意:执行完后,EDI、ESI的值+或者-1/2/4(根据复制的数据大小判断)

---同理:

---MOVS word ptr ES:[EDI],word ptr DS:[ESI]   //简写:MOVSW

---MOVS dword ptr ES:[EDI],dword ptr DS:[ESI] //简写:MOVSD

---注意:EDI、ESI的值+或者-根据EFL(32标志寄存器)的DF来判断

---DF(方向位),在EFL寄存器中的第十位

---根据byte、word、dword来判断加减的数据的大小

---将19FF78的值复制到19FF7C中去

---单步步过,ESI\EDI的值为

---执行MOVS指令

---发现ESI/EDI+4,且DF=0

(2)STOS指令(将AL/AX/EAX的值存储到EDI指定的内存单元)

---EDI所指向的内存要用ES

---根据DF的值,来判断指向STOS命令后EDI的加减

---STOS byte ptr es:[EDI]      //STOSB

---STOS word ptr es:[EDI]      //STOSW

---STOS dword ptr es:[EDI]      //STOSD

---执行后,只将EAX中的最低位赋值给了EDI指向的内存地址

---EDI的值+1

---缺点:只能1次将EAX复制到内存(1次最多4byte)

(3)REP指令:计数寄存器

---根据ECX(计数寄存器),遍历执行,每次ECX-1

---执行rep后,ecx循环3次,应该是将[esi,esi+12]的数据复制到[edi,edi+12]的堆栈中去

---ecx变为0

---edi指向的堆栈发现增加了3个dword的地址

---这里是根据DF来判断,如果DF=1,则就是向上增加堆栈

---将EAX的值连续赋值给堆栈

---这里将EAX赋值给[edi,edi+4*4]

十四:堆栈相关指令

什么是堆栈?

---操作系统在程序启动时分配,和数据结构的堆栈无关

---查看程度的核心:查看堆栈

---查看exe程序被分配的内存

---查看FS,可以看出OS分配了多少的内存

---这里是336000

---查看这块内存,336000为指向SEH的指针(SHE是啥啊)

---从19D000开始,从1A000结束

---在堆栈中查看(堆栈在使用是从后往前使用,我的理解是:将分配的内存压入堆栈,最后面的内存就在最上面,就最先使用)

---如果程序超出了堆栈,会导致堆栈溢出

---栈底是:19FFFC,19FFFC+4=19A000

---栈顶是19D000

#如何查看当前进程的堆栈使用情况?

---ESP(stack pointer):栈顶指针寄存器,记录当前程序使用的堆栈

---[19FFFC,19FF78]是当前程序使用的堆栈

---[19FF74, 19D000]是后面程序使用的堆栈

---ESP向上移动8位

---向下移动8位

---注意:单纯的移动数据是无法改变ESP

---SUB/ADD的缺点:在修改堆栈之后,还要进行ESP的修改



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有