Post

汇编基本概念

汇编入门概念

汇编基本概念
目录

入门知识

课程内容

  1. 课程指南
  2. 访问寄存器和内存
  3. 汇编语言程序
  4. 内存寻址方式
  5. 流程转移与子程序
  6. 中断及其应用
  7. 高级汇编语言技术

课程指南

定位

  • 理解硬件结构
  • 掌握指令集
  • 理解程序的运行过程

内容:入门级指令集、作为80x86,linux,arm等的前置知识体系

  • 8088
  • 8086

学习方法:

  • 贯穿实践
  • 观察机器内部的状态
  • 学习进程

编程语言与指令

机器语言与机器指令

  • 机器语言:机器指令的集合
  • 机器指令:机器可以正确执行的命令
    • 由一串二进制数表示
    • 电平脉冲(用高低电位表示0、1)

汇编语言与汇编指令

  • 汇编语言:汇编指令的集合
  • 汇编指令:机器指令的助记符
    • 便于记忆的书写格式

汇编语言编写过程:

    flowchart LR
    pro[程序员]-->ins[汇编指令]-->complier[编译器]-->machine[机器码]-->cp[计算机]

汇编语言结构:

  • 伪指令 — 由编译器执行
  • 其它符号 — 由编译器识别
  • 汇编指令 — 机器码的助记符

寄存器与内存

预习与回顾(对照王爽教材 第三版)

CPU中的寄存器

8086CPU有14个寄存器:

  • 通用寄存器:AX、BX、CX、DX ;
  • 变址寄存器:SI、DI ;
  • 指针寄存器:SP、BP ;
  • 指令指针寄存器: IP ;
  • 段寄存器:CS、SS、DS、ES ;
  • 标志寄存器:PSW : 共性:
  • 8086CPU所有的寄存器都是16位的, 可以存放两个字节。

在 x86 架构的汇编语言中,常用的寄存器有:

  1. AX
    • 全写:Accumulator Register
    • 作用:用于算术运算、I/O 操作。
  2. BX
    • 全写:Base Register
    • 作用:用于基址的存储,通常用于指向数据段中对象的起始位置。
  3. CX
    • 全写:Counter Register
    • 作用:用于循环操作的计数器。
  4. DX
    • 全写:Data Register
    • 作用:用于存放 I/O 操作的地址或数据。
  5. SI
    • 全写:Source Index
    • 作用:作为源地址的指针,用于字符串操作。
  6. DI
    • 全写:Destination Index
    • 作用:作为目的地址的指针,用于字符串操作。
  7. BP
    • 全写:Base Pointer
    • 作用:用于指向栈中的数据,常用于高阶语言的局部变量访问。
  8. SP
    • 全写:Stack Pointer
    • 作用:指向栈顶,用于栈操作。
  9. IP
    • 全写:Instruction Pointer
    • 作用:指向下一条执行的指令。
  10. CS
    • 全写:Code Segment
    • 作用:指向代码段的起始地址。
  11. DS
    • 全写:Data Segment
    • 作用:指向数据段的起始地址。
  12. SS
    • 全写:Stack Segment
    • 作用:指向栈段的起始地址。
  13. ES
    • 全写:Extra Segment
    • 作用:额外的数据段,用于字符串操作。
  14. FS
    • GS
    • 全写:General Purpose Segment
    • 作用:额外的段寄存器,提供更多段地址。
兼容性问题

问题:8086上一代CPU中的寄存器均是8位,如何确保程序的兼容性?
方案:通用寄存器分为两个独立的8位寄存器使用
细化:

  • AX可以分为 AH 和 AL
  • BX可分为 BH BL
  • CX可分为 CH CL
  • DX可分为 DH DL
字长和字

通常说的多少位CPU,指的是CPU有多少位的字长
8086是16位CPU,它的字长(word size)是16bit
一个n位的cpu中,一个字可以存在n位的寄存器里

物理地址 和 寻址能力的矛盾

矛盾:

  • 寻址能力由字长决定 – 即16位字长的地址也是16位,寻址能力只有64K
  • 而物理地址有 20位 ,1 M的地址

解决方法:

  • 用两个16位地址(段地址、偏移地址)合成一个20位的物理地址
  • 地址加法器合成地址的方法:物理地址=段地址左移4位 + 偏移地址

段地址$\times16+$偏移地址=物理地址 的本质含义

  • 用一个基础地址(16位的段地址),加上相对于基础地址的偏移地址,给出内存单元的物理地址

内存的分段表示法

内存本身是一体的,分段来自于CPU

基本事实
  1. 段地址x16 必然是16的倍数,意味着一个段的起始地址也是16的倍数
  2. 偏移地址是16位,16位地址的寻址能力是64k,因此一个段的最大长度为64k

存储单元地址的表示方法、例子:
数据存在 21F60H 中,段地址是 2000H

  1. 数据存在内存 2000H:1F60H 单元中
  2. 数据存在内存的 2000H段中的 1F60H 单元中
段地址的重要性

由于段地址的重要性,有专门用来存放 段地址的寄存器。

  • CS - 代码段寄存器
  • DS - 数据段寄存器
  • SS - 栈段寄存器
  • ES - 附加段寄存器

偏移地址可以用多种方法提供 — 形成8086丰富的取址方式
掌握汇编语言是 学会活用 丰富的取址方式 的过程

Debug的使用

在DOSBOX中 挂载指定目录到 C盘, 并转到C盘

1
2
mount c e:\dailyfile\codefile\masm
C:
相关命令
  1. r - 寄存器相关操作
    • r 寄存器名 - 修改指定寄存器内容
  2. d - 查看内存
    • d 列出预设地址内存 8行 x 16列个 字节, 即128个字节
    • d 段地址:偏移地址 [数量]- 列出指定地址的内容,[可指定列出范围]
  3. e - 修改内存内容
    • e 段地址:偏移地址 数据1 数据2 …
    • e 段地址:偏移地址 - 询问式修改
      • 空格 - 接受并继续
      • 回车 - 结束
  4. u - 将机器指令翻译成 汇编指令 查看
  5. a - 用汇编指令的形式写入内存
  6. t - 逐条执行 CS:IP 处的指令
    • 可通过r 修改 CS:IP 的位置
  7. q - 退出 debug

g命令

在 DOSBox 中使用 debug 工具时,g 命令是一个非常重要的指令,用于控制程序的执行。下面是详细的解释和用法:

g 命令概述

g 命令用于启动被调试程序的执行,或继续执行之前被暂停的程序。可以按指定的地址或断点进行跳转。

语法

g[=address] [address [address [...]]]

参数说明
  • address: 可选的参数,指定程序继续执行的起始地址。如果省略,则从当前地址开始执行。
  • address [address [...]]: 可选的,指定一个或多个断点地址。如果执行达到这些地址中的任一个,程序将暂停,并返回到调试器。
使用示例
  1. 从当前地址开始执行:

    g

    它将从当前的指令开始继续执行程序。

  2. 从指定地址开始执行:

    g=CS:100

    将从代码段寄存器 (CS) 和 100 偏移(如 CS:100)处开始执行。

  3. 设置断点:

    g 200 250 300

    将从当前地址开始执行,并在地址 200, 250, 300 处设置断点,如果执行到这些地址之一,程序将暂停。

示例解释

假设你正在调试一个简单的程序,并希望代之从地址 0x100 处继续执行,且在地址 0x1500x1A0 处设置断点:

  1. 启动 debug 并加载程序:

    debug myprog.exe

  2. 显示当前寄存器和状态,并查看当前地址:

    -r

  3. 使用 g 命令执行程序,并在特定的断点处暂停:

    -g=100 150 1A0

这样,debug 将从 0x100 处开始执行,当指令指针达到 0x1500x1A0 时,程序将暂停并返回到调试器界面,你可以继续调试程序。

注意事项
  • 如果没有指定断点,程序将在运行到底后停止调试。
  • 设置的断点无论是否真正命中,如果程序遇到非法操作或其他错误,同样会终止并返回调试器。
  • CS 代表当前段寄存器,通常在 16 位段的程序中会使用。

通过正确利用 g 命令,你可以高效地控制程序的执行流,设置断点并进行详细的调试分析。

修改CS:IP

  1. Debug中,通过 rcs/rip 进行修改
  2. 汇编代码中,通过 jmp 指令修改
    • jmp cs:ip 指定跳转cs、ip
    • jmp ax 仅更改 ip 为对应的寄存的值

字在内存中的存储

对8086CPU, 16位作为一个字

  1. 16位的字 在寄存器中的存储
    • 例如:3E20
    • 高位放高字节、低位放低字节
    • AH存高位(3E), AL存低位(20)
  2. 连续内存,在内存中的存储
    • 低位在低地址、高位在高地址
    • $4E20 \underset{存放地址}{\longrightarrow} 204E$

注意区分:
字节型数据 & 字型数据
字型 — 16位CPU,即是4位16进制数 字节型 — 即,1字节 - 8位 - 2位16进制数

DS

DS是数据段寄存器(Data Segment Register)的缩写。它用来指向内存中的数据段,帮助程序访问特定的数据区域。比如,当你需要读取或存储数据时,DS会提供基础地址。

1
2
3
mov ax, 1000H
mov ds, ax
mov ax, [0]   -- 1000:0 的数据赋给ax

mov ax, [0]

栈及栈操作

SS、SP —- 栈段、栈顶指针

SS 指向栈的顶部(最低地址)
SP 指向栈底(最高地址) — SP初始指向的地址不存放数据、表示空栈 栈的大小 — 初始状态下的 SP - SS 即是栈的大小

关于栈的超界问题

  • CPU不会检测栈的是否超界
  • 需要程序员自己把握栈的大小
栈的操作

栈的每一操作,都是对一字长的数据进行操作

  • push ax
    • 将 ax 的数据 压入栈中
    • 每压入一个,SP往前移动一个字长
  • pop ax
    • 将 栈顶数据弹出, 存入 ax
    • 每弹出一个,SP往后移动一个字长

段的总结

  • DS — 数据段
    • 通过访问内存单元 []
  • CS — 代码段
    • CS/IP(指令指针寄存器) , 设置IP偏移量访问
  • SS — 栈段
    • SP 栈顶指针
    • push 、 pop 操作
This post is licensed under CC BY 4.0 by the author.