【汇编】四、汇编语言程序

1.第一个程序

1.1 用汇编语言编写的源程序

4.1-4.2
在汇编语言源程序中,包含两种指令,一种是汇编指令,一种是伪指令。
 汇编指令是有对应的机器码的指令,可以被编译为机器指令,最终为 CPU所执行。
 伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。

assume cs:codesg  ;假定段寄存器cs与段codesg关联

;定义段codesg,以segment开始,以ends结束
codesg segment 
	mov ax,0123H
	mov bx,0456H
	add ax, bx
	add ax,ax
	
	;下面这两句表示程序返回,将CPU交给另一个程序
	;程序结束运行后,将CPU的控制权交还给使它得以运行的程序(常为DOS系统)

	mov ax, 4c00H
	int 21H
codesg ends ;段结束

;表示程序结束
end

程序中可能出现的错误:
 语法错误:程序在编译时被编译器发现的错误;
 逻辑错误:程序在编译时不能表现出来的、在运行时发生的错误;

1.2 由源程序到程序执行

4.3-4.8
在这里插入图片描述

masm 1;   ;编译
link 1;   ;连接
1   ;执行

 操作系统是由多个功能模块组成的庞大、复杂的软件系统。任何通用的操作系统,都要提供一个称为shell(外壳)的程序,用户(操作人员)使用这个程序来操作计算机系统进行工作。
 DOS中有一个程序command.com,这个程序在 DOS中称为命令解释器,也就是DOS系统的shell。

 如果用户要执行一个程序,则输入该程序的可执行文件的名称,command首先根据文件名找到可执行文件,然后将这个可执行文件中的程序加载入内存,设置CS:IP 指向程序的入口。此后,command暂停运行,CPU运行程序。程序运行结束后,返回到 command中,command再次显示由当前盘符和当前路径组成的提示符,等待用户的输入。

1.3 用Debug跟踪程序的执行

4.9

debug 1.exe  ;command先调用debug,debug再调用1.exe

继续命令P(Proceed):类似T命令,逐条执行指令、显示结果。但遇子程序、中断等时,直接执行,然后显示结果。

p	;p可以一次性执行完循环

运行命令G(Go)∶从指定地址处开始运行程序直到遇到断点或者程序正常结束。

g
g 偏移地址  ;从CS:IP执行至CS:偏移地址 处

(1)程序加载后,ds中存放着程序所在内存区的段地址,这个内存区的偏移地址为0,则程序所在的内存区的地址为ds:0;
(2)这个内存区的前256个字节中存放的是 PSP,DOS用来和程序进行通信。从256字节处向后的空间存放的是程序。
 所以,从 ds 中可以得到PSP的段地址SA,PSP的偏移地址为0,则物理地址为SA×16+0。
 CS:IP=SA+10H:0

2.[BX]和loop指令

2.1 […]的规定和(…)的约定

第五章序言部分+5.1
[…]:(汇编语法规定)表示一个内存单元
(…):(为学习方便做出的约定,非汇编语法)表示一个内存单元或寄存器中的内容

符号idata表示常量

2.2 Loop指令

5.2

	mov cx,idata ;idata为循环次数
s:	add ax,ax   ;要循环执行的代码
	loop s

CPU 执行loop s 的时候,要进行两步操作:
1.(cx)=(cx)-1;
2.判断 cx 中的值,不为0则转至标号s所标识的地址处执行(这里的指令是add ax,ax),如果为零则执行下一条指令(下一条指令是mov ax,4c00h)。

2.3 Loop指令使用再例

5.3
在汇编源程序中,数字不能以字母开头,如A000h应写为0A000h。

p:一次性执行完循环
g 偏移地址:将程序从CS:IP执行至CS:偏移地址

2.4 段前缀的使用

5.4-5.8
在Debug中将[idata]解释为一个内存单元;
masm编译器将源程序中的[idata]解释为idata。

在汇编源程序中,可以用ds:[idata](即显式地加上段地址)的方式访问内存。

inc [bx]	;bx+=1

“ds:”,“cs:”,“ss:”,“es:”称为段前缀。

 在一般的PC机中,DOS方式下,DOS和其他合法的程序一般都不会使用0:200-0:2ff (00200h-002ffh)的256个字节的空间。所以,我们使用这段空间是安全的。不过为了谨慎起见,在进入DOS后,我们可以先用Debug 查看一下,如果0:200-0:2ff单元的内容都是0的话,则证明DOS和其他合法的程序没有使用这里。
随便的向任意地址的内存单元写入数据是很危险的。

3.包含多个段的程序

3.1 在代码段中使用数据

6.1
可以将数据、代码、栈放入同一个段,也可以放入不同段。

assume cs:code
code segment
		:
		数据
		:
start:
		:
		代码
		:
code ends
end start

start指明程序的入口。程序载入CPU时CS:IP指向start后的指令。

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

 “dw”的含义是定义字型数据。dw即“define word”。在这里,使用dw定义了8个字型数据(数据之间以逗号分隔),它们所占的内存空间的大小为16个字节。

3.2 在代码段中使用栈

6.2
可以在程序中通过定义数据来取得一段空间,然后将这段空间当作栈空间来用。

dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;定义了16个字型数据,开辟出了32个字节的空间

3.3 将数据、代码、栈放入不同段

6.3

assume cs:code,ds:data,ss:stack
data segment
	dw 0h,1h,2h,3h,4h,5h,6h,7h
data ends
stack segment
	dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends
code segment
start:	mov ax,stack
	mov ss,ax
	mov sp,20h	;设置栈顶ss:sp指向stack:20

	mov ax,data
	mov ds,ax	;ds指向data段
	
	mov bx,0	;ds:bx指向data段中的第一个单元

	mov cx,8
s:	push [bx]
	add bx,2
	loop s		;入栈

	mov bx,0

	mov cx,8
s0:	pop [bx]
	add bx,2
	loop s0		;出栈
	
	mov ax,4c00h
	int 21h
code ends

end start

 程序中对段名的引用,如指令“mov ds,data”中的“data”,将被编译器处理为一个表示段地址的数值。数值是不能直接送入段寄存器的。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷冰殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值