C++ 逆向辅助学习----汇编基础 寄存器(内存访问) 3

61 篇文章 2 订阅
17 篇文章 2 订阅

寄存器(内存访问)
   1.1    内存中字的存储
        20000                     0x4E 20        
        a) Little - Endian (小端)就是低位字节放在内存的低地址端,高位字节放在内存的高地址端
        b) Big - Endian    (大端)就是高位字节放在内存的低地址端,低位字节放在内存的高地址端
               网络字节顺序(也就是大端模式)
               
                int a = 20000;  0x00004e20
                int* p = &a;
                printf("p=0x%p\n",p);   

            p                        
          0x004CFE44            20
          0x004CFE45            4e
          0x004CFE46            56
          0x004CFE47            43
                                
                
    1.2 DS和[address]
        1.2.1 内存单元地址
              - CPU要读取一个内存单元的时候,必须先给出这个内存单元的地址;
              - 在8086PC中,内存地址由段地址和偏移地址组成。
              - 8086CPU中有一个 DS寄存器,通常用来存放要访问的数据的段地址。       
                              
        1.2.2 mov指令传送功能     
            (1)将数据直接送入寄存器;
            (2)将一个寄存器中的内容送入另一个寄存器中。
            (3)mov 指令 还可以将一个内存单元中的内容送入一个寄存器,
                 或者将寄存器中的数据写入内存单元
        
        1.2.3 字的传送(练习)        
           (1)
            1000:0  10000H   1123H
            ax = 1123H    

            1000:2  10002H   6622H
            bx = 6622H
            
            1000:1  10001H   2211H
            cx = 2211H
            
            1000:1  10001H   2211H
            add bx,[1] => add bx,2211H
            bx = bx + 2211H = 6622H + 2211H = 8833H
            
            1000:2  10002H   6622H
            add cx,[2] = add cx,6622H
            cx = cx + 6622H = 2211H + 6622H = 8833H
        
         1.2.4 mov、add、sub指令
 
         1.2.5 数据段              
                将一段内存当作数据段,是我们在编程时的一种安排,
                我们可以在具体操作的时候 ,用 ds 存放数据段的段地址,
                再根据需要,用相关指令访问数据段中的具体单元。
        
         1.2.6 检测点3.1
            (1)
               ds = 1
            
            MOV AX,[0000]            
            1:0    1*16 + 0 = 10H    AX = 2662H
                        
            MOV BX,[0001]
            1:1    1*16 + 1 = 11H    BX = E626H

            MOV AX,BX       AX = E626H
            MOV AX,[0000]   AX = 2662H
            
            MOV BX,[0002]  
            1:2   1*16 + 2 = 12H     BX = D6E6H
            
            ADD AX,BX    AX = FD48H
            
            ADD AX,[0004]
            1:4  14H      AX = FD48H + 2ECCH = 2C14H 舍去溢出部分
        
            mov ax,0        ax = 0

            mov al,[0002]         
            1:2  12H       al = e6H   ax = 00e6H
                            
            mov bx,0       bx = 0
            
            mov bl,[000c]  bl = 26H  BX = 0026H
            
            add al,bl    al = 0cH    ax =  000CH
        
          
           (2)
             MOV AX,6622H   CS=2000H  IP=0    DS=1000H AX=6622H BX=0
             JMP 0FF0:0100  CS=0FF0   IP=100H DS=1000H AX=6622H BX=0
             MOV AX,2000H   CS=0FF0   IP=103H DS=1000H AX=2000H BX=0
             MOV DS,AX      CS=0FF0   IP=105H DS=2000H AX=2000H BX=0
             MOV AX,[0008]  CS=0FF0   IP=108H DS=2000H AX=C389H BX=0
             MOV AX,[0002]  CS=0FF0   IP=10BH DS=2000H AX=EA66H BX=0
            
        
    1.3 栈
       1.3.1  栈是一种具有特殊的访问方式的存储空间。它的特殊性就在于,
               最后进入这个空间的数据,最先出去。
        
       1.3.2 栈有两个基本的操作:入栈和出栈。
                入栈:将一个新的元素放到栈顶;
                出栈:从栈顶取出一个元素。
                
              栈顶的元素总是最后入栈,需要出栈时,又最先被从栈中取出。
              栈的操作规则:LIFO(Last In First Out,后进先出)
    
          1.3.3 CPU提供的栈机制
          (1) 8086CPU提供入栈和出栈指令: (最基本的)
                 PUSH(入栈)
                 POP  (出栈)
        
               push ax:将寄存器ax中的数据送入栈中;
               pop ax :从栈顶取出数据送入ax。
                  
               8086CPU的入栈和出栈操作都是以字为单位进行的。
    
          (2) 8086CPU中,有两个寄存器:
                段寄存器SS  存放栈顶的段地址
                寄存器SP     存放栈顶的偏移地址
            任意时刻,SS:SP指向栈顶元素。
    
        1.3.4  push 指令的执行过程
            push ax
            (1)SP=SP–2;
            (2)将ax中的内容送入SS:SP指向的内存单元处,
                 SS:SP此时指向新栈顶。
         
              任意时刻,SS:SP 指向栈顶元素,当栈为空的时候,栈中没有元素,
              也就不存在栈顶元素,所以SS:SP 只能指向栈的最底部单元下面的单元,
              .该单元的偏移地址为栈最底部的字单元的偏移地址+2,栈最底部字单元
              的地址为1000:000E,所以栈空时,SP=0010H。

       1.3.4 pop 指令的执行过程
            (1)    pop ax
                    (1)将SS:SP指向的内存单元处的数据送入ax中;
                    (2)SP = SP+2,SS:SP指向当前栈顶下面的单元,
                       以当前栈顶下面的单元为新的栈顶。
                
                注意:
                 出栈后,SS:SP指向新的栈顶 1000EH,pop操作前的栈顶元素,
                 1000CH 处的2266H 依然存在 ,但是,它已不在栈中。
                
                 当再次执行push等入栈指令后,SS:SP移至1000CH,并在里面写入新的数据,
                 它将被覆盖。

       1.3.5 栈顶超界
             (1)  当栈满的时候再使用push指令入栈,
                  栈空的时候再使用pop指令出栈,
                  都将发生栈顶超界问题。

             (2)  栈顶超界是危险的。

            
             (3) 8086CPU的工作机理,只考虑当前的情况:
                  当前栈顶在何处;
                  当前要执行的指令是哪一条。
            
       1.3.6 栈与内存
            栈空间当然也是内存空间的一部分,它只是一段可以以一种特殊的方式进行访问的内存空间。

       1.3.7 push、pop指令     
            push和pop指令的格式(1)
                push 寄存器:将一个寄存器中的数据入栈
                pop寄存器:出栈,用一个寄存器接收出栈的数据    
                例如:push ax
                      pop bx

            push和pop指令的格式(2)
                push 段寄存器:将一个段寄存器中的数据入栈
                pop段寄存器:出栈,用一个段寄存器接收出栈的数据    
                例如:push ds
                      pop es

            push和pop指令的格式(3)
                push内存单元:将一个内存单元处的字入栈(栈操作都是以字为单位)
                pop 内存单元:出栈,用一个内存字单元接收出栈的数据
                例如:push [0]
                      pop [2]


       1.3.9 问题分析
           (1) 3.7         10000H ~ 1000FH   16字节
             mov ax,1000H
             mov ss,ax
             mov sp,0010H
             push ax
             push bx
             push ds
             
            (2) 3.8  10000H ~ 1000FH  ss:1000H  sp=?
            
             mov ax,1000H
             mov ss,ax
             mov sp,0010H
             mov ax,001AH
             mov bx,001BH
             push ax
             push bx
             sub ax,ax
             sub bx,bx
             pop bx
             pop ax
                 
            结论:
              从上面的程序我们看到,用栈来暂存以后需要恢复的寄存器中的内容时 ,
              出栈的顺序要和入栈的顺序相反,因为最后入栈的寄存器的内容在栈顶 ,
              所以在恢复时,要最先出栈。
              
          (3) 3.9
             mov ax,1000H
             mov ss,ax
             mov sp,0010H
             mov ax,001AH
             mov bx,001BH
             push ax
             push bx
             sub ax,ax
             sub bx,bx
             pop ax
             pop bx

          (4)3.10
           栈内存示意:
           10000H  66  
           10001H  22
           10002H      <- sp    

             mov ax,1000H
             mov ss,ax
             mov sp,0002H
             mov ax,2266H
             push ax

      1.3.11 栈段
          我们可以将长度为 N(N ≤64K )的一组地址连续、起始地址为16的倍数的内存单元,
          当作栈来用,从而定义了一个栈段。
            
      1.3.13 段的综述
          我们可以将一段内存定义为一个段,用一个段地址指示段,
          用偏移地址访问段内的单元。这完全是我们自己的安排。
            
          我们可以用一个段存放数据,将它定义为“数据段”;
          我们可以用一个段存放代码,将它定义为“代码段”;
          我们可以用一个段当作栈,将它定义为“栈段”;
          
          我们可以这样安排,但若要让CPU按照我们的安排来访问这些段,就要:
            - 对于数据段,将它的段地址放在 DS中,用mov、add、sub等访
              问内存单元的指令时,CPU就将我们定义的数据段中的内容当作
              数据段来访问;
              
            - 对于代码段,将它的段地址放在 CS中,将段中第一条指令的偏移地址放在IP中,
              这样CPU就将执行我们定义的代码段中的指令;
          
            - 对于栈段,将它的段地址放在SS中,将栈顶单元的偏移地置放在 SP 中,
              这样CPU在需要进行栈操作的时候,比如执行 push、pop 指令等,就将我们
              定义的栈段当作栈空间来用。
 
         总结:
            一段内存,可以既是代码的存储空间,又是数据的存储空间,还可以是栈空间,
            也可以什么也不是。关键在于CPU中寄存器的设置,即:CS、IP、SS、SP、DS的指向。

        
        检测点3.2:
            (1)
             把2000H安排为栈段
            
             mov ax,2000H
             mov ss,ax
             mov sp,0010H
            
            
           (2)
             把1000H安排为栈段
            
             mov ax,1000H
             mov ss,ax
             mov sp,0H
            
            
        实验任务:        
             mov ax,[0]    ;ax = C0EAH
             add ax,[2]    ;ax = C0FCH
             mov bx,[4]    ;bx = 31F0H
             mov bx,[6]    ;bx = 30F0H
           
             push ax       ;sp = 00FEH  修改的内存单元地址是2200:00FE 内容为C0FCH
             push bx       ;sp = 00FCH,修改的内存单元地址是2200:00FC 内容为6021H
             pop  ax       ;sp = 00FCH, ax = 6021H
             pop  bx       ;sp = 00FEH, bx = COFCH

             push [4]      ;sp = 00FEH ,修改的内存单元地址是2200:00FE 内容为2F31H            
             push [6]      ;sp = 00FCH ,修改的内存单元地址是2200:00FC 内容为30F0H

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值