汇编语言笔记(一)

章节目录

  1. 简单程序
  2. 使用段
  3. 简单字符串处理程序
  4. 使用 bx, si, di, bp 寄存器寻址
  5. 寻址方法
  6. 指明数据长度
  7. div指令

作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢!

本文中所有程序均在DOSBox下使用MASM, LINK编译运行

简单程序

loop program

  • segment…ends: 伪指令, 用来定义一个段(比如,代码段,数据段,堆栈段), segment 标识一个段的开始, ends 标识一个段的结束.
  • 语法:
    SegmentName segment
    ..
    SegmentName ends

  • assume: 伪指令, 它假设某一段寄存器和程序中的某一个用 segment..ends 定义的段相关联.


  • mov ax, 4c00h
    int 21h

    称为程序返回,它的作用是将 CPU 的控制权交还给使他得以运行的程序.
  • 使用段

    using segments

    使用 assume 将我们定义的数据段,堆栈段,代码段和对应的段寄存器关联起来.

    cs 寄存器对应代码段
    ds 寄存器对应数据段
    ss 寄存器对应堆栈段

    值得注意, 我们在访问数据段或者堆栈段的时候,总是将段基址先保存在 ax 中,然后由 ax 保存到 ds 或者 ss. 为什么不直接将段基址保存到 ds 或者 ss 中? 答案是该操作非法.

    简单字符串处理程序

    这里写图片描述

    在这里, 我们使用 bx + offset 的语法访问数据段中的字符串. 相应的字符的地址计算方法为 a d d r = d s 16 + b x + o f f s e t .

    这里 offset 一般为常量. 如果不是常量, 我们可以使用 [bx+di+offset] 来完成. 相应的字符的地址计算方法为 a d d r = d s 16 + b x + d i + o f f s e t .
    对于栈的访问可以使用 [bx+si+offset] 的方式访问. 相应的字符的地址计算方法为 a d d r = d s 16 + b x + s i + o f f s e t .

    使用 bx, si, di, bp 寄存器寻址

  • 只有这四个寄存器可以用在 ‘[…]’ 中来进行内存单元寻址
  • 比如:
    mov ax, [bx]
    mov ax, [bx+si]
    mov ax, [bx+di]
    可以使用 bp 替换 bx.

    //以下用法是错误的
    mov ax, [ax]
    mov ax, [cx]
    mov ax, [dx]
    mov ax, [ds]

  • 这四个寄存次可以单个出现在 ‘[…]’ 中或者以组合出现.
  • 组合形式只能是以下四种:

    mov ax, [bx + si + offset]
    mov ax, [bx + di + offset]
    mov ax, [bp + si + offset]
    mov ax, [bp + si + offset]
    当然 offset 可以为零.

    //以下用法是错误的
    move ax, [di + si]
    move ax, [bx + bp]

  • 只要在 ‘[…]’ 中使用 bp 寄存器, 而指令中没有显式的给出段地址, 段地址默认在 ss 中.
  • 寻址方法

  • 直接寻址
  • 如: mov ax, [0] // 段基址在 ds 中

  • 寄存器间接寻址
  • 如:
    mov ax, [bx] // 段基址在 ds 中. bx 指明偏移
    mov ax, [si] // 段基址在 ds 中. si 指明偏移
    mov ax, [di] // 段基址在 ds 中. di 指明偏移
    mov ax, [bp] // 段基址在 ss 中. bp 指明偏移

  • 寄存器相对寻址
  • 如:
    mov ax, [bx+offset] // 段基址在 ds 中. bx+offset 指明偏移
    mov ax, [si+offset] // 段基址在 ds 中. si+offset 指明偏移
    mov ax, [di+offset] // 段基址在 ds 中. di+offset 指明偏移
    mov ax, [bp+offset] // 段基址在 ss 中. bp+offset 指明偏移

  • 基址变址寻址
  • 如:
    mov ax, [bx+si] // 段基址在 ds 中. bx+si 指明偏移
    mov ax, [bx+di] // 段基址在 ds 中. bx+di 指明偏移
    mov ax, [bp+si] // 段基址在 ss 中. bp+si 指明偏移
    mov ax, [bp+di] // 段基址在 ss 中. bp+di 指明偏移

  • 相对基址变址寻址
  • 如:
    mov ax, [bx+si+offset] // 段基址在 ds 中. bx+si+offset 指明偏移
    mov ax, [bx+di+offset] // 段基址在 ds 中. bx+di+offset 指明偏移
    mov ax, [bp+si+offset] // 段基址在 ss 中. bp+si+offset 指明偏移
    mov ax, [bp+di+offset] // 段基址在 ss 中. bp+di+offset 指明偏移

    指明数据长度

  • 通过寄存器名指明要处理的数据的尺寸
  • // 使用字长度 (ax: 16bit)
    mov ax, 1
    mov ds:[0], ax

    // 使用字节长度 (al: 8bit)
    mov al, 1
    mov ds:[0], al

  • 在没有寄存器名存在的情况下, 使用操作符 Type ptr 指明内存单元长度. Type 可以使 word 或者 byte.
  • // 使用字长度 (ax: 16bit)
    mov word ptr ds:[0], 1
    add word ptr [bx], 1

    // 使用字节长度 (al: 8bit)
    mov byte ptr ds:[0], 1
    add byte ptr [bx], 1

  • 有些指令有默认的访问数据长度. 比如 push 就只能进行字操作
  • div指令

    注意问题:

  • 除数: 有 8 位和 16 位两种, 在一个 reg 或者内存单元中
  • 被除数: 默认放在 AX 或者 DX 和 AX 中, 如果除数为 8 位, 被除数则为 16 位, 默认在 AX 中; 如果除数为 16 位, 被除数则为 32 位, 在 DX 和 AX 中存放, DX 存放高 16 位, AX 存放低 16 位.
  • 结果: 如果除数为 8 位, 则 AL 存放除法操作的商, AH 存放余数; 如果除数为 16 位, 则 AX 存放除法操作的商, DX 存放余数;
  • 欢迎交流任何想法.

    End…

    猜你喜欢

    转载自blog.csdn.net/zhaoruixiang1111/article/details/80865994
    今日推荐