运行 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:
   | 
 
显示一个数字