汇编语言程序设计杂记

加油学汇编!


OF与CF的计算

  1. CF=1:表示无符号数的溢出

  2. OF=1:表示有符号数的溢出

  3. 但是在计算机中(补码),无法辨别有符号数和无符号数,就也无法根据上述方法来确定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,分别是白,红,绿,蓝。

EQU


详细将下方链接
https://blog.csdn.net/husion01/article/details/6453538
EQU:equal,感觉类似c语言的宏定义(?)


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不为1CX不为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中放得相对表首地址的偏移地址

待更新…

汇编小白笔记,若有错误欢迎指出~~

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值