运行 DOSBox
mount c: d:\masm
C:
masm test.asm
回车3次
link test.obj
回车4次
debug test.exe
-r
运行
-t
继续
-t 10
运行10条指令
-d
内存
-u
源码
-p
跳过(尤其是库函数)
-q
退出
常用指令
assume
声明
mov
复制内存 mov ax, [bx]
inc
加一 inc ax
dec
减一
jmp
跳转 jmp loop1
cmp
比较大小 cmp ax, bx
add
增加某数 add ax, 10
其他指令
ADC
带进位加法
LEA dx, [0000]
相当于MOV
字符串
? 比较大小
cmp cx, 0
比较结果执行下面的语句
ja
> above
jb
< blow
jbe
<=
jae
>=
jz
== (相减为 zero)
jnz
!=
库函数
INT 21
MOV AH 0A
时:接收一个用户输入到 ds[dx]
MOV AH 4C
时:退出程序,返回操作系统
寄存器拆开
AX = AH + AL
只有 AX BX CX DX 这四个可以拆开用
常用代码块
声明变量
1 2
| assume cs:code, ds:data1 mov ax, data1
|
变量加一
1 2 3
| mov al, [bx] ; 数据段寄存器DS 到 寄存器 inc al ; 增加 1 mov [bx], al ; 寄存器 到 DS
|
循环
1
| for (i = 0; i < 10; i++);
|
1 2 3 4 5 6
| mov cx, 0
loop1: inc cx cmp cx, 10 jb loop1
|
while 循环
1 2 3 4 5
| i = 10; while (i >= 0) { i--; }
|
1 2 3 4 5 6 7 8 9 10
| mov ax, 10
loop1: cmp ax, 0 jb next ;P1 dec ax jmp loop1
next:
|
接收用户输入
1 2 3 4 5
| MOV AX, 076A MOV DS, AX MOV DX, 0000 MOV AH, 0A INT 21
|
清屏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| mov ax,cs mov ss,ax mov sp,0x7c00 ;set stack and sp
mov ah,0x06 mov al,0 ; 准备清窗口
mov ch,0 ; 左上角的行号 mov cl,0 ; 左上角的列号 mov dh,25 ; 右下角的行号 mov dl,80 ; 右下角的行号 mov bh,0x07; 属性为蓝底白字 int 0x10 ; 执行清空操作
@1: jmp @1
times 510-($-$$) db 0 db 0x55,0xaa
|
画白线
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| mov al, 0x13 ; VGA320×200×8bit 显示模式 mov ah, 0x00 int 0x10 mov ax, 0x0a000 ; 往显存中放入点数据 mov ds, ax mov dl, 30 mov ax, 0 f: mov bx, ax mov [ds:bx], dl inc ax cmp ax, 50 ja io jmp f io:
|
画线函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| org 0x7c00
mov ax, 80 ; y mov bx, 50 ; x1 mov cx, 150 ; x2 call drawline ; 运行画线 ; y:ax, x1:bx, x2:cx drawline: mov dx, 320 ; 屏幕宽是320 mul dx ; dx *= ax 16位中AX为被乘数,8位中AL为被乘数 sub cx, bx ; cx = x2-x1 线的宽度 add bx, ax ; 横偏移量+横纵偏移量 = 偏移位置 mov dl, 1 ; 色号 loop0: mov [ds:bx], dl ; 填充颜色 inc bx ; 偏移位置+1 dec cx ; 循环次数-1 jnz loop0 ; 受到上面的DEC的ZF标志位 RET
|
画竖线
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ;**************************************** ; y1->ax, y2->cx, x->bx ;**************************************** DrawVerticalLine: mov dx, 320 ; w = 320 mov bp, dx sub cx, ax ; y1 = y2-y1 循环次数 mul dx ; ax = w * y1 纵偏移量 add bx, ax ; 横纵偏移量 mov dl, 1 x1: mov [ds:bx], dl add bx, bp dec cx jnz x1 ret
|
设置颜色
1 2 3 4 5 6 7 8 9 10 11 12 13
| mov al, 1 ; 颜色号 mov dx, 0x3c8 out dx, al
mov al, 100 ; R / 4 = 25 mov dx, 0x3c9 out dx, al
mov al, 0 ; G out dx, al
mov al, 0 ; B out dx, al
|
数组
1 2 3 4 5 6 7 8 9
| ;rgb db 100, 0, 0, 0, 100, 0, 0, 0, 100 rgb db 100, 0, 0, db 0, 100, 0, db 0, 0, 100
mov ax, 0 mov ds, ax mov si, rgb mov [ds:si], ... ; 偏移地址,si为下标
|
进栈出栈保存变量
1 2 3
| push ax mov ax, 0 pop ax
|
定时器
每隔18分之一秒运行一次,多个任务的话会被覆盖掉
1
| mov word [ds:0x20],int_timer0
|
打印字符
函数:在 ex:bx
的位置显示一个 ‘A’
1 2 3 4 5 6 7 8 9 10
| int_timer0: mov byte [es:bx],'A' mov byte [es:bx+1],0x0a inc bx ; 自增两次到下次打印的字符 inc bx
mov al,0x20 mov dx,0x20 out dx,al ;EOI=0 中断 iret
|
获取按键输入
1 2 3 4 5 6 7 8 9 10 11 12
| int_key: mov dx, 0x20 ; 下一个键值可以进来了(没有这一段就只能输入一次按键了) mov al, 0x61 out dx, al
mov dx, 0x60 ; 读取一次按键 in al, dx cmp al, 0x9e jz func0
func0:
|
显示一个数字