• 汇编语言笔记v1.0


    1.loop的用法

     loop指令的格式是:loop标号,cpu执行loop指令的时候,要进行两步操作

    1:(cx)=(cx)-1    

    2:判断cx中的值,不为零则转至标号处执行,如果为零,则向下执行

    这里有几点需要注意:

    1.loop虽然是一种循环的格式,但是和高级语言中的for或者while不同,它本身并没有达成循环的作用,只是提供一个循环中可以用到的判断。要实现循环,依然需要搭配程序段以及程序段中的jmp实现

    2.loop是“先减再判断”,这一点在设置cx的值时要特别注意。例如,如果需要循环十次,那么cx中的值应该设置为11.因为除了循环10次之外,最后一次要跳出循环时是cx-1==0,这里的cx依然需要保持为1

    2.emu8086与debug

      就我本人而言,我更倾向于在学习汇编语言时使用emu8086,IDE的存在可以减少重复劳动、提高学习效率,但是emu8086作为一款模拟软件,并没有支持8086所有的伪指令和宏指令。目前我个人已经发现emu8086不支持的操作有如下:

    不支持宏嵌套
    不能识别宏中的IF,ELSE语句
    DUP不支持无定义的字节变量(DB ?),支持(DW ?),但是初始化时初始化为0(xx DB 0)
    不支持size length伪指令 ORG 和SEG伪指令align
    不支持structure

    所以,在这种情况下,我们只能使用debug进行调试。但是要注意debug只能用来调试.exe文件时才能出现你所编写的代码,如果直接调试.asm文件将出现难以理解的代码。

    常用的debug命令如下:

    名称 解释 格式 
    a (Assemble) 逐行汇编 a [address] 
    c (Compare) 比较两内存块 c range address 
    d (Dump) 内存16进制显示 d [address]或 d [range] 
    e (Enter) 修改内存字节 e address [list] 
    f (fin) 预置一段内存 f range list 
    g (Go) 执行程序 g [=address][address...] 
    h (Hexavithmetic) 制算术运算 h value value 
    i (Input) 从指定端口地址输入 i pataddress 
    l (Load) 读盘 l [address [driver seetor> 
    m (Move) 内存块传送 m range address 
    n (Name) 置文件名 n filespec [filespec...] 
    o (Output) 从指定端口地址输出 o portadress byte 
    q (Quit) 结束 q 
    r (Register) 显示和修改寄存器 r [register name] 
    s (Search) 查找字节串 s range list 
    t (Trace) 跟踪执行 t [=address] [value] 
    u (Unassemble) 反汇编 u [address ]或range 
    w (Write) 存盘 w [address[driver sector secnum> 
    ? 联机帮助 ?

    3.struc的使用

    struc的结构预置语句应该放在数据段中,作为数据的一部分。而对于结构的定义也即struc段应该放在各段之外单独成段。注意,对于数据段中的结构预置语句,如果不给与初始化值,一定要用逗号隔开,否则会出现初始化错误

    4.键盘输入输出

    总结一下常用的键盘输入输出方式:

      4.1.1 输入字符

    ah=1,字符的ASCII码传入al中

      4.1.2 输入字符串

    字符串的输入按照结构要求,需要预先在数据段中准备好以下结构:

    1 maxlen db 32;字符串的最大长度,需要初始化
    2 actlen db ?;实际输入的字符串长度,这个可以初始化也可以不做初始化
    3 string db 32 dup(?);用于存放字符的串,长度用dup确定下来

      4.2.1 输入字符

    ah=2,将字符的ASCII码存放在dl中

      4.2.2 输出字符串

    ah=9, 将字符串的偏移量用offset的形式传入dx中。注意,字符串要人为在最后加上结束符,如果要回车(0dh)换行(0ah),也要人为加在结束符之前

    eg.

    1 string db 'hello',0dh,0ah,'$'
    2 mov dx,offset string
    3 mov ah,9
    4 int 21h

    5.堆栈

    在调用子程序时,如果是远调用(call a; a proc far),会在堆栈中依次压入cs和ip,而如果是近调用(call a; a proc near)只会压入ip。在使用ret返回主程序时,要务必保证堆栈顶是ip,否则会返回到错误的位置去执行

    另外,在子程序的开头,我们需要保存子程序中要用到的寄存器的原有的值以便主程序继续使用,保存的方法就是压入堆栈。如果我们没有自定义堆栈段,那么程序会自动将数据段作为堆栈段,但是是从数据填入的反方向开始填入堆栈段数据

    6.运算

    有一些需要记住的运算

      6.1 乘法运算

    乘法运算只传递一个参数。如果传入8位寄存器,则与AL相乘,结果保存在AX中;如果传入16位寄存器,则与AX相乘,结果保存在DX:AX中。即对于乘法,两个数的位数是相同的。

      6.2 除法运算

    而除法则不然:除数、商和余数的位数都要是被除数的一半!被除数同样放在AL或者AX中,根据传入的参数的位数决定使用哪个

      6.3 移位运算

    下面图片里的内容都很关键

     

    差不多就这样,想起来再补充

  • 相关阅读:
    centos 安装Phpstorm
    PostgreSQL 里面的 BIGSERIAL
    如何下载symfony
    换行
    javaScript 真经 小感 this 指向
    css3 抖动
    jq 抖动效果
    还是 js 替代 vw vh 了
    常用 Math 属性及方法
    js 判断浏览器类型及版本
  • 原文地址:https://www.cnblogs.com/jiading/p/10664546.html
Copyright © 2020-2023  润新知