delphi CPU窗口的扩展学习


本文整理自网络,侵删。

 
一、寄存器结构
这是一个寄存器的结构:


二、CPU窗口解释


图片左上角,有蓝色选中的那一块是反汇编窗口,这个窗口显示的是汇编代码
图片左下角是转储窗格,先来看看第一排:
00410000 49 00 41 00 64 FF 32 64 I.A.d.2d
00410000 这个暂时我还不清楚,应该是内存地址。
接下来我们来看看内存中的内容,也就是:
49 00 41 00 64 FF 32 64
首先它是8进制的,所以每个数字就代表一个字节,即4是一个字节,9是一个字节…
所以这边一共有16个字节(byte)
然后我们将他们转换成十进制:
73 0 65 0 100 255 56 100
然后对照ASCII码表:
I . A . d . 2 d

右上角那块是寄存器窗格,我们要知道CPU本身只负责运算,不负责储存数据,数据一般都储存在内存里。但是CPU的计算速度远远高于内存的读写速度,为了避免被拖慢,CPU一般自带一级缓存和二级缓存,基本上CPU缓存可以看出读写速度较快的内存。但是缓存还是不够快,另外数据在缓存里的地址是不固定的,cpu每次读写需要读址会拖慢速度,因此除缓存之外cpu还自带了寄存器。用来储存最常用的数据,哪些最频繁读取的数据(循环变量),都会放在寄存器里面,CPU优先读写寄存器,再由寄存器跟内存交换数据。
寄存器不靠地址区分数据而是靠名称。
早期的 x86 CPU 只有8个寄存器,而且每个都有不同的用途。现在的寄存器已经有100多个了,都变成通用寄存器,
我们常常看到32位CPU和64位CPU其实指的是寄存器的大小。

程序运行的时候,系统会给它分配一段内存用来储存程序和运行产生的数据。这段内存有起始地址和结束地址。比如从0x1000到0x8000(十六进制数用0X或0x做前缀,0是数字零,而不是字母o),起始地址是较小的那个地址,结束地址反之。这种由用户主动划分出来的内存区域叫做Heap(堆),它由起始地址开始,由低位(地址)向高位(地址)增长。Heap的一个重要特点是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。对,内存泄露泄露的就是heap。
而Stack是函数运行时占用的内存区域。
以一个简单的程序来说明stack和heap:
public void Method1(){
1. int i=1;
2. int k=2;
3. A a=new A();
4.}
代码执行到第1行 以后,将i=1入栈(push)。
同理 第2行 执行完了也会入栈,但这边要注意,出栈的时候是k=2先出
然后执行到第3行 这里的a是指针,要入栈,而A指向的真正的实例会存放在heap里,注意heap是无序的而stack是有序的。
所以这个时候stack里面有{i=1,k=2,a(指针)}
heap里面有{a指向的那个对象实例}

在这个函数执行完毕,stack和heap还会发生一些变化:
可以说是执行完第4行的时候,由于局部变量i,k还有指针a,执行完函数不起作用了,也就是说stack里面的{i=1,k=2,a(指针)}没有什么作用了。就会全部清空,stack为空{}.
由于在这个函数里,我们没有释放掉a指针指向的内存,所以heap里的内存会一直存在,如果有内存回收机制,就会回收掉。

在stack里面还有一个帧的概念。帧就是说系统开始执行函数的时候会为其建立一个帧(frame),所有函数的内部变量,比如上一个例子里的i,k,a都会保存在这个帧里面。函数执行结束后,该帧就会被回收释放所有的内部变量,不再占用空间。那么如果是A函数中调用B函数,那么B函数也会建立一个帧,简单来说,调用栈有几层,就有几帧。然后回收的时候是先从B函数的帧开始回收,也就是栈的后进先出。

stack是由内存区域的结束地址开始。高位(地址)向低位(地址)分配。比如内存区域的结束地址是0x8000,第一帧假定是16字节(一个内存地址代表一个字节的存储空间),这一次分配的内存是0x8000~0x7FF1那么下一次的分配地址就会从0x7FF0开始。

mov [a],b
将b内存中的所有字节传送到a中
mov a,[b]
将b内存中的4个字节传送到a中

注意:
*mov eax, [ebx-ecx] ; 只能用加法
mov [eax+esi+edi], ebx ; 最多只能有两个寄存器参与运算*

mov eax, [ebx] ; 将ebx值指示的内存地址中的4个字节传送到eax中

假设ebx指示的内存地址已经分配了4个字节,
那么将我假设的四个字节,字节A,字节B,字节C,字节D传送到eax中
字节A=00000001
字节B=00000010
字节C=00000011
字节D=00000100

三、关于声明
汇编语言中,声明内存大小事一般用DB(1byte),DW(2byte),DD(4byte)
但如果遇到没有DB,DW,DD声明的情况,如:
mov [ebx], 2
因为没有特殊的标识,所以不确定常数2是单字节还是双字节

四、一些思考
为什么数组里只能存放固定的数据类型呢?我的想法是这样的,因为数组给每一块空间分配的内存大小是一样的,比如说int是4个字节,所以数组里每一块空间都能保存四个字节的内容,而这个时候往数组里放其他数据类型,如果小了,那么空间就浪费了,如果大了,那就放不进去。所以规定职能存放固定的数据类型吧。
(java中的数据类型)
byte 8位 1字节
short 16位 2字节
int 32位 4字节
long 64位 8字节
float 32位 4字节
double 64位 8字节
char 16位 2字节

参考博客:http://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html

相关阅读 >>

Delphi createmessagedialog

Delphi 动态加载删除字体

Delphi tstrings 随机打乱

Delphi使用project manager添加一个java库到你的应用程序

Delphi通过post传递参数给php

Delphi inc函数和dec函数的用法

Delphi 在指定图片上绘制透明文字

Delphi中使用xmlhttp / xmlhttprequest 避免缓存

Delphi 代码查询一个 ip 地址的归属地

Delphi 2009 之 tstringbuilder 类[6]: equals

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...