- 环境配置
- xp环境配置
- 拷贝masm615到指定目录
- 将masm615目录添加进环境 变量
- 在cmd中输入ml,可识别即配置成功
win10使用dosbox示例:
找到dosbox的目录如下:将masm611拷贝进去
然后修改:DOSBox 0.74 Options.bat文件进行配置
将masm611的所在目录挂载到dosbox上
原来:
改动:
若有问题,可以尝试将路径用””包起来
例如:
- 编译命令
- ml/c asm文件.asm
- link asm文件.asm
- 编译+调试 脚本
- ml/c %1.asm
- link %1.obj
- debug %1.exe
- 示例:
示例代码:
assume cs:code,ds:data,ss:stack
data segment
g_sz db "hello word$" ;用$表示字符串的结束
data ends
stack segment stack
db 128 dup (0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax
mov ah,9
int 21h
mov ax,4C00H
int 21H
code ends
end start
根据上面的编译+调试 脚本,我们新建一个build.txt(修改完改后缀名为.bat)
然后将其放到dosbox所挂c盘下
- 使用build(刚刚创建的.bat文件)
入口和段
- 入口
- 入口点指定使用关键字end,后面跟标号名
- 入口点可以写在任意段外面,但一般写在文件末尾
- 段
- 一个程序必须至少有一个段
- 一个程序中可以定义多个段
- 段不能嵌套
- 段可以重命名,重命名的段会被编译到同一块内存中
- 注释
- 汇编中使用分号(;)来标注行注释
- 常量
- 整数可以支持多个进制
- 数值必须以数字开头,如果非数字,前面必须加0
- 负数前面可以加减号(-)
- 字符
- 字符可以用单引号(‘)或双引号(“”)
- mov byte [bx],’$’
- mov byte [bx],”$”
- g_sz db “hello world$”;16位汇编中以美元符结尾
- 字符可以用单引号(‘)或双引号(“”)
- 变量
- 整数可以支持多个类型
- 整数可以有多个初值,未初始化的值用问好(?)表示
- 变量一般定义在一个单独的段中
assume cs:code,ds:data,ss:stack
data segment ;数据段
g_db db 55h
g_dw dw 6644h
g_dd dd 77887788h
g_dq dq 1122334455667788
g_dt dt 11223344556677889900h
g_dw0 dw ? ;是?的话,原来是什么数据就是什么,不初始化
g_sz db "hello world$";16位汇编中以美元符结尾
data ends
stack segment stack
db 128 dup (0)
stack ends
code segment
val db 56h
start:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,4C00H
int 21H
code ends
end start
- 数组
data_seg1 segment
g_ary1 dw 5566h,7788h,9966h
g_ary2 dw 10h dup(6666h)
g_ary3 dw 9999,16 dup(7777h),4455h,16 dup(3322h)
data_seg1 ends
- 属性
- masm提供了很多伪指令,可以获取变量的大小和地址,称之为变量的属性。
- ```matlab assume cs:code,ds:data,ss:stack
data segment ;数据段 g_db db 55h g_dw dw 6644h g_dd dd 77887788h g_dq dq 1122334455667788 g_dt dt 11223344556677889900h g_dw0 dw ? ;是?的话,原来是什么数据就是什么,不初始化 data ends
data_seg1 segment g_ary1 dw 5566h,7788h,9966h g_ary2 dw 10h dup(6666h) g_ary3 dw 9999h,16h dup(7777h),4455h,16 dup(3322h) data_seg1 ends
stack segment stack db 128 dup (0) stack ends
code segment
val db 56h
start:
mov ax,stack
mov ss,ax
mov sp,128
assume ds:data_seg1 ;要先用assume才能用mov指令访问对应段的标号
mov ax,data_seg1 ;取段的地址
mov ds,ax
mov ax,seg g_ary3 ;取g_ary3的段地址
mov ax,offset g_ary3 ;取g_ary3的偏移地址
lea ax,g_ary3
mov ax,type g_ary2
mov ax,length g_ary2
mov ax,size g_ary2
mov ax,4C00H
int 21H
code ends end start
<a name="WSGda"></a>
## 堆栈
- stack关键字让程序在被加载的时候指定ss、bp和sp。
- 使用数组为栈设置大小
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12923347/1632757844943-0531bcb8-494a-4270-92bc-0f9ba57d1b61.png#align=left&display=inline&height=279&margin=%5Bobject%20Object%5D&name=image.png&originHeight=279&originWidth=577&size=109455&status=done&style=none&width=577)
- **调用dos功能号**
- 功能号
- dos系统提供的功能(API),通过21号中断来调用
- 每个功能都有一个编号,通过AH指定功能号
- 每个功能的参数查看手册
- ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12923347/1632758294216-6a520cbe-f286-4392-9e0f-f57b6caaa128.png#align=left&display=inline&height=186&margin=%5Bobject%20Object%5D&name=image.png&originHeight=186&originWidth=349&size=24880&status=done&style=none&width=349)
例:显示字符
```matlab
assume cs:code,ds:data,ss:stack
data segment ;数据段
g_sz db "hello word$" ;用$表示字符串的结束
data ends
stack segment stack
db 128 dup (0)
stack ends
code segment
val db 56h
start:
mov ax,stack
mov ss,ax
mov sp,128
mov dl,"A"
mov ah,2 ;
int 21h
mov ax,4C00H ;程序退出
int 21H
code ends
end start
- 键盘输入示例
assume cs:code,ds:data,ss:stack
data segment ;数据段
g_sz db "hello word$" ;用$表示字符串的结束
g_buf db 255,255 dup(00)
data ends
stack segment stack
db 128 dup (0)
stack ends
code segment
val db 56h
start:
mov ax,stack
mov ss,ax
mov sp,128
assume ds:data
mov ax,data
mov ds,ax
mov dx,offset g_buf
mov ah,0ah ;0ah 输入到缓冲区 ds:dx=缓冲区首地址
int 21h
mov ah,1 ;键盘输入并回显
int 21h
mov ah,7 ;键盘输入无回显
int 21h
mov ah,8 ;键盘输入无回显 检测ctrl-break
int 21h
mov dl,"A"
mov ah,2
int 21h
mov ax,4C00H ;程序退出
int 21H
code ends
end start
先演示输入字符串
assume cs:code,ds:data,ss:stack
data segment ;数据段
g_sz db "hello word$" ;用$表示字符串的结束
g_buf db 255,255 dup(00)
data ends
stack segment stack
db 128 dup (0)
stack ends
code segment
mov dx,offset g_sz
mov ah,9
int 21h
val db 56h
start:
mov ax,stack
mov ss,ax
mov sp,128
assume ds:data
mov ax,data
mov ds,ax
mov dx,offset g_buf
mov ah,0ah
int 0
mov ax,4C00H ;程序退出
int 21H
code ends
end start
修图解析,e那里改变中断向量并表所记载的入口地址,改为code segment 的开始位置,有右边dosbox得知段地址为0785,偏移地址为0000
修改后查看一下
结果如下:
作业
4、 从键盘读入任意字符串(不超过255),并输出字符串长度和字符串内容
5、 从键盘读入任意字符串(不超过255),以第一个字母为文件名,将字符串存入文件。
6、 从键盘读入文件名,打开文件(不超过255),显示文件内容
8、 从键盘读入文件名,打开文件(不超过255),输出文件中字符的个数。
- 5 ```matlab data segment file db ‘?.txt’,0 buf db 100,?,100 dup(?) bufstr db 100,?,100 dup(‘$’) ;键盘输入会往后偏移两位 fh dw ?
error_msg db 0dh,0ah,’error!’,’$’ writer_msg db 0dh,0ah,’open file !input text:’,0ah,’$’ success_msg db 0dh,0ah,’done!’,’$’ data ends
stack segment stack dw 20h dup(?) top label word stack ends
code segment assume ds:data,cs:code,ss:stack p proc far
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
lea sp,top
;输入字符串,取第一个字母为文件名
lea dx,bufstr
mov ah,0ah ;键盘输入字符串到缓冲区
int 21h
mov bl,[bufstr+2]
mov [file],bl
;
lea dx,file ;文件名
mov cx,0
mov ah,3ch ;创建文件
int 21h
jc error
;================================================================= writer: mov fh,ax;save the code of file lea dx,writer_msg ;显示开始写字符 mov ah,09h int 21h
lea dx,buf
mov ah,0ah ;键盘输入字符串到缓冲区
int 21h
lea si,buf ;
inc si
xor ch,ch
mov cl,[si];1
inc si
mov dx,si;2
mov bx,fh;3
mov ah,40h
int 21h
jc error
;=================================================================
success:
lea dx,success_msg
mov ah,09h
int 21h
jmp exit
;=================================================================
error:
mov cx,16
mov bx,ax
l1: rol bx,1
mov dl,bl
and dl,1
add dl,30h
mov ah,02h
int 21h
loop l1
lea dx,error
mov ah,09h
int 21h
exit: mov ah,4ch int 21h
p endp
code ends end p
- 6
```matlab
data segment
FileNameFuf db 100,?,100 dup(0)
TheFile db 100 dup(0)
file db 'test.txt',0
buf db 100 dup(?)
fh dw ?
error_msg db 0dh,0ah,'error!','$'
success_msg db 0dh,0ah,'done!','$'
data ends
stack segment stack
dw 20h dup(?)
top label word
stack ends
code segment
assume ds:data,cs:code,ss:stack
p proc far
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
lea sp,top
;输入文件名
lea dx,FileNameFuf
mov ah,0ah ;键盘输入字符串到缓冲区
int 21h
xor cx,cx
xor al,al
copy:
lea bx,FileNameFuf
add bx,2
add bx,cx
mov al,[bx]
cmp al,0dh
je endcopy
mov si,cx
lea bx,TheFile
mov ds:[bx+si],al
cmp cx,100
je endcopy
inc cx
jmp copy
endcopy:
;
lea dx,file
;open file
lea dx,TheFile
mov al,0
mov ah,3dh
int 21h
jc error
mov fh,ax
;read file
lea dx,buf
mov cx,100
mov bx,fh
mov ah,3fh
int 21h
jc error
; mov cx,ax
; lea si,buf
;l1: mov dl,[si]
; inc si
; mov ah,02h
; int 21h
; loop l1
lea dx,buf ;显示开始写字符
mov ah,09h
int 21h
jmp exit
error:
lea dx,error_msg
mov ah,09h
int 21h
exit:
mov ah,4ch
int 21h
p endp
code ends
end p