2.汇编-内存

Asura 2017年09月17日 101次浏览

寄存器数量和容量有限,为了存储大量数据,所以我们需要内存

  1. 每个程序都会有自己的独立的4GB内存空间(

这里的内存其实是虚拟的,并不是真的给了程序4G内存,当程序读或者写这段内存的时候,操作系统才会把使用的内存映射到物理内存上
物理内存和内存条之间还有一层映射

WX20170916-044017

1Bit 就是一个位 也就是可以存储1个0或者1
1Byte(字节) = 8Bit
1KB = 1024Byte
1MB = 1024KB
1GB = 1024MB

内存地址

  1. 内存太大没法起名字,所以只能用编号,当我们想读取或者写入数据到内存的时候,就必须用到编号
  2. 这个编号又称为内存地址(32位,前面0可以忽略),换算成16进制,那么就是8个16进制数表示

WX20170916-044944@2x

为何32位中单个应用程序只能用4G内存?

因为内存地址只有32位 那么寻址只能是 0x000000000xffffffff
也就是0xffffffff +1(0x0也是一个地址) = 10000000 个Byte,
一个Byte(字节)可以存储8位(Bit) 那么可以存储 100000000 * 8 = 800000000个0或者1(16进制)
换算成10进制就是34359738368个Byte
通过计算(34359738368/8(Byte)/1024(KB)/1024(MB)/1024(GB)) 就是4GB

内存操作

  1. 立即数到内存(内存需要声明数据宽度,并且写入的数据必须和内存数据宽度匹配)

BYTE = 1字节 =8bit
WORD = 2字节 =16bit
DWORD = 4字节 =32bit

MOV BYTE PTR DS:[19FFF0],0xFF
MOV WORD PTR DS:[19FFF0],0xFFFF
MOV DWORD PTR DS:[19FFF0],0x12345678
  1. 寄存器值到内存

内存地址的每个编号,代表的是一个byte字节
那么我们写的word(双字节)和dword(四字节)的多出来宽度的数据哪里去了?
这里其实会往后写
比如往<code>写四字节 0x12345678
那么实际情况会是:

0x0019FFF012
0x0019FFF134
0x0019FFF256
0x0019FFF378

会连续使用4个字节的内存

MOV DWORD PTR DS:[19FFF0],EAX
MOV WORD PTR DS:[19FFF0],AX
MOV BYTE PTR DS:[19FFF0],AL
  1. 内存到寄存器
MOV EAX,DWORD PTR DS:[19FFF0]
MOV AX,WORD PTR DS:[19FFF0]
MOV AL,BYTE PTR DS:[19FFF0]
  1. 内存到内存

在汇编中,大多数操作都不可以内存到内存

内存的5种形式

立即数

  1. 读取内存的值:
MOV EAX,DWORD PRT DS:[0X19FFC4]
  1. 向内存中写入数据:
MOV DWORD PTR DS:[0X13FFC4],EAX

[REG] reg代表寄存器,可以使8个通用寄存器中的任意一个

  1. 读取内存的值:
MOV ECX,0X13FFD0
MOV EAX,DWORD PTR DS:[ECX]
  1. 向内存中写入数据:
MOV EDX,0X13FFD8
MOV DWORD PTR DS:[EDX],0X87654321

[REG+立即数]

  1. 读取内存的值:
MOV ECX,0X13FFD0
MOV EAX,DWORD PRT DS:[ECX+4]
  1. 向内存中写入数据:
MOV EDX,0X13FFD8
MOV DWORD PTR DS:[EDX+0XC],0X87654321

[REG+REG*{1,2,4,8}]

  1. 读取内存的值:
MOV EAX,13FFC4
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX*4],87654321
  1. 向内存中写入值:
MOV EAX,13FFC4
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX*4],87654321

[REG+REG*{1,2,4,8}+立即数]

  1. 读取内存的值:
MOV EAX,13FFC4
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX*4+4],87654321
  1. 向内存中写入值:
MOV EAX,13FFC4
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX*4+4],87654321

小端存储模式

内存地址对应一个内存单元
每个单元的大小就是8位(byte) 一个字节

WX20170916-071145

情况1:

MOV BYTE PTR DS:[0x00000000],0X1A
0x000000000x1A
0x00000001
0x……….

情况2:

MOV WORD PTR DS:[0x00000000],0x1A2C

分析:
以字节为单位:数据 0x1A2C1A为高位 2C为低位
内存 0x00000000 为低位 0x00000001 为高位

大端模式:

0x000000001A
0x000000012C

小端模式:

0x000000002C
0x000000011A

那么我们的存储到底用的那种模式呢?

在x86架构中绝大多数都是用的小端存储(非绝对,受编译器影响)
在arm中绝大多数采用大端模式存储(非绝对,受编译器影响)