加油学汇编!
OF与CF的计算
-
CF=1:表示无符号数的溢出
-
OF=1:表示有符号数的溢出
-
但是在计算机中(补码),无法辨别有符号数和无符号数,就也无法根据上述方法来确定CF,则:
对于CF:
<1>加法运算中,看和的最高位是否向更高位进1,是的话CF为1;
<2>减法运算中, 当被减数最高位向更高位借位时,CF=1。
<3>减法运算中,若利用补码,将减法转化为等价的加法 ,得出来的CF值将与我们想要的答案CF值相反。
对于OF: 若正正得负、负负得正,OF为1。
栈
定义一个栈:
S1 SEGMENT
DW 30H DUP(0)
TOP LABEL WORD
S1 ENDS
注意:栈的单位是两个字节,即是以字为一个储存单位,所以上述代码定义了一个长为30H字(60H字节)的栈区
特点:先进后出
堆栈指针SP:初始化当前栈的长度。表示堆栈基址与栈顶之间的距离,以字节为单位,按上方代码的话,SP里存的是60H。
栈底bottom:存值始终为栈初始容量减2。
- 进栈:PUSH SRC
(SP) - =2
数据(SRC)进栈,这时候SP指向的地址((SP)+1,(SP))中存着数据(SRC)。 - 出栈:POP DST
(DST)=((SP+1),(SP))
(SP)+=2
注:
- (SP):SP中储存的值
- [SP]:表示地址,即也是SS:SP
- SP指向的地址为SS:SP,SP中存的是偏移量
- SRC:源操作数
- DST:目的操作数
汇编代码格式
S1 SEGMENT
DB 30H DUP(0)
S1 ENDS
S2 SEGMENT
DW 30H DUP(0)
TOP LABEL WORD
S2 ENDS
S3 SEGMENT
ASSUME CS:S3,DS:S1,SS:S2
MAIN PROC FAR
MOV AX,S1
MOV DS,AX
MOV AX,S2
MOV SS,AX
LEA SP,TOP
;...
MOV AH,4CH
INT 21H
MAIN ENDP
S3 ENDS
END MAIN
输入输出
在21H中:
- 1号:输入字符,存在AL寄存器。
- 2号:输出DL寄存器上的字符。
- 9号:输出一个字符串,调入参数DX是以‘$'结尾的字符串的首地址。
- 10号(0A号):输入一个以回车为结尾的字符串,调入参数DX是缓冲区首地址而非字符串首地址,返回值存在AL【00表示有输入,FF表示无输入】和(DS:DX+1)单元中【输入字符数–不包括回车】。
【记忆 1-2-9-10:入-出-出-入】
21H-0A号功能的缓冲区
在数据段中:
S2 SEGMENT
BUFF DB 101,?,101 DUP(0)
EEN DB 0DH,0AH,24H
S2 ENDS
“ BUFF DB 101,?,101 DUP(0) ” 定义了一个缓冲区BUFF,注意:
- 只能用DB。
- " 101 ":是缓冲区中第一个单元中的数字,即该缓冲区可存最大字符数(包括回车)。
- " ? ":是缓冲区第二个单元中是数字,这里填入‘?’,即随机值。因为此处数据代表该缓冲区实际填入字符(不包括回车),将由系统自己填入。
- " 101 DUP(0) ":将后面的101个单元赋值为0。
也就是说,在缓冲区中的数据是这样的: 101,?,0,0,…,0 。 【问号表示随机值,0共101个】 - 缓冲区最大可存字符数:255(包括回车)。
- 缓冲区最小的空间为3个。
" EEN DB 0DH,0AH,24H "
一个字符串ENN:回车+换行+‘$’,用21H的9号功能输出即实现了换行。
4种移位
逻辑左\右移【补0】【无符号数】
SHL
SHR
算术左\右移【前补符号后补0】【针对有符号数】
SAL
SAR
循环逻辑左\右移【首补尾\尾补首】
ROL
ROR
带进位循环左\右移【前任cf补位】
RCR
RCL
移位操作后面可以是1或CL,其余不可。
eg:ROR BX,CL
eg:ROR BX,1
TEST和CMP
TEST AX,8000H;【AND】
检查AX中的数字第15位是否为1,且不改变AX中的数值, 只改变程序状态字(PSW)。
TEST可以理解为是不改变DST的AND操作,但是会影响PSW.
CMP AX,‘0’ ;【SUB】
判断AX中存的数和’0‘的关系
其实就是做减法,根据结果来判断大小关系,结果只改变PSW。
需要记得的ASSIC码值
0:30H,A:41H,a:61H
记住数字,大写字母,小写字母各自起始值即可。
汇编实现输入数字储存在内存时,需要用到这些进行一些计算。
回车:0DH,换行:0AH
这个可以记也可不记,但是感觉挺常用,记着也没多大功夫。【虽然可以直接用字符代替】
一个我觉得值得记录的BUG
一个输入3位十进制的程序:
S1 SEGMENT
DB 30H DUP(0)
S1 ENDS
S2 SEGMENT
DW 30H DUP(0)
TOP LABEL WORD
S2 ENDS
S3 SEGMENT
ASSUME CS:S3,DS:S1,SS:S2
P1 PROC FAR
MOV AX,S1
MOV DS,AX
MOV AX,S2
MOV SS,AX
LEA SP,TOP
XOR BX,BX
MOV CX,3
MOV SI,10
L1:MOV AH,1
INT 21H
CMP AX,'9'
JA L1
CMP AX,'0'
JB L1
AND AX,000FH
XCHG AX,BX
MUL SI
ADD BX,AX
LOOP L1
MOV AH,4CH
INT 21H
P1 ENDP
S3 ENDS
END P1
然而以上代码会死循环,无限输入,明显出BUG。
只需要将比较代码改成以下:
L1:MOV AH,1
INT 21H
CMP AL,'9'
JA L1
CMP AL,'0'
JB L1
或者
L1:MOV AH,1
INT 21H
XOR AH,AH
CMP AX,'9'
JA L1
CMP AX,'0'
JB L1
这是因为输入内容只存在AL里,然后输入时因为调用1号功能所以AH里是1。所以假设这时候输入的是0-9的字符,AL中数值就是30H-39H,而AH此时为1,所以输入0-9时,两个cmp得出来的都是大于。所以要么AL去cmp就好,要么在cmp上面加个 XOR AH,AH。
写屏-变色
(屏幕是25行*80列)
全屏变绿:
-debug
-f b800:0 f9f 20 20
全屏网格变绿(20)代码
-debug
-f b800:0 f9f 20 c5 20//格式:-f b800:0 f9f 20 x;x可为70,40,20,10,分别是白,红,绿,蓝。
CLD和STD
CLD:clear DF,清零
STD:set DF,置一
类似地,
CLC:clear CF;
STC:set CF
LOOP和REPNE
-
LOOP
cx不为0就继续比,和循环语句块搭档
该部分循环语句块之前,cx必须大于等于1,否则将死循环
自理解的“loop L”
(1)cx自减1
(2)cx不为0就跳到L行 -
REPNE
不相等就继续比,后面只能跟一句循环语句
自理解"repne scasw"
(1)(AX)-(ES:[DI])【影响ZF】
(2)DI 自加2(或自减2,取决于DF)
(3)ZF不为1且CX不为0就继续回到(1)
因此如果AX真的和串中某个数据k相等,那么最后退出循环后,ES:[DI]指的是数据k的下一位(或前一位,这个看DF)
加减乘除
- add普通加法 adc带进位加法
- sub普通减法 sbb带进位减法
带进位加减法可用于大数加减,比如32位数据相加,那么:
数A:高位dx,低位ax
数B:高位si,低位di
add ax,di
adc dx,si
或
sub ax,di
sbb dx,si
结果存在 dx,ax
- mul无符号乘法 imul有符号乘法
- div无符号除法 idiv有符号除法
- 被除数:
除数为8位, 被除数为16位:AX.【AX】
除数为16位, 被除数为32位, AX存低16位,DX存高16位.【DX AX】 - 结果:
除数为8位, 则AL:商;AH:余数【AH AL 余数 商】
除数为16为, 则AX:商; DX:余数【DX AX 余数 商】
- 被除数:
有符号数求和,需要判断正负,正的直接加,负的neg后再减即可。
无符号和有符号的比较也不一样
无符号:A-above,B-below
有符号:G-greater,L-less
这个很重要!!!
NEG
MOV CX,-1//CX=-1D=0FFFFH
NEG CX//CX=1D=1H
MOV CX,1//CX=1D=1H
NEG CX//CX=-1D=0FFFFH
可知,neg是沟通正负数的桥梁,可正变负,负变正(扭转乾坤颠倒黑白)
Ps:"//"并非汇编注释符号,“;”才是。这里是为了代码块里能好看点才用“//”
又一Bug
MOV AX,4929H
MOV DX,0FH
AND DX,AX
ADD DX,'0'
MOV AH,2
INT 21H
MOV AX,4929H
MOV DX,0F000H
AND DX,AX
ADD DX,'0'
MOV AH,2
INT 21H
前者可以正常输出,后者是‘0’。
and失常??并不
原因在于,后者and后,DX前8位即DH存下了and后的蛛丝马迹;但是DL被屏蔽了,即各位全0。
而2号功能输出的是DL。
而且在第二种代码,就算2号功能可以输出整个DX,截取部分储存在DX最高4位,是个0001都变成了4096
LDS指令及LES指令
-
LDS OPRD1,OPRD2
OPRD1 为任意一个16位的寄存器.
OPRD2 为32位的存储器地址. -
LDS DI,[BX]
该指令的功能是把BX所指的32位地址指针的段地址送入DS,偏移地址送入DI. -
LES指令功能同上,只不过是载入ES
-
通常DS与DX或baiBX或SI配合使用,ES与BX或DI配合便用du。
XLAT指令
- XLAT
以DS:[BX+AL]为地址,提取存储器中的一个字节再送入AL。
即:[BX+AL]->AL - XLAT是查表指令,将BX指向表的首地址,AL中放得相对表首地址的偏移地址
待更新…
汇编小白笔记,若有错误欢迎指出~~