💻 计算机组成原理(PART B)

请注意,本文最近一次更新于:2022-07-25,文章内容可能已经不具有时效性,请谨慎参考

本文最后更新于:2022年7月25日星期一下午2点59分 +08:00

计算机组成原理B,这里开始学习汇编了


AL

2022年3月22日

DOSBox入门

2022年3月24日

DOSBoxⅠ

2022年3月29日

DOSBoxⅡ

2022年4月7日

DOSBoxⅢ

2022年4月7日

DOSBoxⅣ

2022年4月7日

DOSBoxⅤ

2022年4月12日

DOSBox Ⅵ

2022年4月12日

DOSBox 指令补充Ⅰ


DOSBox不完全指北

DOSBOX 指令补充Ⅰ

中断代码 功能 入口参数 出口参数
INT 20 程序正常退出 CS=PSP段地址
INT 21 系统功能调用 AH=功能号
INT 22 程序结束处理
INT 23 Ctrl-Break处理 AL=0(忽略)
INT 24 严重错误处理 AL=驱动器号 AL=1(重试)
AL=2(通过INT 23H终止)
Cy=1(出错)
INT 25 绝对磁盘读 CX=读入扇区数
DX=起始逻辑扇区数
DS:BX=缓冲区地址
AL=驱动器号
Cy=0(正确)
INT 26 绝对磁盘写 CX=读入扇区数
DX=起始逻辑扇区数
DS:BX=缓冲区地址
INT 27 驻留退出 CS=PSP段地址
DX=程序末地址+1

功能号设置在AH中,设置好其余入口参数后向DOS发出INT 21H指令,最后得到出口参数
由于太多啦,这里只给出一些常见的
|调用代码|功能|入口参数|出口参数|
|—|—|—|—|
|00H|程序终止|CS=PSP段地址| |
|01H|键盘键入字符| |AL=输入的字符|
|02H|显示输出|DL=显示的字符| |
|03H|串行设备输入| |AL=输入的字符|
|04H|串行设备输出|DL=输出的字符| |
|05H|打印输出|DL=输出的字符| |
|06H|直接控制台I/O|DL=0FFH(输入请求)
DL=字符(输出请求)|AL=输入的字符|
|07H|直接控制台I/O(不显示输入)| |AL=输入的字符|
|08H|键盘输入字符(无回显)| | |
|09H|显示字符串|DS:DX=缓冲区首址| |
|0AH|输入字符串|DS:DX=缓冲区首址| |
|0BH|检查标准输入状态| |AL=00(无按键)
AL=0FFH(有按键)|
|0CH|清除输入缓冲区
并执行指定的标准输入功能|AL=功能号
DS:DX=缓冲区首址|AL=输入的数据|
|4CH|带返回码的结果|AL=进程返回码| |

DOSBox 初级汇编基础

  • DOSBox是一种模拟器软件,主要是在IBM PC兼容机下,模拟旧时的操作系统:MS-DOS
  • 支持许多IBM PC兼容的显卡和声卡,为本地的DOS程序提供执行环境,使这些程序可以正常运行于大多数现代计算机上的不同操作系统
  • 指令
    1
    mount X dir %一行出奇迹 
    • 参数说明一下下:
      • X: 虚拟盘命名,随意命名,比如C,G
      • dir: 虚拟盘创建的文件夹位置,比如D:\DOSBox\SourceCode
  • 比如我在D:\DOSBox\SourceCode目录下有一个hello.asm,下面以此为例说明运行asm的流程
  • 流程如下
    • 创建虚拟环境
    • 进入虚拟环境
    • 编译asm源文件
    • 链接编译为可执行文件
    • 执行并大功告成
  • 关于debug
    • debug asm文件需要有edit.com,如果压缩包中没有读者可以前往官网下载
    • edit.com文件建议放置在放置asm源文件的同级目录中,这样方便直接在DOSBox中直接调用
    • 调用debug流程方法
      • 创建虚拟环境
      • 进入虚拟环境
      • 执行edit指令
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        %运行asm
        mount g d:\DOSBox\SourceCode %创建虚拟环境
        g: %进入虚拟环境
        masm hello.asm %编译源文件
        link hello.obj %编译可执行文件
        hello.exe %运行可执行文件
        %调试asm
        mount g d:\DOSBox\SourceCode
        g:
        edit hello.asm %在edit中打开asm文件
        edit hello.LST %打开hellO的清单文件,LST是后续断点调试很重要的文件诺

高级调试入门

  • 反汇编就是将存储器中的二进制数据翻译成有意义的助记符的形式,用以帮助理解程序,常用命令格式如下:
    • -U:从当前指令指针IP指示位置开始对约连续32字节内容反汇编,需要注意的是,反汇编的结果可能并不完全是程序内容,这是因为从指示位置起始到程序结束可能本身没有32字节长度
    • -U offset:offset指指定的偏移地址,将从该地址开始对连续约32字节内容反汇编,例如-U 0123就将从IP=0123开始反汇编
    • -U ofs1 ofs2:设定两个指定的偏移地址,将对这两个偏移地址区间内程序反汇编
  • 用以显示或修改寄存器内容
  • 在显示寄存器内容时,标志寄存器F或程序状态字寄存器PSW将被表示为各个分离的标志位,其表示意义如下所示:
    # 溢出 方向 中断 符号 辅助进位 奇偶 进位
    0 NV UP DI PL NZ NA PO NC
    1 OV DN EI NG ZR AC PE CY
  • 常用命令格式如下:
    • -R:显示所有寄存器当前的内容和当前即将执行的指令
    • -R RX:RX为指定寄存器名,限制指定的寄存器当前的内容,并等待键入新值,如果不想键入数值可以直接回车,比如-R AX Enter就是显示AX寄存器的内容而不加修改
    • -R F:显示标志寄存器F的各个标志位的内容并等待键入新的标志位,同样地,无需修改直接回车
  • 让程序在Debug控制下运行,一般有全程和断电运行两种方式,指令如下
    • -G:控制程序在当前IP处运行直到程序结束,用于快速观察程序的运行情况
    • -G ofs:控制程序由当前IP处运行,直至指定的断电IP=ofs处,此时程序暂停并显示哥哥寄存器的当前值以及断点处指令,同时返回Debug提示符”-“
  • 控制程序运行一条指令后暂停,并显示各个寄存器的当前值及断点处指令,然后返回Debug提示符”-“
    • -T:就没什么说的啦
  • 单步命令一般用于需对程序运行作仔细分析的地方,如判断分支转移、观察运算结果等
  • 以十六进制以及ASCII码两种方式显示内存区的二进制数据,通常用来观察数据段内的缓冲区内容,常见指令格式如下:
    • -D:从0000单元开始,连续显示128个内存单元的内容
    • -D ofs ofs:从指定单元开始显示到指定单元结束
  • 用于在Debug环境下直接键入汇编语言语句,生成简单的可执行代码而不必经过完整的汇编语言编程步骤,或用来在调试过程中临时修改某条指令,常见指令格式如下:
    • -A:从当前IP处输入汇编语句
    • -A ofs:从指定的IP=ofs处输入汇编语句
  • Debug模式默认使用十六进制,故在输入时不能使用H
  • 用来将被调试程序重新转载进内存中,一般用于程序运行结束后继续进行调试程序,或者从头开始调试程序
  • 键入Q退出调试状态,回到DOSBox界面

DOSBox实验指南

实验一: 顺序结构

  • 本实例旨在利用顺序结构实现计算$w=\frac{(v-(x\times y+z-2))}{x}$的计算,其中x,y,z,v均为有符号字类型数据,将x,y,z,v的值存放在字变量X,Y,Z,V中,将结果存放在双变量W中
  • 汇编语言作为底层语言是无法像高级语言一样轻松实现运算结果,这要求我们按照优先级顺序拆分运算表达式合理设计程序,下面给出mermaid流程图
    graph TD
    n0(开始) ==> n1
    n1["x*y->(BX:CX)"] ==> n2
    n2["将z扩展为双字->(DX:AX)"] ==> n3
    n3["(BX:CX)+(DX:AX)->(BX:CX)"]==>n4
    n4["(BX:CX)-2->(BX:CX)"]==>n5
    n5["将V扩展为双字->(DX:AX)"]==>n6
    n6["(BX:AX)-(BX:CX)->(DX:AX)"]==>n7
    n7["(DX:AX)/X,商->W,余数->W+2"]==>id(结束)
    
  • 代码分析
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    DATA    SEGMENT
    X DW 2
    Y DW 2
    Z DW 3
    V DW 10
    W DW 2 DUP(?)
    DATA ENDS
    STACK SEGMENT STACK PARA STACK 'STACK'
    DB 200 DUP(0)
    BUFFER DB 10 DUP(?)
    STACK ENDS
    CODE SEGMENT
    ASSUME DS:DATA,CS:CODE,SS:STACK
    START: MOV AX, SEG DATA
    MOV DS, AX ;DATA→AX
    LEA SI, BUFFER
    MOV AX, X
    IMUL Y ;(x)*(y)→DX:AX
    MOV CX, AX
    MOV BX, DX ;(DX:AX)→(BX:CX)
    MOV AX, Z
    CWD ;(Z) 符号扩展
    ADD CX, AX
    ADC BX, DX ;(BX:CX)+(DX:AX)→(BX:CX)
    SUB CX, 2
    SBB BX,0 ;(BX:CX)-2→(BX:CX)
    MOV AX,V
    CWD ;(V)符号扩展
    SUB AX,CX
    SBB DX,BX ;(DX:AX)-(BX:CX)→(DX:X)
    IDIV X ;(DX:AX)/X
    MOV DL,AL
    PUSH CX
    MOV CL,4
    SHR AL,CL
    OR AL,30H
    MOV [SI],AL
    INC SI
    MOV AL,DL
    AND AL,0FH
    OR AL,30H
    MOV [SI],AL
    INC SI
    MOV AL,'$'
    MOV [SI],AL
    MOV DX,OFFSET BUFFER
    MOV AH,09H
    INT 21H
    MOV AH,4CH
    INT 21H
    CODE ENDS ;退出DOS 状态
    END START
    AL
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    DATA    SEGMENT
    X DW 2
    Y DW 2
    Z DW 3
    V DW 10
    W DW 2 DUP(?)
    DATA ENDS
    STACK SEGMENT STACK PARA STACK 'STACK'
    DB 200 DUP(0)
    BUFFER DB 10 DUP(?)
    STACK ENDS
    CODE SEGMENT
    ASSUME DS:DATA,CS:CODE,SS:STACK
    START: MOV AX, SEG DATA
    MOV DS, AX ;DATA→AX
    LEA SI, BUFFER
    MOV AX, X
    IMUL Y ;(x)*(y)→DX:AX
    MOV CX, AX
    MOV BX, DX ;(DX:AX)→(BX:CX)
    MOV AX, Z
    CWD ;(Z) 符号扩展
    ADD CX, AX
    ADC BX, DX ;(BX:CX)+(DX:AX)→(BX:CX)
    SUB CX, 2
    SBB BX,0 ;(BX:CX)-2→(BX:CX)
    MOV AX,V
    CWD ;(V)符号扩展
    SUB AX,CX
    SBB DX,BX ;(DX:AX)-(BX:CX)→(DX:X)
    IDIV X ;(DX:AX)/X
    MOV DL,AL
    PUSH CX
    MOV CL,4
    SHR AL,CL
    OR AL,30H
    MOV [SI],AL
    INC SI
    MOV AL,DL
    AND AL,0FH
    OR AL,30H
    MOV [SI],AL
    INC SI
    MOV AL,'$'
    MOV [SI],AL
    MOV DX,OFFSET BUFFER
    MOV AH,09H
    INT 21H
    MOV AH,4CH
    INT 21H
    CODE ENDS ;退出DOS 状态
    END START
    • LEA:Load Effective Address,取有效地址指令
      • 指令功能:取源操作数地址的偏移量,并将它传送到目的操作数所在单元
      • 指令格式:LEA reg16,mem
    • DUP:duplicate,重复
      • 指令功能:用来定义重复的字节、字、双字、结构等内存缓冲区
      • 指令格式:数据类型 重复次数 dup(重复数据值)
      • 一些栗子:
        • DB 10 DUP(?):表示定义一个容量为10的起始数据不定的字节内存区
        • DD 5 DUP(0):表示定义一个容量为5的数据为0的双字内存区
        • BUFFER DB 10 DUP(?):表示定义了一个名为BUFFER的大小为10的字节类型的数组
    • INC:目标操作数自增1指令
    • CWD:Change Word to Double Word
      • 指令功能:将一个字类型变量扩张为双字类型变量
      • 顺便白送你一份类似的指令族
        • CBW:change byte to word % 8->16,e.g. AL->AX
        • CWDE: change word to extended word % 16->32 AX->EAX
        • CDQ:change double word to quadword % 32->64 e.g. EAX->EDX:EAX
    • INT:Interrupt routine
      • 指令功能:引发中断,调用中断例程
      • 指令格式:INT n % n表示中断号,也称中断类型码,范围在0-255的整数
      • 执行指令int n时,CPU从中断向量表中找到第n号表项,修改CS和IP,使得
        • IP=4n,CS=4n+2
      • 程序中的INT 21H表示直接返回DOS
    • MOV AH,4CH的含义是带返回码结束
    • $是汇编语言中的一个预定义符号,等价于从当前正在汇编的段的偏移地址,$可用于表达式任意位置
    • XLAT:Translate
      • 汇编语言查表指令,缩写为XLAT
      • 指令格式:XLAT TABLE Table为一待查表格的首地址,以DS:[BX+AL]为地址
      • 指令功能:提取存储器中的一个字节再送入AL,执行XLAT将使待查内容送到累加器,即AL<–((BX)+(AL))
      • 该指令只能是字节操作,所以表格的最大容量为256字节。指令不影响标志位
      • 举个例子:
        1
        2
        3
        4
        X DW 1122H,3344H,5566H,7788H
        LEA BX,X
        MOV AL,03H
        XLAT

实验二:分支结构

  • 本实例的目的是:已知在内存中有一个字节单元NUM,存有带符号数据,要求计算出它的绝对值后,放入RESULT单元中
  • 本程序的mermaid流程图如下
    graph TD
    n1(开始)-->n2[初始化]
    n2-->n3[将X送入到AL中]
    n3-->n4{AL>=0?}
    n4--N-->n5[将AL内容求补]
    n5-->n6[AL内容送入RESULT单元]
    n4--Y-->n6
    n6-->n7(结束)
    
  • 代码分析
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    DATA	SEGMENT
    X DB -15
    RESULT DB ?
    DATA ENDS
    CODE SEGMENT
    ASSUME DS:DATA,CS:CODE
    START: MOV AX,DATA
    MOV DS,AX ;初始化
    MOV AL,X ;X取到AL中
    TEST AL,80H ;测试AL正负
    JZ NEXT ;为正,转NEXT
    NEG AL ;否则AL求补
    NEXT: MOV RESULT,AL ;送结果
    MOV AH,4CH
    INT 21H ;返回DOS
    CODE ENDS
    END START ;汇编结束
    • Test: 测试指令
      • 指令格式:TEST OPD,OPS
      • 指令功能:将源地址和目标地址的内容执行按位与运算,结果不送入目的地址中
      • 举个例子
        1
        2
        TEST AL,01H  %判断AX中的最低位是否为1
        JNZ L %如果不是0就跳转L
    • NEG:求相反数的指令,再次提醒负数是以补码形式存在噢:补码=原码按位取反+1

实验三:循环结构

  • 本实验的目的是:在一串给定个数的数中寻找最大值,并且放置至指定的存储单元
    graph TD
    n1(开始)-->n2["初始化寄存器:DS,SS,SP"]
    n2-->n3["数组首偏移地址->BX<br>数组元素个数->CX,0->AX"]
    n3-->n4[比较BX与AX的值]
    n4-->n5{AX>BX?}
    n5--Y-->n6[BX->AX]
    n6-->n7["BX+1->Bx"]
    n7-->n8[CX-1->CX]
    n5--N-->n7
    n8-->n9{CX>0?}
    n9--Y-->n4
    n9--N-->n10["AX->[MAX]"]
    n10-->n11(结束)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    DATA SEGMENT
    BUFFER DW 2,4,6,1,8
    COUNT EQU ($-BUFFER)/2 %取得数组元素个数,注意直接减法是字节数,而元素是字类型,所以除2
    MAX DW ?
    DATA ENDS

    STACK SEGMENT PARA STACK 'STACK'
    DB 64 DUP(?)
    TOP EQU $-STACK
    STACK ENDS

    CODE SEGMENT
    ASSUME CS: CODE,DS:DATA,SS:STACK

    START PROC FAR %PROC 定义的一个过程,封装函数
    BEGIN: PUSH DS %压栈,为最后RET准备
    MOV AX,0
    PUSH AX
    MOV AX,DATA
    MOV DS,AX
    MOV AX,SEG STACK
    MOV SS,AX
    MOV AX,TOP
    MOV SP,AX
    MOV CX,COUNT;%存放数的个数
    LEA BX,BUFFER;%存放buffer首指针
    MOV AX,[BX];%取第一个数至AX

    INC BX;%BX +1
    INC BX: %BX+1 注意指针要加2才能移动到下一个元素
    DEC CX;%CX -1
    AGAIN: CMP AX,[BX]
    JGE NEXT
    MOV AX,[BX]
    NEXT: INC BX
    INC BX
    LOOP AGAIN
    RET %return
    START ENDP
    • 汇编程序的另一种写法,但不推荐
      • PROC:Process,封装一个过程
      • RET:Return,配合PROC使用,在程序结束时返回
        • 相当于MOV AX 4CH; INT 21H
    • COUNT $-BUFFER:这里$就指代BUFFER数组后的下一个指针位置;BUFFER表示数组首地址,整体效果就是计算数组中元素的个数并传入COUNT中储存
    • 值得强调的是要指向下一个元素时,一定要注意指针移动的次数

实验四:多重循环架构

  • 在一串给定个数的数中寻找最小值,并且放置至指定的存储单元。每个数用16位表示

    graph TD
    n1(开始)--DS,SS,SP-->n2[寄存器初始化]
    n2--Buf->BX-Num->CX-0->AX-->n3[数组偏移地址与大小传递]
    n3--BX?AX-->n4[数据大小比较]
    n4-->n5{AX>BX}
    n5-->n6[BX->AX]
    n6-->n7[BX+1->BX]
    n5-->n7
    n7-->n8[CX-1->CX]
    n8-->n9{CX>0}
    n9-->n4
    n9-->n10[AX->min]
    n10-->n11(结束)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    DATA SEGMENT
    BUFFER DW 1,2,3,4,5,6 %初始化数据
    COUNT EQU $-BUFFER %取得数组大小
    min DW ?
    DATA ENDS
    STACK SEGMENT PARA STACK STACK
    DB 64 DUP(?)
    TOP EQU $-STACK
    STACK ENDS
    CODE SEGMENT
    ASSUME CS:CODE DS:DATA SS:STACK
    START PROC FAR
    BEGIN: PUSH DS
    MOV AX,0
    PUSH AX
    MOV AX,DATA
    MOV DS,AX
    MOV AX,SEG STACK
    MOV SS,AX
    MOV AX,TOP
    MOV SP,AX
    MOV CX,COUNT
    LEA BX,BUFFER
    MOV AX,[BX]
    INC BX
    DEC CX
    AGAIN: CMP AX,[BX]
    JGE NEXT
    MOV AX,[BX]
    NEXT: INC BX
    LOOP AGAIN
    RET
    START ENDP
    CODE ENDS
    END BEGIN
  • 一编写程序完成求1+2+3+……N的累加和,直到累加和超过1000为止。统计被累加的自然数的个数送CN单元,累加和送SUM

    graph TD
    n1(start)-->n2["initialize data,AX(0),BX(0)"]
    n2-->n3[BX++]
    n3-->n4[AX+=BX]
    n4-->n5{"AX≤N"}
    n5--Y-->n3
    n5--N-->n6["N(BX),SUM(AX)"]
    n6-->n7(END)
    
    

    DATA SEGMENT
    SUM DW ?
    N DW ?
    DATA ENDS
    CODE SEGMENT
    ASSUME CS:CODE DS:DATA
    START:
    MOV AX,DATA
    MOV DS,AX
    MOV AX,0
    MOV BX,0
    LP:
    INC BX
    ADD AX,BX
    CMP AX,1000
    JBE LP
    MOV SUM,AX
    MOV N,BX
    MOV AH,4CH
    INT 21H
    CODE ENDS
    END START

实验五:冒泡排序

  • 将以BUF为首地址的字存储区中存放的N个有符号数从大到小排列存入BUF区
    graph TD
    n1(start)-->n2["initialize,CX(N),(CX)-1->CX"]
    n2-->n3["(CX)->DX,0->BX"]
    n3-->n4["(BUF[BX])->AX"]
    n4-->n5{"AX≥BUF[BX+2]"}
    n5--N-->n6["(AX)->BUF[BX]"]
    n5--Y-->n7["(BX)+2->BX"]
    n6-->n7
    n7-->n8["(CX)-1->CX"]
    n8-->n9{"(CX)=0?"}
    n9--N-->n4
    n9--Y-->n10["(DX)->CX"]
    n10-->n11["(CX)-1->CX"]
    n11-->n12{"(CX)=0?"}
    n12--N-->n3
    n12--Y-->n13(END)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    DATA SEGMENT
    BUF DW 3,-4,6,7,8,2,0,-8,-9,-10,20
    N=($-BUF)/2
    DATA ENDS
    STACK SEGMENT STACK
    DB 200 DUP(0)
    STACK ENDS
    CODE SEGMENT
    ASSUME CS:COD,DS:DATA,SS:STACK
    START:
    MOV AX,DATA
    MOV DS,AX
    MOV CX,N
    DEC CX
    LOOP1:
    MOV DX,CX
    MOV BX,0
    LOOP2:
    MOV AX,BUF[BX]
    CMP AX,BUF[BX+2]
    JNE L
    XCHG AX,BUP[BX+2]
    MOV BUF[BX],AX
    L:
    ADD BX,2
    DEC CX
    JNE LOOP2
    MOV CX,DX
    LOOP LOOP1
    MOV AH,4CH
    INT 21H
    CODE ENDS
    END START

实验六:字符串相关

  • 指令:MOVS,更精细可以使用 MOVSB 或 MOVSW,分为传送字节和传送字
  • 格式:MOVS dest, src
  • 功能:将源操作数DS:SI所指向的存储单元数据送到ES:DI所指向的存储单元。当方向标志符DF=0时,传送后SI与DI都加一;当DF=1时,SI与DI都减一
  • 指令:CMPS,更精细可以使用CMPSB 或 CMPSW
  • 格式:CMPS dest, src
  • 功能:与CMP类似,只不过CMP是对两个单个数据进行比较,CMPS是对两个数据串进行比较
  • 指令:SCAS,更精细可以使用SCASB 或 SCASW
  • 格式:SCAS dest
  • 功能:SCAS指令将累加器AL(或AX)的内容与目的串(ES:DI)中的数据进行比较,比较结果不改变操作数,之影响标志位。它执行与CMPS指令同样的不返回结果的减法操作,不同之处只是源操作数为AL(或AX)
  • 指令:LODS,更精细可以使用LODSB 或 LODSW
  • 格式:LODS src
  • 功能:LODS指令将DS:SI指向的源串中的数据装入到AL(或AX)中,并根据方向标志符DF自动修改指针SI,以达到让SI指向下一个装入数据字节(或字)
  • 等价:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    %LODSB指令的等价指令表述为:
    MOV AL,[SI];
    INC SI; % DF=0时
    DEC SI % DF=1时
    %LODSD指令等价指令表述为:
    MOV AL,[SI];
    INC SI; %DF=0
    INC SI;
    DEC SI;%DF=1
    DEC SI;

  • 指令:STOS,更精细可以使用 STOSB 或 STOSW
  • 格式:STOS dest
  • 功能:STOS指令将AL(或AX)中的内容存储到由ES:DI指向的目的串中,并根据DF自动修改DI指针
  • 等价:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    %STOSB
    MOV ES:[DI], AL
    INC DI %DF=0
    DEC DI %DF=1
    %STOSW
    MOV EX:[DI], AX
    INC DI %DF=0
    INC DI
    DEC DI %DF=1
    DEC DI
  • DAA,(Decimal Adjust After Addition),即加法的十进制调整指令
  • 功能:如果AL寄存器中低四位大于9或者辅助进位标志符AF=1,则AL=AL+06H且AL=1;如果AL的高四位大于9或者进位标志符CF=1,则AL=AL+60H且CF=1
  • 栗子:
    1
    2
    3
    4
    MOV AL 37H
    MOV BL 35H
    ADD AL,BL %十六进制加法 37H+35H=6CH
    DAA %DAA调整 0CH+06H->12H 30H+30H->60H 最终结果为72H

您阅读这篇文章共花了:
Invitation
Floral-Sunsunrise
FeynmanDirac
created:12/03/2022
Welcome to Floral-Sunsunrise

This is an identification card as an honored membership of FeynmanDirac

Happy to see you follow FeynmanDirac, enjoy science together

© 版权声明
验证码启动中...