Post

汇编语言程序

汇编程序

汇编语言程序
目录

汇编程序

Debug 的汇编程序与 源程序编译的汇编程序 的区别
Debug:

  • 使用功能简单、短小精悍的程序
  • 只需要包含汇编指令

源程序:

  • 编写大程序
  • 需要包含汇编指令、指导编译器工作的伪指令
  • 源程序由段组成、这些段用来存放代码、数据、或用作栈空间
  • 注释符号: ;

源程序

  • 伪代码
    • 指导编译器 完成相关的编译工作
  • 汇编代码
    • 可转换成对应的机器指令,由CPU执行

编写步骤:

  1. 定义一个段
    • name segmeng … name ends
  2. 书写汇编指令
    • 放在段定义中
  3. 指出程序结束
    • end 写在最后
  4. 关联段和寄存器
    • assume cs:name
  5. 程序返回代码
    • 固定的代码,写在执行段的定义中
    • mov ax, 4c00h
    • int 21h

源文件 -> 程序运行

$源文件\underset{编译}{\longrightarrow}OBJ文件\underset{连接}{\longrightarrow}EXE文件$

编译工具 masm

将源文件编译成为 目标文件

masm name[.asm][;]

  • 默认文件后缀为 .asm
  • 加 ; 可以简化过程

相关的中间文件:

  • 列表文件
  • 交叉引用文件

将目标文件文件 连接成 可执行文件

相关文件:

  • 映像文件(.MAP)
    • 连接成可执行文件时,产生的中间结果
  • 库文件(.LIB)
    • 包含了可调用的子程序

程序运行的 debug 和 跟踪

程序的执行方式:

  1. DOS执行
    • 由命令解释器(command.com)控制
    • command 将程序加载入内存,设置CPU的CS:IP
    • 程序结束后,CPU返回到 命令解释器,继续运行 command
  2. Debug执行
    • command 加载 Debug.exe
    • debug 将程序载入内存
    • 程序结束后,返回到Debug
    • 退出Debug时,返回到command
程序载入debug:
  • [DS, CS) — PSP(Process Segment Prefix) 程序段前缀
  • [CS, CS+CS] — 代码段

  • DS — 程序在内存中的 段地址
  • PSP — DOS与程序通信
  • CS — 代码的长度(字节)

例子:

跟踪 与 运行命令
t
p
g 直接运行到断点 或 程序正常结束

[…] 与 (…)

[…]

  • 是汇编语法
  • 表示内存单元

(…)

  • 学习时使用
  • 代表内存单元 或寄存器中的 内容

loop 指令

与 cx 寄存器联合使用

  • 每次执行loop命令时
    1. cx 减 1
    2. 判断 cx 是否为0
      • 为 0 执行下面命令
      • 不为 0 ,更改 IP 为指定值
  • 即循环次数 = cx
1
2
s:  add ax, [2]
    loop s

段前缀的使用

1
2
3
4
5
6
    mov ax, 2000h
    mov ds, ax
    mov bl, [1]
    ;mov bl, 01   若不加段前缀,则直接放入数据
    mov ax, [bx]
    ;mov ax, ds:bx  寄存器不加段前缀时,默认为 ds

指定段前缀:

  • ds:[bx]
  • ds:[0]
  • es — 为附加段,用作同时对两个段的内存进行操作

代码段中写入数据

写入数据的方式
  • dw — 写入字
  • db — 写入字节
  • dd — 写入双字
写入的数据在内存中的存储情况

代码段

  1. 写入的数据
  2. 执行的指令

问题: IP地址默认指向数据内存单元、而非指令

解决方法:

1
2
3
4
5
6
assume cs:code
code segment
        dw 0134h,1234h
[name:] [code]
end [name]
; IP 偏移至 name 

代码段中使用栈

  • 定义的数据放在代码段中
  • 栈需要的内存空间 通过定义 空 数据取得
    • dw 0,0,…

程序分段书写

  • 数据段
  • 栈段
  • 代码段

分段书写的步骤:

  1. 定义各段内容
  2. 数据段中准备工作
    1. 初始化各段寄存器
    2. mov ax, stack;此处 stack 为 栈段的地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
assume cs:code, ds:data, ss:stack
;指定段寄存器的分段名

data segment
    dw ..,..
stack segment
    dw ..,..
code segment
start:mov ...,..
      ...
      mov ax, 4c00h
      int 21h
code ends
end start

其它指令

inc

自增1

写程序易错点

注:

  1. 数据写入寄存器时,不能是字母开头
    例如
    $\times$ mov ax, ffffh
    $\checkmark$ mov ax, 0ffffh
  2. 段寄存器之间不可以直接赋予 例如
    $\times$ mov ss, cs
    $\checkmark$ mov ax, cs mov ss, ax
This post is licensed under CC BY 4.0 by the author.