过程
汇编源代码 -> 编译 -> 链接 -> 执行exe。
编译:将源码翻译成机器代码,生成目标(obj)文件。有 x 个源码文件就会生成 x 个目标文件。
链接:将目标文件进行链接,生成exe文件。
在dos中,shell是一直运行的进程,当执行汇编exe时,shell会将exe加载进内存,shell中断暂停运行,并设置CPU的CS:IP指向入口。exe执行结束后中断返回至shell,shell继续运行。
exe
exe中包含两部分文件,程序(exe)和数据;相关的描述信息(map),比如程序有多大,占用的内存空间等。
在操作系统中,操作系统依照可执行文件中的描述信息,加载机器码和数据,并进行相关初始化(比如设置cs:ip指向第一条要执行的指令),然后CPU执行程序。
dos加载exe的过程
- 找到一段起始地址SA:0,起始地址的偏移地址为0的容量足够的空闲内存区。
- 在这个内存去的前256个字节,创建一个数据区(PSP),DOS利用PSP来和家在程序进行通信。
- 程序被加载在PSP后面,程序地址被设为SA+10H:0。
- 将该内存区的段地址存入ds,初始化其他寄存器,设置CS:IP指向程序的入口。
为什么是 SA+10H:0
程序加载后,ds存放着程序所在内存区的段地址,这个内存区的偏移地址为0,即地址为ds:0。
这个内存区的前256个字节是PSP,256之后是程序。
所以,PSP的段地址是SA,PSP偏移地址是0,所以物理地址是SA*16 + 0。
因为PSP占用256字节,所以程序物理地址是:
SA * 16 + 0 + 256 = SA * 16 + 16 * 16 + 0 = (SA+16)*16 + 0
简化乘法分配律,即得SA + 10H:0。
SA * 16 + 0 是起始地址,加上 PSP 的大小后就是程序的物理地址。
源码分析
assume cs:code, ds: data, ss: stack
data segment
dw 1, 2, 3, 4
data ends
stack segment stack
dw 0H,0H,0H,0H
stack ends
code segment
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
mov cx, 8
mov ax, 4c00h
int 21h
code ends
end start
伪指令
汇编指令有对应的机器码指令,可以被编译为机器指令,CPU最终执行。
伪指令是编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。
XXX segemnt / XXX ends
这是一对指令伪指令,作用是定义一个段,segment说明一个段开始,ends说明一个段结束。
段名 segment
...
段名 ends
这里的段名可以任意取名。
end
这里的end是end start
中的end,不是段的ends,代表了对源程序的编译,写完程序要加上end,不然编译器不知道在何时结束。
start
start是一个标号,代表程序入口在此。程序加载到内存后,CS:IP会指向这个标号,从start指向的指令开始运行。
start换成main也行,start不一定在程序代码最前面,也有可能在中间,前面是可以有指令或者数据的,但这样很不规范,在代码段里放置变量。
assume
定义标记符,将segement...end的段和某一寄存器相关联。
assume cs:code
定义了一个代码段,使用了assume来关联了cs寄存器。
程序的返回
当程序运行结束之后就要返回,返回程序段如下。
mov ax, 4c00H
int 21H
调用 INT 21H 的 4CH 号中断,安全退出程序。
标签:汇编,exe,16,程序,mov,helloWorld,SA,PSP From: https://www.cnblogs.com/hatsuzuki/p/17596706.html