起初是因为我们的期末要考。。。

玩了一个学期的我当然是屁都不会。
这一周一轮复习,整理了汇编的基础知识笔记https://blog.csdn.net/xinghuayu_lin/article/details/156052083
感觉就能上手做做题了。
过了这三题,也渐入佳境了。有了算法基础其实学任何一门语言都很快的。
T1
这是我完全屁都不知道的状态写出来的代码
INT 21
SUB AX,1
INT 21
ADD AX, BX
INT 21
ADD AX, BX
INT 21
ADD AX, BX
正解代码:
DATA SEGMENT
CHR DB ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
;读入一个字符
MOV AH, 1 ;功能号01H:读入一个字符
INT 21H ;返回字符在AL中
MOV CHR, AL ;保存输入字符
;输出前一个字符
MOV AL, CHR
DEC AL
MOV DL, AL
MOV AH, 2 ;功能号02H,显示DL
INT 21H
;输出原字符
MOV DL,CHR
MOV AH, 2 ;功能号02H,显示DL
INT 21H
;输出后一字符
MOV AL, CHR
INC AL
MOV DL, AL
MOV AH, 2 ;功能号02H,显示DL
INT 21H
;结束程序
MOV AH, 4CH
INT 21H
CODE ENDS
END START
然后我发现了,我差的就是这一部分:

以及寄存器的使用,AX、BX、CX、DX,基本不会。我一开始把他们当变量整。
T2
拙劣的代码:
DATA SEGMENT
DB 50 DUP(?)
ARRAY[50]
DATA ENDS
CODE SEGMENT
ASSUME CS:DATA,DS:ARRAY
START:
MOV CX, 50
MOV AX, 0
MOV BX, 0
FUN:
CMP DS:[SI], 0
JG ZHENG
JZ ZERO
JMP NEXT
ZERO:
INC BX
JMP NEXT
ZHENG:
INC AX
NEXT:
ADD SI,2
LOOP FUN
MOV DL, AL
MOV AH, 2
INT 21
MOV DL, BL
MOV AH, 2
INT 21
MOV DL, 50
SUB DL, AL
SUB DL, BL
MOV AH, 2
INT 21
CODE ENDS
ENDS START
正解代码:
DATA SEGMENT
ARRAY DW 10,-3,0,5,0,-7,2,9,-1,0
COUNT EQU 10
POS DB ? ; 正计数器0计数器负计数器
ZERO DB ? ; 全部设置成字节,方便转入DL
NEG DB ? ;
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA ; 把 DS 段寄存器指向 DATA 段,
MOV DS, AX ; 使程序能够正确访问数组和变量。
MOV POS, 0
MOV ZERO, 0
MOV NEG, 0
MOV CX, COUNT
MOV SI, 0
FUN:
MOV AX, ARRAY[SI] ;AX是当前元素
CMP AX, 0
JG IS_POS
JE IS_ZERO
IS_NEG:
INC NEG
JMP NEXT
IS_ZERO:
INC ZERO
JMP NEXT
IS_POS:
INC POS
NEXT:
ADD SI, 2
LOOP FUN
MOV DL, POS
ADD DL, 30H ;DL输出的永远是ASCII,不是数字
MOV AH, 2
INT 21H
MOV DL, ZERO
ADD DL, 30H ;DL输出的永远是ASCII,不是数字
MOV AH, 2
INT 21H
MOV DL, NEG
ADD DL, 30H ;DL输出的永远是ASCII,不是数字
MOV AH, 2
INT 21H
MOV AH, 4CH
INT 21H
CODE ENDS
END START
总结:现在开始已经有点开窍了,代码能够成型了
但是最典型的:寄存器瞎几把用,不会主动设置变量名
仿照C语言就好了,该设置的别省
然后再复习一遍:AL是缓冲区读入字符,DL是输出字符类型,AH设置4CH是结束程序。
T3
拙劣的代码
DATA SEGMENT
STR
POS DB ?
FLAG DB ?
DATA SEGMENT
CODE SEGMENT
ASSUME CS: CODE, DS: DATA
START:
MOV AX, DATA
MOV DS, AX
MOV POS, 0
MOV FLAG, 0
MOV SI, 0
FUN:
MOV AX, DS:[SI]
CMP AX, 41H
JNZ NEXT
MOV POS, SI
MOV FLAG, 1
JMP FIND
NEXT:
INC SI
LOOP FUN
JMP FINISH
FIND:
MOV DL, POS
ADD DL, 30H
MOV AH, 02H
INT 21H
FINISH:
MOV AH, 4CH
INT 21H
CODE ENDS
ENDS START
这里就要讨论到一个问题了:
DL 必须是 ASCII 字符,否则会输出乱码。
因此:无法输出两位(或多位)数字的位置,只能输出 0~9。
这是不支持2位数的代码
DATA SEGMENT
STR DB 50 DUP(?)
POS DB ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA
MOV DS, AX
;读入字符串
MOV SI, 0
READ_LOOP:
MOV AH, 1
INT 21H
CMP AL, 0DH ;回车
JE DONE_INPUT
MOV STR[SI], AL
INC SI
JMP READ_LOOP ;用JMP模拟循环,太屌了
DONE_INPUT:
MOV STR[SI], 0 ;用0结束字符串
MOV SI, 0
MOV POS, 0FFH ;FF表示未找到,省略flag
SEARCH:
MOV AL, STR[SI]
CMP AL, 0 ;//到结尾了都没找到
JE NOT_FOUND
CMP AL, 'A'
JE SHOW_POS
INC SI
JMP SEARCH
NOT_FOUND:
MOV DL, '-'
MOV AH, 2
INT 21H
JMP EXIT
SHOW_POS:
MOV POS, SI
MOV DL, POS
ADD AL, 30H
MOV DL, AL
MOV AH, 2
INT 21H
EXIT:
MOV AH, 4CH
INT 21H
CODE ENDS
ENDS START
这里是支持两位数的代码,其实3位数以及以上,你也不能只用AX了,麻烦的一批。
DATA SEGMENT
STR DB 50 DUP(?)
POS DB ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA
MOV DS, AX
;读入字符串
MOV SI, 0
READ_LOOP:
MOV AH, 1
INT 21H
CMP AL, 0DH ;回车
JE DONE_INPUT
MOV STR[SI], AL
INC SI
JMP READ_LOOP ;用JMP模拟循环,太屌了
DONE_INPUT:
MOV STR[SI], 0 ;用0结束字符串
MOV SI, 0
MOV POS, 0FFH ;FF表示未找到,省略flag
SEARCH:
MOV AL, STR[SI]
CMP AL, 0 ;//到结尾了都没找到
JE NOT_FOUND
CMP AL, 'A'
JE SHOW_POS
INC SI
JMP SEARCH
NOT_FOUND:
MOV DL, '-'
MOV AH, 2
INT 21H
JMP EXIT
SHOW_POS:
MOV POS, SI
MOV AL, POS
;N位数字输出逻辑
MOV AH, 0
MOV BL, 10
DIV BL
ADD AL, 30H
MOV DL, AL
MOV AH, 2
INT 21H
ADD AH, 30H
MOV DL, AH
MOV AH, 2
INT 21H
EXIT:
MOV AH, 4CH
INT 21H
CODE ENDS
ENDS START