滴水三期:day03.2-寻址方式

本文详细讲解了CPU如何通过五种寻址方式(立即数、寄存器、寄存器+立即数、寄存器+寄存器*、寄存器+寄存器*+立即数)来访问内存,包括MOV、MOVDWORD等指令实例,并提供了内存读写和地址获取的练习题。

一、为什么要寻址

  • 我们知道数据存储在内存中,CPU需要使用存在内存中的数据,使用一个数据就要在内存中找到这个数据,用什么找,就是用内存编号,即地址,来找到数据在内存中所在的位置,把它取出来使用,或者再放回到指定位置
  • 上述就是一个寻址过程:寻址方式一共有五种,计算机只认识这五种方式来寻址

二、五种寻址方式

1.寻址方式一[立即数]

  • 直接通过[立即数],即直接用内存地址来寻址

  • 读取内存的值

    MOV EAX,DWORD PTR DS:[0x13FFC4]   
    

    MOV就是将DWORD PTR DS:[0x13FFC4]这个值放到32位EAX寄存器中;DWORD表示读32位的数字,可以省略但不建议;PTR是固定写法;DS是段寄存器,32位汇编中段寄存器和内存的属性有关系,如果后面地址直接用数表示,则用DS,如果后面写ESP或者EBP,就写SS,如果EDI的话就用ES。所以32位汇编中段寄存器就是后面内存属性的一个标识。所以整条指令的作用就是用立即寻址的方式将内存中0x13FFC4地址中存储的值读出来放到EAX里

    BBCB4D45FEEF6B0E68FC1C7299C98A85
  • 内存中写入数据

    MOV DWORD PTR DS:[0x13FFC4],ebx
    

    将内存中0x13FFC4中的值读出来写入到ebx寄存器中

  • 获取内存编号

    LEA EAX,DWORD PTR DS:[0x13FFC4]
    

    第一条指令表示将内存中0x13FFC4这个地址编号放入到EAX寄存中

    535E45CAA61E06FC94AD883FFC11D7FA

2.寻址方式二[reg]

  • 通过[reg]来寻址,reg可以是8个通用寄存器中的任意一个。先通过读取寄存器中存放的内存地址编号,再通过内存地址编号找到内存中的值

  • 读取内存的值

    MOV ECX,0x13FFD0    #将0x13FFD0这个地址编号,放到到ECX寄存中,此地址就是ecx的基址
    #中间可能还有很多对ecx中的值的操作,我们只要找到ecx的基址,就可以跟踪ecx,最后得到下面语句中ecx究竟是什么
    MOV EAX,DWORD PTR DS:[ECX]    #将ECX寄存中存储的0x13FFD0这个地址中的值取出来放到EAX里
    
    8CFD8A6055012E11FC6BFBEE1DD4F520
  • 向内存中写入数据

    MOV EDX,0x13FFD8     #将0x13FFD8存入EDX中
    MOV DWORD PTR DS:[EDX],0x87654321
    
  • 获取内存编号

    LEA EAX,DWORD PTR DS:[EDX]
    
    429BF6AA2E5457D5D99FC0BAF68FDE19

3.寻址方式三[reg+立即数]

  • 通过[reg+立即数]

  • 读取内存的值

    MOV ECX,0x13FFD0
    MOV EAX,DWORD PTR DS:[ECX+4]     #将地址编号为0x13FFD0+0x000004中的值取出存到EAX中
    
  • 向内存中写入数据

    MOV EDX,0x13FFD0
    MOV DWORD PTR DS:[EDX+0xC],0x87654321
    
  • 获取内存编号

    LEA EAX,DWORD PTR DS:[EDX+4]
    

4.寻址方式四[reg+reg*{1,2,4,8}]

  • 通过[reg+reg*1或者2或者4或者8]来寻址,只能是1,2,4,8,后面学硬编码就知道了

  • 读取内存的值

    MOV EAX,0x13FFC4
    MOV ECX,2
    MOV EDX,DWORD PTR DS:[EAX+ECX*4]  #将0x13FFC4+0x8后的地址编号中的值取出来存到EDX
    

    特殊情况:如果[reg+reg*{1,2,4,8}]得到的内存地址编号不是栈的表示地址,比如算出来的结果是0x0019ff7A,我们知道栈中每个地址编号之间相差4,是因为用一个首地址0x0019ff78表示了0x0019ff78到0x0019ff7B这四个内存块,一共4字节,所以0x0019ff78后面才能显示存的值为0x004010f0。实际上0x0019ff7A中存的值为0x40(一个字节),而上面的命令用的是DWORD,表示读取4字节作为整体存入edx中,所以就从0x0019ff7A后面往后取4字节,即取0x19ff7A,0x19ff7B,0x19ff7C,0x19ff7D中的值,最终结果为0xFA100040(写的时候记得从高位开始写)

    image-20211124111141002
  • 向内存中写入数据

    MOV EAX,0x13FFC4
    MOV ECX,2
    MOV DWORD PTR DS:[EAX+ECX*4],87654321   #将87654321这个值写入到0x13FFC4+0x8这个内存中
    
  • 获取内存编号

    LEA EAX,DWORD PTR DS:[EAX,ECX*4]   #只是将EAX,ECX*4这个地址编号存入到EAX中
    

5.寻址方式五[reg+reg*{1,2,4,8}+立即数]

  • 通过[reg + reg*1或者2或者4或者8 + 立即数 ]

  • 读取内存的值

    MOV EAX,0x13FFC4
    MOV ECX,2
    MOV EDX,DWORD PTR DS:[EAX+ECX*4+4]
    
  • 向内存中写入数据

    MOV EAX,0x13FFC4
    MOV ECX,2
    MOV DWORD PTR DS:[EAX+ECX*4+4],87654321
    
  • 获取内存编号

    LEA EAX,DWORD PTR DS:[EAX+ECX*4+2]
    

三、作业

1.内存读写练习

  • 每种寻址公式分别实现内存的读、写和取内存地址

    • 寻址公式一:[立即数]

      mov eax,dword ptr ss:[0x0019ff74]          #读取内存
      mov dword ptr ss:[0x0019ff74],0xAAAAAAAA   #写入内存
      lea eax,dword ptr ss:[0x0019ff74]          #取内存地址
      
    • 寻址公式二:[reg]

      mov eax,dword ptr ss:[esp]
      mov dword ptr ss:[esp],0xBBBBBBBB
      lea eax,dword ptr ss:[esp]
      

      注意mov指令两个参数不能同时为寄存器

    • 寻址公式三:[reg + 立即数]

      mov eax,dword ptr ss:[esp+4]
      mov dword ptr ss:[ebp-8],edx   #将edx中的值存入到[ebp-8]内存
      lea eax,dword ptr ss:[esp+8]
      
    • 寻址公式四:[reg + reg * {1,2,4,8}]

      mov eax,2
      lea ecx,dword ptr ss:[ebp]  #现在ecx中存的值即为栈底地址编号0x19ff80
      lea ebx,dword ptr ss:[esp]  #现在ebx中存的值即为栈顶地址编号0x19ff74
      ----------------------------------
      #mov edx,dword ptr ds:[ecx-eax*1]  不能是减法!!!
      mov edx,dword ptr ds:[ebx+eax*1]   #将0x19ff76地址编号以及往高位的后三位地址编号组合起来的数存入									  edx中
      mov edx,dword ptr ds:[ebx+eax*2]   #将0x19ff78地址中的值复制一份存入edx中
      ----------------------------------
      mov dword ptr ds:[esp+eax*2],ecx
      lea eax,dword ptr ds:[esp+eax*4]
      
    • 寻址公式五:[reg + reg * {1,2,4,8} + 立即数]

      mov eax,1
      mov ebx,dword ptr ss:[esp+eax*4+0x2]   #fa100019
      mov dword ptr ss:[esp+eax*4+0x2],edx
      lea eax,dword ptr ss:[esp+eax*4+0x2]
      
      屏幕截图 2021-11-24 113659
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值