7.12 王爽汇编语言(九)
中间笔记
要完整的描述一个内存单元,需要两种信息: (1)内存单元的地址; (2)内存单元的长度;
# [bx]表示一个内存单元,该内存单元的偏移地址保存在 bx 寄存器中;
# 如下例子解释:将一个内存单元的内容送入 ax, 这个内存单元的长度为 2 字节(字单元),
# 存放一个字,偏移地址在 bx 中,段地址在 ds 中;
mov ax,[bx]
# 如下例子解释:将一个内存单元的内容送入 al,这个内存单元的长度为 1 字节(字节单元),
# 存放一个字节,偏移地址在 bx 中,段地址在 ds 中;
mov al,[bx]
在后续汇编语言学习过程中,书上将使用一个描述性符号"()"来表示一个寄存器或一个内存单元 中的内容,比如(ax)表示 ax 中的内容,详情见 P96;
约定符号 idata 表示常量,详情见 P96;
# 新指令 loop
# cs 和 loop 指令相配合实现循环功能的 3 个要点
(1)在 cx 中存放循环次数;
(2)loop 指令中的标号所标识地址要在前面;
(3)要循环执行的程序段,要写在标号和 loop 指令的中间。
# cx 和 loop 指令配合实现循环功能的程序框架如下:
mov cx, 循环次数
s:
循环执行的程序段
loop s
注意'int 21'指令在 debug 调试时要用 p 命令执行;
新学到指令 g,可以使用 g 指令直接执行到指定代码; 比如 "g 0016"表示直接执行到 (cs):0016 的代码处,之前的所有代码都被执行; g 还可以应用到结束 loop 上;p 命令也可以应用到 loop 上;
# 知道为什么在汇编语言源程序中使用 [bx] 来保存需要访问的内存单元的偏移地址了
因为我们运行 debug.exe 来编写汇编指令的时候,经常使用 mov ax, [idata]来获取内存单元的数据(idata在这里指常量,比如 1, 2, 3, 4,5)。
但是我们在编写汇编语言源程序的时候,mov ax, [idata] 会被汇编语言编译器解释成 mov ax, idata(进而就变成了“将常量赋值给 ax 寄存器了,而不是获取内存单元数据了”)
# 对以上问题书上给的解决办法如下:
mov al, ds:[0] # 如果一定要写常量,那么在 [idata] 前加上保存内存单元段地址的寄存器(寄存器不仅限于 ds 寄存器,其它寄存器也可以,详情见 P117)
mov al, [bx] # 之前的思路,使用寄存器 bx 保存内存单元的偏移地址
mov al, ds:[bx] # 跟上面类似,在我看来就是属于“脱了裤子放屁”(“脱下裤子放屁”:此话通常用来讥讽别人说话做事画蛇添足、多此一举。)
dos 方式下,我们如果要往一段内存里面写入内容时,就使用 0:200~0:2ff这段空间,一般来说这段空间是“安全的“;
总结
学习了用 debug.exe 来调试 exe 可执行文件之后,我大概明白了为什么别人能逆向出源程序的动作了;因为之前由别的程序,比如 powershell.exe 加载的 exe 程序到内存,powershell 将 CPU 控制权直接交给 exe 程序;而平常的逆向 debug 工具,没有交出 CPU 控制权,所以可以单步调试下去;