• 汇编学习笔记(3) -- 编写第一个汇编程序


     
     
    源程序
    第一步:编写汇编源程序
    使用文本编辑器(记事本等),用汇编语言来编写汇编语言
     
    第二步:编译源程序
    使用汇编语言的编译程序对源程序进行编译,产生目标文件
    再用连接程序对目标程序进行连接,生成可执行文件
     
    可执行分界线包含两部分内容:
    程序和数据
    相关的描述信息
     
    第三步:执行可执行文件中的程序
     1 assume cs:codesg
     2 codesg segment
     3     mov ax,0123H
     4     mov bx,0456H
     5     add ax,bx
     6     add ax, ax
     7     mov ax,4c0OH
     8     int 21H
     9 codesg ends
    10 end
    在汇编源程序中包含两种指令,一种是汇编指令,一种是伪指令
    汇编指令有对应的机器码,可以被编译为机器指令被cpu执行
     
    伪指令没有对应的机器指令,不能被cpu执行
    伪指令由编辑器执行
     
     
    伪指令
     
    segment和ends
     
    segment和ends是一对 成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指令。
     
    segment和ends的功能是定义一个段
    segment说明一个段开始
    ends说明一个段结束
    一个段必须有一个名称来标识,使用格式为:
    1 段名 segment
    2 3 段名 ends
     
    一个汇编程序是由多个段组成的,一个有意义的汇编程序至少有一个存放代码的段
     
     
    end
    end是一个汇编程序的结束标记,编译器遇到end就会结束对源程序的编译
    注意end后面没有s,ends是段结束
     
     
    assume
    含义为"假设"
    它假设某一段寄存器 和 程序中的某一个用segment...ends定义的段相关联。
    通过assume 说明这种关联,在需要的情况下,编译程序可以将段寄存器和某一个具体的段相联系。
    不需要深入理解,只要记着用assume将有特定用途的段和相关的段寄存器关联起来就行
     
     
    源程序由计算机编译成程序
    程序以汇编指令的形式粗在于源程序中
    编译连接后变成机器码,存储在可执行文件里
     
     
     
     
     
    标号
    一个标号代表了一个地址
    比如
    codesg:放在segment前面
    作为一个段的名称
    这个段的名称最终将被编译、连接程序处理为一个段地址
     
     
     
    程序的结构
     
    例题:运算2^3
    先定义一个段,名为abc
    1 abc segment
    2   :
    3 abc ends
     
    之后在段中写入汇编指令
     
     
    1 abc segment
    2  
    3   mov ax,2
    4   add ax,ax
    5   add ax,ax
    6  
    7 abc ends
     
    段写完后要指出程序在何时结束
     
    1 abc segment
    2  
    3   mov ax,2
    4   add ax,ax
    5   add ax,ax
    6  
    7 abc ends
    8 end
    9  
     
    abc作为代码段所以要让cs指向abc
    1 abc segment
    2   mov ax,2
    3   add ax,ax
    4   add ax,ax
    5   abc ends
    6  
    7 end
     
     
    程序返回
     
    DOS是一个单任务操作系统
    一个程序P2在可执行文件中则必须有一个正在运行的程序P1
    将P2从可执行文件中加载入内存后
    将CPU控制权交结P2,P2才能得运行·P2开始运行后,P1暂停运行
     
    而当P2运行完毕后,应该将CPU的控制权交还给使它得以运行的程序Pl
    此后P1继续运行
     
    程序返回 就是将CPU的控制权交还给使它得以运行的程序,
    程序的末尾添加返回的程序段
    mov ax, 4c00H int 21H
    这两条指令所实现的功能就是程序返回
    暂时不需要理解原因,只需要知道这两条指令可以实现程序返回
     
     
    语法错误和逻辑错误
    语法错误:
    编译时被编译器发现的错误
     
    逻辑错误:
    编译后,运行时发生的错误是逻辑错误
     
     
     
     
    编译
    使用dosbox编译
    在编辑器里写号源代码,后缀名是asm
    存放在c:/code(dosbox默认目录)
     
    打开dosbox,输入dir,就能显示出文件(文件夹变动,dosbox必须重启才能在里面看到)
     
    开始编译
    输入masm + 名字.asm
     
    或者这样,输入masm,在第一行后面写文件名(如果文件后缀是asm,则可省略不写)
    后面都可按enter跳过,或者输入路径,指定生成位置
    最终生成目标文件.obj 其中.list(列表文件) .crf(交叉引用文件)是中间结果,可忽略
     
     
    连接
    使用dosbox
    输入link
     
    类似编译
    只要在第一行输入文件名即可,后面可跳过
     
    最后一行报错是 没有栈段,可忽略
     
    最后生成 .EXE文件
     
     
    还有种简洁的方法
    masm 1;
    link 1;
    自动跳过中间文件
    直接生成目标文件
     
     
     
    执行
    在dosbox里执行文件,win10里不支持这种格式了
    执行没结果,很正常,因为没有写向显示器输出信息的命令
    后面再说
     
    如果在想用debug跟踪执行
    只要 debug xxx.exe 即可
    然后输入t,输入一次执行一行
     
     
    谁将可执行文件中的程序装载进入内存并使它运行?
    前文提过
    在DOS中,可执行文件中的程序 a 若要运行
    必须有一个正在运行的程序 b,
    将 a 从可执行文件中加载入内存,将CPU的控制权交给它,a 才能得以运行;
    当 a 运行完毕后,应该将CPU的控制权交还给使它得以运行的程序 b。
     
     
    按照上面的原理,再来看一下 上面的 执行 中的 1.exe的执行过程
    (1)在提示符 “c:>” 后面输入可执行文件的名字“1”,按Enter键。
    这时,请思考问题1。
     
    (2)1.exe中的程序运行
     
    (3)运行结束,返回,再次显示提示符 “c:>” 。请思考问题2。.
     
    问题1
    此时,有一个正在运行的程序将1.exe中的程序加载入内存,这个正在运行的程序是
    什么?它将程序加载入内存后,如何使程序得以运行?
     
    问题2
    程序运行结束后,返回到哪里?
     
    如果你对DOS有比较深入的了解,那么,很容易回答问题4.1、问题4.2中所提出的
    问题。如果没有这种了解,可以先阅读下面的内容。
     
    操作系统的外壳
    操作系统是由多个功能模块组成的庞大、复杂的软件系统。
    任何通用的操作系统,都要提供一个称为shell(外壳)的程序
    用户(操作人员)使用这个程序来操作计算机系统进行工作。
     
    DOS中有一个程序command.com,这个程序在DOS中称为命令解释器,也就是DOS系统的shell。
    DOS启动时,先完成其他重要的初始化工作,然后运行command.com
    command.com运行后,执行完其他的相关任务后,在屏幕上显示出由当前盘符和当前路径组成的提示符
    比如:“c:” 或 “c:windows”等,然后等待用户的输入。
     
    用户可以输入所要执行的命令,比如,cd、dir、type等,这些命令由command执行
    command执行完这些命令后,再次显示由当前盘符和当前路径组成的提示符,等待用户的输入。
     
    如果用户要执行一个程序,则输入该程序的可执行文件的名称
    command首先根据文件名找到可执行文件
    然后将这个可执行文件中的程序加载入内存
    设置CS:IP 指向程序的入口
     
    此后,command 暂停运行,CPU 运行程序
     
    程序运行结束后,返回到command 中,command 再次显示由当前盘符和当前路径组成的提示符,等待用户的输入。
     
    在 DOS中,command处理各种输入命令或要执行的程序的文件名。
    我们就是通过command来进行工作的
     
     
     
    现在我们可以回答 问题1和2
    问题1:
    是正在运行的command,将1.exe中的程序加载入内存;
    command 设置CPU的 CS:IP指向程序的第一条指令(即程序的入口),从而使程序得以运行;
    问题2
    程序运行结束后,返回到command 中,CPU继续运行command。
     
     
     
     
     
     
    程序执行过程的跟踪
    可以用Debug来跟踪一个程序的运行过程
    对于隐藏较深的错误,就必须对程序的执行过程进行跟踪分析才容易发现。
     
    以1.exe为例,讲解如何用Debug 对程序的执行过程进行跟踪。
     
    现在我们知道,在DOS中运行一个程序的时候,是由command 将程序从可执行文件中加载入内存,并使其得以执行。
    而Debug可以将程序加载入内存,设置CS:IP指向程序的入口
    但Debug 并不放弃对CPU的控制
    这样,我们就可以使用Debug的相关命令来单步执行程序,查看每一条指令的执行结果。
    输入
     
     
    DOS中.exe文件中的程序的加载过程
     
    注意,有一步称为重定位的工作没有讲解,因为这个问题和操作系统的关系较大,不作讨论
     
     
    从上图中我们知道以下的信息。
    (1)程序加载后,ds 中存放着程序所在内存区的段地址,这个内存区的偏移地址为0,则程序所在的内存区的地址为ds:0;
    (2)这个内存区的前256个字节中存放的是PSP,DOS用来和程序进行通信。
    从256字节处向后的空间存放的是程序。
    所以,从ds中可以得到PSP的段地址SA,PSP的偏移地址为0,则物理地址为SA×16+0。
    因为PSP占256(100H)字节,所以程序的物理地址是:
    SA×16+0+256 = SA×16+16×16+0= (SA+16) × 16 + 0
    可用段地址和偏移地址表示为:SA+10H:0。
     
     
    上图中,DS = 075C,IP = 0,CS:IP 指向程序的第一条指令
    所以程序的地址为075C + 10 :0 即 076C : 0
    cs里就是076C
    注意,debug里默认数据用16进制表示
     
    使用u查看指令
     
    输入t开始单步执行,观察每一步指令的执行结果,直到int 21
    用p命令执行int 21
     
     
    上图中 int 21 执行后,显示出“Program terminated normally” 返回到 Debug中。
    表示程序正常结束。
    注意,要使用Р命令执行int 21。
    这里不必考虑是为什么,只要记住这一点就可以了。
     
    需要注意的是,在这里是Debug 将程序加载入内存
    所以程序运行结束后要返回到Debug 中
     
    使用 q 命令退出 Debug,将返回到command 中
    因为Debug 是由command加载运行的。
     
    在DOS中用“debug 1.exe”运行Debug对1.exe进行跟踪时
    程序加载的顺序是:
    command加载Debug
    Debug加载1.exe
     
    返回的顺序是:
    从 1.exe中的程序返回到Debug
    从Debug 返回到command
     
     
    参考: 王爽 - 汇编语言 和 小甲鱼零基础汇编
     
     
  • 相关阅读:
    sql 变量赋值
    mysql 行号 获取指定行数据
    SQL Server获取指定行的数据
    sql server 创建内联表值函数
    sql server 表变量存储临时查询数据
    sql server 循环操作
    oracle for in 学习
    oracle C# 访问
    sql server insert values 多值 与oracle 的不同
    mysql 如何选择随机行
  • 原文地址:https://www.cnblogs.com/ZhouJiaHao/p/13642324.html
Copyright © 2020-2023  润新知