汇编程序深入

简单的汇编模板

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相差0x30H,A~F的二进制数和它的ASCII相差37H。所以在转换时先对四位二进制数进行判断,是数字加0x30H,是字母加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

猜你喜欢

转载自blog.csdn.net/recclay/article/details/80102878