1.一个源程序从写出到执行的过程

1.一个汇编语言从写出到最终执行

1
2
3
4
5
1.编写:用文本编译器,用汇编语言编写编写汇编源程序
记事本,Nodepad++, UltraEdit
2.编译连接
1.使用汇编语言编译程序【MASM.EXE】对源程序文件中的源程序进行编译,生成目标文件
2.用连接程序【LINK.EXE】对目标文件进行连接,生成可在操作系统中直接运行的可执行文件

2.可执行文件包含:

1
2
1.程序【从源程序中的汇编指令翻译过来的机器码】和数据【源程序中定义的数据】
2.相关的描述信息【程序有多大,要占多少内存空间】

3.执行可执行文件的程序

1
2
1.在操作系统中,执行可执行文件中的程序
2.操作系统依照可执行文件中的描述信息,将可执行文件中的机器码和数据加载入内存,并进行相关的初始化(比如:设置CS:IP指向第一条要执行的指令)然后由CPU执行程序

2.源程序

1
2
3
4
5
6
7
8
9
10
11
assume cs:codesg
codesg segment
start: mov ax,0123H
mov bx,0456H
add ax,bx
add ax,ax

mov ax,4c00h
int 21h
codesg ends
end start

1.汇编指令,有机器码一一对应的,被cpu’执行

2.伪指令 > 给编译器看的

1
2
3
4
5
6
7
8
9
segment 和 ends 是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指令。它们的作用就是定义一个段

segment 就是段的开始
ends 就是段的结束
一个段,需要由一个段名来标识:

格式:
段名 segment
段名 ends

3.定义一个段

1
2
1.一个汇编程序是由多个段组成的,这些段用来存放代码,数据,或者被当作栈空间来使用
2.一个由意义的汇编程序中至少要由一个段,这个段用来存放代码

4.end是一个汇编程序的结束标记,end是伪指令

5.assume:假设

1
2
它假设某一段寄存器和程序中的某个用segment  ends定义的段相关联
通过assume说明这种关联,在需要的情况下,编译程序将段寄存器和某一个具体的段相联系
1
2
3
总而言之:就是说assume将有特殊用途的段和相关的段寄存器相关联起来
比如:assume cs:codesg
就是将要用作代码段的段-->codesg【这个是人为起的名字】和CPU中的段寄存器cs联系起

image-20230409120205822

!!!重点来了

源程序文件被编译器编译过后,就编程了程序,放在可执行文件中,可执行文件就是PE的一种格式

6.标号–相当于指针

1
2
1.一个标号指代了一个地址
2.codesg:放在segment的前面,作为一个段的名称,这个段的名称最终被编译连接程序处理为一个段的地址

7.DOS是一个单认为操作系统

8.程序返回

1
2
3
4
5
1.我们的程序最先以汇编指令的形式存在源程序中,经编译,连接后转变为机器码,存储在可执行文件中。
2.一个程序结束后,将CPU的控制权交还给使他得以运行的程序,这个过程就是:程序返回
3. mov ax,4c00H
int 21H ; 中断机制
这两条指令所实现的功能就是程序返回

3.编辑源程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
assume cs:codesg
codesg segment
start: mov ax,0123H
mov bx,0456H
add ax,bx
add ax,ax

mov ax,4c00h
int 21h
codesg ends
end


保存到1.asp

4.编译

这里我不是很会

在我的电脑上是用:dosbox

1
2
3
mount c d:\masm
c:
masm 1.asm

我学汇编就只是会就好了

5.连接

连接是用link

1
具体内容可以查书

6.以简化的方式进行编译和连接

1
2
3
就是在最后加上  ;  

masm 1.asp;

7.exe的执行

执行就好了三

8.谁将可执行文件中的程序装载进入内容并使他运行?

首先来补充一点知识

操作系统的外壳是什么?

1
操作系统,都需要提供一个称为shell的程序【用于来操作计算机系统进行工作】

可执行文件中的程序装入内存并运行的原理

汇编程序从写出到执行的过程

1
2
编程->1.asm->编译->1.obj->连接->1.exe->加载->内存中的程序->运行
edit masm link command cpu

4.9程序执行过程的跟踪

首先先写一个东西,放入2.asp中,然后使dosbox

1
2
3
masm 2.asp
link 2.obj
debug 2.exe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
assume cs:codesg

codesg segment

fishcc: mov ax,0123H
mov bx,0456H
add ax,bx
add ax,ax

mov ax,4c00H
int 21H

codesg ends

end fishcc

image-20230410125716706

首先在cs里面是指令的长度

1
2
这里是000F
说明长度是15字节

在DOS系统中.exe文件中的程序加载过程如下

image-20230410130359400

我们从上面的那个dos窗口就可以发现CS的值比DS的值要大10H,在计算成段地址后*16后就相当于是大了100H也就是256个字节

这个是为什么呢?

1
上图解释得比较清楚

当然我们也可以看一下这些地方都存了什么JB玩意

image-20230410131327202

这些应该就是它所说的PSP什么什么的

image-20230410131436362

这些才是我们写入的指令,也就是程序真正的指令

很重要的总结

1.程序加载之后,ds中存放着程序所在内存区的段地址,这个内存区的偏移地址为0,则程序所在的内存区的地址为 ds:0

2.这个内存区的前256 [100H]个字节中存放的是psp【我也不知道是什么玩意】,反正就是用来dos和程序进行通讯

3.从256字节处向后的空间存放的是程序【也就是我们写进去的东西】

4.所以我们在ds中可以得到psp的段地址SA,psp的偏移地址是0,则物理地址就是SA*16+0

5.因为PSP占256(100H)个字节,所以程序的物理地址是:SA×16+0+256=SA×16+16×16,可用段地址和偏移地址表示SA+10:0【这里是在经过化工场之前,所以是+10而不是100,在经过化工厂后它会向左偏移一位】

1
2
3
用u命令查看一下其他指令:
用T命令单步执行程序中的每一条指令,并观察美条指令执行的结果
到了int21,就需要用p命令执行

image-20230410132832513

看到int 21 就用p【屁股一下】

我们在dos中运行 debug 1.exe的时候

是command加载debug ,debug加载1.exe
所以在退出的时候,要先返回debug 这个就是 p【命令】 然后返回command 这个用 q【命令】