简单的汇编模板
DATA SEGMENT
...
DATA ENDS
EXTRA SEGMENT
...
EXTRA ENDS
STACK SEGMENT STACK
...
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, ES:EXTRA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
MOV AX, EXTRA
MOV ES, AX
...
MOV AH, 4CH
INT 21H ;系统功能调用,返回操作系统
CODE ENDS
END START
看START
标号里面的前4行代码,必须借助通用寄存器,当然可以不是AX寄存器!
MOV是不能直接把立即数放入段寄存器中的,必须使用通用寄存器进行过渡!以上四条语句用来装载数据段地址
和附加段地址
。
段的起始地址是AT
,偏移地址是ORG
32768 是 2^15次方,32K
逻辑移位的时候如果移的位数大于1,必须先装入CL
,然后再移!!!
eg:编程实现 Z = ((x+y)*8-x) / 2
区分算术左移和逻辑左移(SAL=SHL)是一样的,但是算术右移和逻辑右移(SAL≠SHL)是不一样的!(逻辑右移,最高位补0)(算术右移最高位不变)
DATA SEGMENT
VARX DW 0006H ;X的值
VARY DW 0007H ;Y的值
RESULT DW ? ;结果存放的地方
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV DX, VARX;x的值放入DX
ADD DX, VARY;加上y的值
MOV CL, 3;8是2的3次方,准备左移3位
SAL DX, CL;左移
SUB DX, VARX;根据题目要求再减去x
SAR DX, 1;再除以2,右移1位
MOV RESULT, DX;把结果放入RESULT中
MOV AH, 4CH
INT 21H
CODE ENDS
END START
什么时候程序必须加堆栈呢? 当程序中有中断;调用子程序!
当然一般写上就更好了,这样可以有效的防止堆栈溢出,程序错误!
可以调试看下寄存下,一步一步观察结果。。。
没毛病、、、、
编程实现:符号函数(练习判断以及跳转)
关于跳转有无条件跳转:JMP
。以及有条件跳转,JX
。关于X有19条指令。。
DATA SEGMENT
XX DB 5
YY DB ?
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV AL, XX
CMP AL, 0;X-0建立标志位
JGE BIGER ;X>=0跳转到BIGER
MOV AL, -1 ;X<0赋值-1
JMP JUS2 ;别忘了这个,如果没有这个程序还会顺序往下执行的!!!
BIGER:
JG JUS1 ;X>0跳转到JUS1
MOV AL, 0;X=0赋值0即可
JMP JUS2
JUS1:MOV AL, 1 ;X>0赋值1
JUS2: MOV YY, AL ;赋最后的YY
MOV AH, 4CH
INT 21H
CODE ENDS
END START
输入5,返回1。。没毛病、、、
eg:编程实现:数组的a1+....+a10
loop
执行指令的时候,先将CX减1没看是否等于0,不为0转至标号处执行程序,否则向下执行!
DATA SEGMENT
TABL DW 1,2,3,4,5
DW 6,7,8,9,10
YY DW ?
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV AX, 0;初始化
MOV BX, OFFSET TABL;取数组的输地址
MOV CX, 10;设置循环次数
LOP:
ADD AX, [BX];开始累加
INC BX;地址加1
INC BX;注意了,为什么加两个呢?因为定义的数组是DW类型的!,而地址每次只能加1个字节!
DEC CX;个数减1
JNZ LOP;CX不等于跳转到LOP 以上两句等价于 LOOP LOP
MOV YY, AX
MOV AH, 4CH
INT 21H
CODE ENDS
END START
1+2+…+10 = 55 = 37H。。。没毛病。。。
编程实现:数据块中正数的个数
DATA SEGMENT
D1 DB 1,-2,3,4,5
DB 6,7,-8,9,10
COUNT EQU $-D1
RS DW ?
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV BX, OFFSET D1
MOV CX, COUNT
MOV DX, 0
JUDGE:
MOV AL, [BX];BX无法和0直接比较需先移入AL
CMP AL, 0
JLE POSITIVE
INC DX
POSITIVE:
INC BX
DEC CX
JNZ JUDGE;这里无需再判断CX与0的大小了,直接条件跳转就行。还可以简写为LOOP JUDGE
MOV RS, DX
MOV AH, 4CH
INT 21H
CODE ENDS
END START
8个正数没错了,。。。
3个地方需要注意:
①、COUNT EQU $-D1
,$表示当前指针,当前指针减去第一个数据块名字不就是第一个数据块的总长度嘛!!
②、DEC CX JNZ JUDGE
无需让CX和0再比较然后跳转。当然了这句也等价于LOOP JUDGE
③、[BX]
是无法直接和0CMP
的,需要借助AL!!!
编程实现:统计16位二进制数中1的个数,并存入CX
左移或者右移指令的最高位会移到CF中去,只要判断CF是多少,就能判断这个数的该位是0还是1了!!!
DATA SEGMENT
DATA ENDS
STACK SEGMENT STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV AX, 04H
MOV CX, 0
LOP:
AND AX, AX;相与后建立标志位
JZ STOP;AX=0则跳转到STOP
SAL AX, 1;算术左移1位
JNC NOD;判断CF是否等于0,等的话跳到NOD
INC CX
NOD:
JMP LOP
STOP:
HLT;暂停
MOV AH, 4CH
INT 21H
CODE ENDS
END START
编程实现在一串字符串中查找'#',若找到记录AL=0,否则为1
字符串输出(9号功能),通常需要用0AH,0DH来控制光标的回车和换行,并必须用'$'
来作为结束标志。
DATA SEGMENT
BUF DB 'ABC#E'
LEN EQU $-BUF
DATA ENDS
STACK SEGMENT PARA STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV CX, LEN
MOV DI, OFFSET BUF
MOV AL, '#';将要查找的字符存入AL
REPNZ SCASB;逐个查找
JZ Y;若ZF=1,表示找到
MOV AL, 1;没找到赋值AL
JMP E;跳转到显示
Y:
MOV AL, 0;找到赋值0
E:
ADD AL, 30H
MOV DL, AL
MOV AH, 02H
INT 21H
MOV AH, 4CH
INT 21H
CODE ENDS
END START
编程实现十六位二进制数转换成四位十六进制数的ASCII
注意先观察规律,数字0~9
它的二进制数和ASCII
相差0x30
H,A~F的二进制数和它的ASCII
相差37H
。所以在转换时先对四位二进制数进行判断,是数字加0x30
H,是字母加0x37H
….
DATA SEGMENT
BIN1 DW 1001110011010111B
HEX1 DB 4 DUP(0)
DATA ENDS
STACK SEGMENT PARA STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
BINHEX:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV CH, 4;十六进制数个数
LEA DI,HEX1
MOV BX,BIN1;取待转换的二进制数
CONV1:
MOV CL, 4
ROL BX, CL;循环左移四位,将最高四位移至最低位
MOV AL, BL
AND AL, 0FH;屏蔽高四位
CMP AL, 09H;0~9吗
JLE ASCI
ADD AL, 07H;A~F 注意了这里只是加7因为会顺序执行,下面会自己再加30的
ASCI:
ADD AL, 30H
MOV [DI], AL
INC DI
DEC CH
JNZ CONV1
MOV AH, 4CH
INT 21H
CODE ENDS
END BINHEX
完全OJBK的程序!!!
编程实现比较两个字符串,相等返回0,不相等返回1
DATA SEGMENT
BUF1 DB 'ABC'
LEN1 EQU $-BUF1
BUF2 DB 'ABD'
LEN2 EQU $-BUF2
DATA ENDS
STACK SEGMENT PARA STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV CX, LEN1;CX存LEN1的长度
CMP CX, LEN2;比较LEN1和LEN2的长度
JNZ NO;如果不相等,跳转至NO
MOV SI, OFFSET BUF1;相等的话,获取两者的偏移地址
MOV DI, OFFSET BUF2
REPE CMPSB;单字节比较SI和DI
JZ YES;CX为0跳出循环,说明两字符串相等
NO:
MOV AL, 1;CX不为0赋值1
JMP L;跳到最后的结果显示
YES:
MOV AL, 0;相等赋值0,顺序执行结果显示
L:
ADD AL,30H;0~9想要显示,需转换为ASCII,即加30H
MOV DL,AL;使用2号功能
MOV AH,02
INT 21H
MOV AH, 4CH
INT 21H
CODE ENDS
END START
测试很OK
编程实现内存的数据传送
DATA SEGMENT
BUF1 DB 'ABC'
LEN1 EQU $-BUF1
BUF2 DB 64 DUP('$');BUF2空间全部复制为字符串结束符
DATA ENDS
STACK SEGMENT PARA STACK
DB 100 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;核心代码段
MOV CX, LEN1
MOV SI, OFFSET BUF1
MOV DI, OFFSET BUF2
REP MOVSB
MOV DX, OFFSET BUF2;显示传送结果
MOV AH, 9
INT 21H
MOV AH, 4CH
INT 21H
CODE ENDS
END START