文章目录
标志寄存器
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
OF | DF | IF | TF | SF | ZF | AF | PF | CF | ||||||||
OV | DN | EI | NG | ZR | AC | PE | CY | 1 | ||||||||
NV | UP | DI | PL | NZ | NA | PO | NC | 0 | ||||||||
计算数字、字符串长度
;$ 运算符(当前地址计数器)返回当前程序语句的偏移量。在下例中,从当前地址计数器($)中减去 list 的偏移量,计算得到 ListSize:
list BYTE 10,20,30,40
ListSize = ($ - list)
;注意是WORD还是byte
list WORD 1000h,2000h,3000h,4000h
ListSize = ($ - list) / 2
简化段定义
;简化段定义
.model small ;定义程序的存储模型
.stack ;定义堆栈段
.data ;定义数据段
string db ’Hello, Everybody !’,0dh,0ah,’$’
;在数据段定义要显示的字符串
.code ;定义代码段
.startup ;程序起始点,建立DS、SS
mov dx,offset string ;指定字符串
mov ah,9
int 21h ;利用功能调用显示信息
.exit 0 ;程序结束点,返回DOS
end ;汇编结束
;完整段定义
stack segment stack ;定义堆栈段
dw 512 dup(?)
;堆栈段有512字(1024字节)空间
stack ends ;堆栈段结束
data segment ;定义数据段
string db ’Hello, Everybody !’,0dh,0ah,’$’
data ends
code segment ’code’ ;定义代码段
assume cs:code,ds:data,ss:stack
start:
mov ax,data ;建立DS段地址
mov ds,ax
mov dx,offset string
mov ah,9
int 21h
mov ax,4c00h
int 21h ;利用功能调用返回DOS
code ends ;代码段结束
end start
;汇编结束,同时指明程序起始点
DOS系统功能调用
步骤
- 在AH寄存器中设置系统功能调用号
- 在指定寄存器中设置入口参数
- 执行指令INT 21H(或ROM-BIOS的中断向量号)实现中断服务程序的功能调用
- 根据出口参数分析功能调用执行情况
输入输出类功能调用
向显示器输出字符
字符的输出
;在当前显示器光标位置显示一个问号
mov ah,02h ;设置功能号:ah←02h
mov dl,'?' ;提供入口参数:dl←'?'
int 21h ;DOS功能调用:显示
字符串输出的功能调用
string db 'Hello,Everybody !',0dh,0ah,'$' ;在数据段定义要显示的字符串
mov ah,09h ;设置功能号:ah←09h
mov dx,offset string ;提供入口参数:dx←字符串的偏移地址
int 21h ;DOS功能调用:显示
从键盘输入数据
字符的输入
-
功能号:AH=01H
-
出口参数:AL=字符的ASCII码
-
功能:获得按键的ASCII代码值
-
调用此功能时,若无键按下,则会一直等待,直到按键后才读取该键值
getkey: mov ah,01h ;功能号:ah←01h
int 21h ;功能调用
cmp al,’Y’ ;处理出口参数al
je yeskey ;是“Y”
cmp al,’N’
je nokey ;是“N”
jne getkey
...
yeskey: ...
nokey: ...
字符串的输入
- 功能号:AH=0AH
- 入口参数:DS:DX=缓冲区首地址
- 执行该功能调用时,用户按键,最后用回车确认
- 本调用可执行全部标准键盘编辑命令;用户按回车键结束输入,如按Ctrl+Break或Ctrl+C则中止
buffer db 81 ;定义缓冲区
;第1个字节填入可能输入的最大字符数
db 0 ;存放实际输入的字符数
db 81 dup(0) ;存放输入的字符串
mov dx,seg buffer
;伪指令seg取得buffer的段地址
mov ds,dx ;设置数据段DS
mov dx,offset buffer
mov ah,0ah
int 21h
mov指令的易错点
易错语法点
- 立即数不能作为目的操作数,如mov 110H,AX
- 立即数不能直接传给段寄存器,如mov DS,110H // 翻译成机器码很长
- 两个操作数不能同时为段寄存器,如mov ES,DS // 可通过Ax寄存器间接传递
- 两个操作数不能同时为存储单元,如mov [0x1245],[0x1312] // 翻译成机器码很长
- 代码段寄存器CS不能为目的操作数,但可为源操作数 // CS为存放代码段的段地址,是代码段寄存器。它与IP共用,以指示下一条要执行的指令,不能随意更改!
- 指令指针IP不能作为mov指令的操作数
解决方案
需求 | 错误指令 | 正确指令 | 备注 |
---|---|---|---|
把字变量VARB的值传送给字变量VARA | MOV VARA, VARB | MOV AX, VARB MOV VARA, AX | |
变量定义(会画图)
定义字节单元伪指令DB
定义字单元伪指令DW
子程序
subname proc ;具有缺省属性的subname过程
push ax ;保护寄存器:顺序压入堆栈
push bx ;ax/bx/cx仅是示例
push cx
… ;过程体
pop cx ;恢复寄存器:逆序弹出堆栈
pop bx
pop ax
ret ;过程返回
subname endp ;过程结束
用寄存器传递参数
用变量传递参数
用堆栈传递参数
段转移
NEG指令
存储器的分段问题
ewH-1609088542836)]
段转移
[外链图片转存中…(img-IvSVKsTr-1609088542838)]
[外链图片转存中…(img-rI6MgpPO-1609088542840)]
NEG指令
[外链图片转存中…(img-KznNMrGI-1609088542844)]
存储器的分段问题
[外链图片转存中…(img-lq02vZIe-1609088542846)]