【汇编】汇编的helloWorld

发布时间 2023-08-01 17:37:42作者: 阿初

过程

汇编源代码 -> 编译 -> 链接 -> 执行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的过程

  1. 找到一段起始地址SA:0,起始地址的偏移地址为0的容量足够的空闲内存区。
  2. 在这个内存去的前256个字节,创建一个数据区(PSP),DOS利用PSP来和家在程序进行通信。
  3. 程序被加载在PSP后面,程序地址被设为SA+10H:0。
  4. 将该内存区的段地址存入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 号中断,安全退出程序。