selector汇编语言

汇编语言知多少(二): 指令使用

2018-10-24  本文已影响74人  Lin__Chuan

上篇文章中我们具体介绍了汇编语言的一些背景, 以及 8086汇编 工作原理, 在这篇文章中具体讲解8086汇编指令, 看完这个有助于学习ARM汇编. 文章后面手把手教你怎么利用 MASM 编译执行程序.

转移指令

8086 提供了一个 mov 指令, 传送指令, 可以用来修改大部分寄存器的值,
CPU 从何处执行指令是由 CS, IP 中的内容决定的, 我们可以通过 Jmp 这类转移指令, 来修改 CS, IP 的值来控制 CPU 执行目标指令.

DS和[address]

CPU 要读写一个内存单元时, 必须要先指出内存单元的地址, 在 8086 中, 内存地址(物理地址) 由 段地址 和 偏移地址 组成.

al寄存器 写数据

mov bx, 1000H
mov ds, bx
mov al, [0]
  1. 上面3条指令的作用将10000H(1000:0)中的内存数据赋值到 al寄存器 中.
  2. mov al,[address] 的意思将 DS:address 中的内存数据赋值到 al寄存器 中.
  3. 由于 al 是8位寄存器,所以是将一个字节的数据赋值给 al寄存器.
  4. 8086不支持将数据直接送入到 段寄存器, 不能直接 mov ds, 1000H

al寄存器 读数据

mov bx, 1000H
mov ds, bx
mov [0], al

大端模式和小端模式

大端模式: PowerPC, IBM, Sun
小端模式: x86, DEC.
ARM 既可以工作在大端模式, 也可以工作在小端模式.

mov 指令, add 指令, sub 指令

add , sub 和 mov 一样, 都有两个操作对象.

mov 寄存器, 数据  比如: mov ax, 8
mov 寄存器, 寄存器  比如: mov ax, bx
mov 寄存器, 内存单元  比如: mov ax, [0]
mov 内存单元, 寄存器  比如: mov [0], ax

是一种具有特殊访问方式的空间 (后进先出, LIFO, Last In First Out)

push ax

  1. SP = SP - 2, SS: SP 指向当前栈顶前面的单元, 以 当前栈顶 前面的单元为新的栈顶.
  2. 将 ax 中的内容送入到 SS: SP 指向的内存单元处, SS:SP 此时指向新栈顶.


pop ax

  1. 将 SS: SP 指向的内存单元处的数据送入 ax 中.
  2. SP = SP + 2, SS: SP 指向当前栈顶下面的单元, 以 当前栈顶 下面的单元为新的栈顶.

值得注意的是, 随着 push 和 pop 的操作, 原来内存单元上的数据并没有被清楚掉, 而是随着 SP 的变化, 称为垃圾数据, 当有新的数据 push 进来时, 原数据会被覆盖.


对于上面这种 10000H ~ 1000FH 这段栈空间, 初始状态为空, 此时 SS = 1000H, SP应该为 0010H, 因为栈空时, SS: SP 指向栈空间最高地址单元的下一个单元.

push 与pop

push 寄存器  ; 将一个寄存器中的数据入栈
pop 寄存器   ; 出栈, 用一个寄存器接收出栈的数据
push 内存单元 ; 将一个内存单元处的字入栈
pop 内存单元  ; 出栈, 用一个内存字单元接收出栈的数据
mov ax, 1000H
mov ds, ax   ; 内存单元的段地址放在 ds 中
push [0]     ; 将 1000: 0 处的字压入栈.
pop [2]      ; 出栈, 出栈的数据送入 1000: 2处

将 10000H ~ 1000FH 这段空间当做栈, 此时为空栈, 设置 AX = 001AH, BX = 001BH, 利用栈, 交换 AX 和 BX 的数据.

mov ax, 1000H
mov ss, ax
mov sp, 0010H ; 栈空时, SP 指向栈顶(栈空间的最高地址)单元的下一单元

mov ax, 001AH
mov bx, 001BH

push ax
push bx

pop ax
pop bx

小结:

终于可以开始我们的第一个完整的汇编程序.

MASM (Microsoft Macro Assembler) 是微软公司微处理器家族开发的汇编开发环境, 因为MASM工具 是一个exe的执行文件, 所以为了在 Mac OS 上能使用它, 我们需要借助DOSBox.

DOSBox 是一款模拟器软件, 为本地的 DOS 程序提供执行环境, (DOS指 磁盘操作系统), 最早期是为了运行计算机程序设计, 目前已经支持 Windows, Mac OS 多个平台, 简单来说, 它就是一个计算机的模拟, 我们可以在官网下载最新的 DOSBox.

使用 DOSBox

  1. 双击打开程序, 默认在 Z 盘, 可以使用 dir, 查看系统的情况


  2. 为了方便处理, 在 用户目录下 新建一个 LCDOSBox 文件夹, 用来存储我们编写的代码文件, 以及 MASM 工具. 这些工具可以在这里下载.

  3. 在 DOSBox 界面挂载我们的文件目录, 这里 c 指的是 虚拟c盘, ~/LCDOSBox 指虚拟的文件夹位置.

Z:\> mount c ~/LCDOSBox
  1. 进入 c 盘, 直接执行当前目录中的 debug.exe 程序.
Z:\> c:

C:\> debug

这里的 -r 指令, 用来显示寄存器的内容.

  1. 编写我们的asm文件.
; 数据段
data segment
    string db 'Hello World! $'
data ends


; 代码段
code segment
    assume cs: code, ds: data  ; 声明代码段和数据段

start:

    mov ax, data
    mov ds, ax    ; 设置 ds 为数据段
    
    mov ah, 9h    ; 功能号 9h 代表在屏幕显示字符串
    ;mov dx, offset string ; ds: dx 代表字符串的地址
    lea dx, string ; 同上 lea指令的功能是将存储单元的有效地址(偏移地址)传送到目的操作数

    int 21h       ; 执行 DOS 系统功能调用

    mov ah, 4ch   ; 功能号 4ch 代表程序退出
    int 21h
    
code ends

end start         ; 遇到 end 停止编译 开始执行 start 里的内容

对于这个程序, 有几点我需要作说明

  1. 编译并链接生成 exe 文件.


    image.png

如果你在利用 DOSBox 执行程序的时候碰到 Unable to open input file:xxx.asm 的错误, 但是代码文件确实存在. 可能是由于文件的名字系统的差别造成, 你可以这样做

如果你在执行的过程中碰到你需要输入的, 直接 enter 键 跳过.

  1. 调试程序
C:\> debug

中断

中断是由于软件的或硬件的信号,使得CPU暂停当前的任务,转而去执行另一段子程序.

指令要处理的数据长度

8086指令能处理2种 尺寸的数据, byte , word, 还有其他指令集中的 dword , 通过这来指明需要操作内存的数据长度.

比如 pop [0], push [0] 操作的数据长度默认只能是 2 个字节.

参考
维基百科-DOSBox
如何用MASM5.0

上一篇 下一篇

猜你喜欢

热点阅读