00:00
这个今天呢,咱们来讲这个循环啊,是前面呢,咱们已经讲过这个GCC指令了,然后呢,GC指令的如何去构造分支啊,我们也已经学过了,那我们就已知是什么东西呢,就是我们啊有现在有几种状态。比如说我现在123456789,我从这第一行指令开始执行,一直执行到第九行指令,然后结束,这种情况呢,它就是什么呢?它就是一种这个顺序结构,那如果说比如说我从一啊,我执行到五,然后又跳回到二,然后再跳到七啊这种呢,它就是一种选择结构啊,就是说啊,自己去决定在什么位置去继续执行,那如果说我们还有一种东西是什么呢?比如说我现在呢,要进行一个打印啊,那比如说我是木木ah啊,然后一个这个九,然后呢,我INT21因特二机啊,那这种情况下呢,如果说我每次啊都这样调用啊,那它比较麻烦,对不对啊,比如说我要打印这个一,这个打印1000个啊1000个这个字符,那我也我也不可能同样的东西啊,调用1000次这个九和这个R1对不对啊,那肯定是想要一定办法让他去重复执行,那这种重复执行呢。
01:23
就是我们这节课的一个内容啊,稍等一下啊,我这个我这个我这个弹幕有点问题啊,稍等稍等啊,我设置一下。嗯。和亮度。这玩意儿怎么回事儿?
02:00
比较奇怪啊,这个东西算了,我用我手机开一下。好了,我换手机了,用你手机开的话,把那个给我研究一下玩,动不动就灭,不知道为啥,今天不知道咋回事,我我刚才是也是这样。好,然后呢,我们继续啊,那我们就不会说多废话了啊,功能我们已经说明白了,那我们就直接开始写代码,我们直接新建一个文本啊,比如说我有2K啊,还有2K,然后点asm。好,我们依然用我们的这个notepad啊,来这个进行代码一个编写啊,这样比较方便啊,啊就这样,首先啊,我们还是啊进行这个代码段的一个指定。那因为今天我们不不用这个变量啊,所以说呢,我们就不声明这个数据了啊,我们直接一个代码段就解决了,然后我们一个代码一个code segment,然后code code n n s,然后呢,是这个我们还需要一个起始地址啊,我们现在呢,在上边给它来一个这个start,结束的地方呢,来一个这个end start。
03:24
好,然后呢,中间我们开始写代码,那我们已知啊,它是这种循环啊,那我们正常情况下,其实呢,指令里头已经给我们提供了一个这个循环的功能啊,我们可以用GC模拟,也可以用它原始的这个功能,那它原始的功能是什么呢?就是我们在这里边有一个叫做loop的一个指令啊,我们来看一下它这个汇编金油指这个loop指令。就是这个指令啊,你可以看到它的格式呢,就是一个这个loop啊,加上一个标号啊,然后呢,啊这儿呢,你看啊,它这有一些这个功能的介绍啊,比如说什么这个CS,什么CS减一什么,然后什么CS移动什么的啊,然后折移动至标号处,循环执行,直到CS等于零啊然后继续啊执行后续指令,那它这里呢,本质上说的是什么意思呢?啊其实呢,是这个意思,就是我们啊,比如说啊,我们这有一个这个标号啊,我们上节课讲机器指令的时候,已经说过什么是标号了,比如说我这有个标号,然后呢,我这条指令呢,我接下来啊有一个东西。
04:29
我要这个进行一个循环,那我在这儿走呢,我要给给我要这个跳回去对不对,那我们正常来说,我们用GC指令就可以跳回去,那我们的这儿呢,不用机器指令,而是我们使用一个loop指令啊,Loop指令lo到这个LP上,那么如果说这是一条机指令,比如说这是一个GP jump指令,那它呢这呢就形成了一个死循环啊,它就一直在执行这个循环,但是我们lo指令不一样,Lo呢,它是有一个这个限制的,就是什么呢?就是它是根据你这个C通用的值来进行这个循环的,那什么意思呢?就比如说我这里环,那它呢,次数是这样的,比如说我们给他一个十,那这个当他第一次执行这个LP跳转到上的时候,它的这个的值就减了一,它就变成了九,当再执行一次循环,它就变成了八啊,直到变成零的时候,Lo就不再行,而是往下走。然后这个就束。
05:29
注程序了,那我们现在呢,可以来给他看一下,比如说我们用一个九啊,这样比较好打印啊,然后我们后边给他写一个这个暂停啊,木ah啊零七啊,然后我们调用一下in特2EH h,让它在这暂停一下,然后呢,我们给他写一个正常退出木S4700H,然后IN21。好,那我们在这个中间环总要点什么呀,要不的话什么是不呀,我们就比如我们可以通过这个字符来打出啊,那通过字符来打印出去之后之外,这这种方式呢,是没有问题的,但是呢,我们这呢,就要介绍一个东西啊,这个叫做ask编码的一个东西。
06:18
我们可以直接通过这个百度来看啊阿码。你可以首先看一下啊,就是我们这个ask克码呢,是这个美国信息交换标准代码啊,然后这个玩意儿呢,其实呢,现在呢,用的也非常多啊,然后但是呢,它以它对应的还有另一套编码,就是佣扣的编码,现我们后续再说我们现在呢,先用这个ask啊ask编码呢,它是有这个一一对应的一个这个表的啊,比如说你这如果是一个这个零,那你这个东西在内存里就是0X30啊,一个16进制的30,那如果是一个一呢,就是一个16进制的31,那比如说我现在啊,我在这循环啊,我在这循环,我给我这个CX,我现在是九,那我正常情况下我的九显示出来啊,显示打印出来,它不是我们的这个正常的九,你看它的九是什么东西呢?它是一个水平制表符啊,这是0S9是个水平制表符,那你想要给它变成你真正想要打印的九怎么办呢?啊,你可以看到它九是什么呢?它的九是390S39,也就是说你在这个循环过程中,你给。
07:23
再加上一个零,它就变成一个可打印可显示的一个字符了。那现在呢,我们来给他这个写一下,比如说我现在呢,这个有嘛,那我现在呢,先给他这个地方一下,比如说我放。的30,然后呢,我现在呢,再把我们的这个东西啊,放到我们的一个计算器里,放到什么计存器呢?啊,我们看一下到S中断,到中断呢,它有一个零二号功能啊,二号功能呢,你可以看到二号功能这个零二呢,是要放到这个ah里的,所以说呢,我们这个功能号ah啊,我们是一个零二。
08:05
啊02H啊,然后呢,我们02H之后呢,我们指定了公众号之后呢,还有指定它输出的字符,你可以看到它显示输出嘛,那输出的字符呢,是放到DL里的,那我们这个DL里它放的实际上就是什么呢?就是一个ask字符,那现在呢,我们就要把这个字符放进去,那我们现在呢,它这个CS本身现在是个九,它要转成这个呢,是加了30之后的,也就是现在在al里,那我所以说呢,我这个放完这个零二之后呢,我现在呢要啊什么呢,这个al啊啊给他一个这个。嗯,我想想啊,不是,哎不是al啊,是DL啊,DL我再放上面吧,我把这个公能号跟它连一起,然后把它放上面啊,把DL里放上al啊,就是我们刚才加出来这个39啊,九加30嘛,39,然后呢,放到DL里,现在D里就是一个字符了啊,就是一个啊这个九的字符阿码,然后呢,把这个零二功能号放在ah里,接着呢,调用这个INT21H啊,然后呢,我们进行这个输出,输出之后呢,如果说啊这个一,这个CS等于九,它就会在这儿啊lo上去,如果它等于零的时候就会往下走啊,现在这个代码应该是没有问题的,我们现在呢,来运行一下测试一下啊。
09:18
复制啊,然后呢,拷贝到我们的虚拟机内。首先mlr k asm啊,然后我们给它这个汇编了啊,你可以看到没有什么问题,那接着呢,我们可以直接运行RK啊,点EE运行,诶你看它是不是就运行出9874562,那这个四五不是那个987654321了,对不对啊,这是不是能看见啊,这个东西呢,就是什么呢?就是我们这个循环啊,循环了这么多次啊,然后把它挨个打印出来了,那么我们现在已经知道了啊,它这个循环是从九打印到一的啊,那我们现在可以进行一个调试啊,简单来看一下它的一个执行流程,首先啊,我们给它啊,Debug e SE啊,我们R,我们首先看一下这一块啊,然后呢,我们U显示一下它的这个返回边,呃,接着呢,我们可以看到,首先呢,它第一行呢,就是目啊这个CS009啊,那首先呢,就是给它这个loop的一个次数做一个限定啊,给到CX里,那我们直接P之后,你可以看到我们C在就有一个九了啊,之后呢,我们再P之后呢,我们可以到我们现在是把这个C。
10:25
现在呢,这个A也就有了,这个有了,你可以看到A现在是九,它实际上这个的个八就是这个九嘛,Al,然后al之后说你直接用这个CS说一个运算的话,一会它下一次循环的时候,你的这个CS的值就变大了啊,它的它的这个循环的次数就变多了,那当前呢,我们用一个中间的一个媒介啊,就是把这个放到A进行这个加减啊,它是不影响CS本身的值的,那你不能影响CS本身的值,在用下一次循环的时候,它就不会受到影响,那么现在呢,我们就来接着看啊,我们现在呢把它呢放到这个DL里,那DL呢,就是我们这个公能号里的这个输出字符啊,现在我们直接PP完之后,你可以看到我们已经啊把我们AR里的一个值,也就是39放到了我们的这个D里啊,你可以看到这个是一个D39。
11:25
接着呢,我们啊目as as一个二,然后呢,你可以看到DA39高位H2啊,然后这个二呢,主要是一个功能号,然后调用21号中啊,然后我们直接一批完之后,你可以看到他在这个底下打了一个九,这个是什么呢?这就是根据它这个al的码,然后打印出的一个字符,那你像是其他的呢,也是一个道理,比如说你想打印一个大写的A,那就是你给他一个0S41,你通过这个二号的一个中,不是二号中断的那个21号中断的一个二号功能号,你就可以把它打印出来啊,这就是它的一个字符的打印方式。
12:02
好,那我们现在呢,已经看到了啊,我们现在是这个IN1,那么此时此刻我们注意C器,因为我们这个调用这个loop了啊,我们现lo到三这个位置了,那么现在那个CS器要变化了啊,我们P一下,P一下之后啊,我们呢就进行了这个。哎呀,我我我直接批了一下,他进行了这个九次循环啊,我不应该P,我应该P啊,啊,那我们Q一下啊。P啊,我们你看之后就成八啊,它就了一啊就了一啊,那我们再一啊现在啊,你看啊我们哎呀我掉我进T了啊,我进算了就这么吧啊就是说明一下啊,它这个循环啊,这个CS值是减的,直到之后它变成零了,它就往下走了啊这个呢,就是什么呢?这就是我们第一个啊第一种调用我们的这个loop啊,原生的这个与循环啊loop指令啊,那如果说啊,这个需要这个什么课件啊,就是我们用的工具啊什么的啊,你可以连系助理啊,加入咱们的这个群啊,在这个评论区啊,可以看到咱们的助理啊发的这个信息,好,然后呢,我们这第一种这个循环讲完之后呢,我们再讲这个第二种啊,第二种循环就是用这个我们的GC指令模拟循环,像是lo这种指令呢,它相当于是一种原生的指令啊,就是它本身就有的指令。
13:29
那么接下来呢,我们就要来讲什么呢?用GCC指令来进行一个它的模拟,模拟跳转,我们上一节课已经说到了,我们可以运用这个GCC来完成一些这个分支的选择,那么现在呢,我们根据这个选择,让它不断的去这个执行,那实呢就形成了一种变相的循环,那比如说我现在呢,就可以这样写啊,我们先把这些东西啊,我们。留一下这个结束的一个东西,剩下都去掉了,那么接着呢,我首先啊,我做一个清理X一下这个BX啊,其实呢,这个哎呀没没讲过这个so啊,我们换种写法啊,这个BX我给他复制个零。
14:08
啊,这种写法啊,我没我忽然想起来我没想过这个SR呢啊先不用,然后我先给他复制个零,复制完零之后啊,那接下来我要干什么呢?我要我要把这个我的这个BX的值我放到这个AX,为什么呢?因为我这是一个正向的循,我想从零一直打到九啊你因为你看我现在是要做加法嘛,然后呢,我个后把这个B去,我为什么要这么做呢?刚才一我现在A,然后30H,因为我要把它转成一个可值可可可观察的一个字符啊。转换成可观察的字符,然后呢,给它加到30之后呢,我们现在呢,就已经变成了这个,因为是零嘛,它现在是30 30之后呢,我们现在呢,因为要二号二号功能啊,所以说呢,要把它的这个值呢放啊,然后把我们这个30呢放在as的啊,把值放D放到DL里之后呢,我们接下来呢,就调用我们的这个二号二号啊,调用我们的这个ah啊,然后呢是零二,然后21号中断啊,这样呢就打印出来了,首先我们在这儿呢,我们只是打印了一次啊,就打印了一个零,它就直接就下去就出去了啊,但是我们这儿可以干嘛呢?我们可以进行一个CP的一个对比啊,我们这儿啊调用一下CMP指令啊,CP指令咱们之前讲过了,它是一种对比指令,它要影响你的这个flag标记位,那现在呢,我用什么的比呢,我用我的BS,我用然后么,然后我GGG如PP。
15:46
之零下边啊,然后呢,现在呢,就是说什么情况呢?就是说比如说我现在啊,从这走走打印到这21号中段打印完啊,然后我进行对比,如果说我的B啊是于十的,那么它就会通过G到,然后续执行,然后呢,如果说它是这个等于十或者说大于的啊,那就直接往下走了啊就是这么一个功能,那我们也就说了啊,我们现在一直跳上去,它一直都是一个零啊,那这怎么行啊对不对啊,那所以说呢,我们在这个执行,我们我个INC INC增可以继续去行上去,然后每次到这之后都会自增,然后再和这个进行对比啊就是这么一,当然你可以把这个呢放到下这个下后再去的话,一定影flag,所以说呢,尽要影响所。
16:46
还有一种方法就是你跳两次啊,这个我们后边的来讲啊,现在呢,我们先不讲两次的问题,我们先来这个测试一下啊,我们把它放到我们的虚拟机。
17:05
对呀,直播。然后呢,我们ML啊,给他这个进行一下汇编。然后我们执行。你可以看到啊,从零到九啊,这没有问题啊,然后我们退出,退出之后呢,我们调用debug啊,来看一下这个首先啊我们R一下,R一下看一下第一行,然后我们U一下啊,看一下它汇编代码,接着呢,我们P首先呢,它第一步啊是给这个move了一下这个asx和BX,因为我刚才已经给这个了,你看B0那么一行的时啊,这个BA实际是零,然后呢,这个A加上十啊,然后转成可视化字符,转成可视化字符之后呢,你可以看到有一个木木什么呢,一个这个D和这个al,它实际上就是把这个al里的三零这个阿码给放到D里,然后呢,我们这有一个啊ah复制一个二的号,然后呢进行一个二一的一个中,然后呢,中断之后,你可以看到这个P底下就打印出一个零了啊,如果说我们这边INC啊,然后你看BX加了一啊,现在BX等于一,接着呢,对比一下我们BX。
18:18
和0A,也就是16进制十,然后呢,对比之后呢,看它这个B和这个AB是不是这个BS比较小,如果BS比较小的情况下呢,调用D个G这个我们码移后呢,进行这个以看到它又个003这个位置上,然后继续下一循环,然后根据刚才的循环条件,我们再经过一次特一,然后再加一次BS之后,你可以看到它现在这个BS等于二,直到什么时候啊,它对比的时候,我们这个BX等于十了啊,那就它就会往下走,而不会被这个GB给跳走,然后呢就循环结束了,这个呢就是它的循环条件。
19:02
啊对啊,如果说有这个资料领取需求的,可以联系一下咱们评论区助理啊,然后我就接着说了啊,这个呢,就是咱们的第二种啊,第二种方式啊,就通过我们这种方式啊,来这个写的这个循环啊,那这种循环呢,相当于什么呢?相当于咱们高级语言啊,高级言C语言里边的这个for循环的,呃,应该说for循环的release模式编译啊,就是默认的一个release模式编译,基本上它它的这个执行流程就是这样的,就是for循环的release编译出来啊,它的汇编就是这样的啊,当然了,它是那个32位或64位的啊,通常情况下它不会调中断来打印啊,通常情况下它是在咱们讲32位之后,也会大家带大家啊去调用一些库函数来进行打印啊,那些更为方便中断这个东西,我们实际上现在呢,也也用不到了啊,但是呢,我们因为要讲这个基础的一些原理,所以说呢,大家还是要看一看,然后呢,我们这个讲完这个for的这种形式之后呢,我们for呢,其实还有一种形式呢,就是什么呢?For循环。
20:03
是他一个C语言,你用这个debug模式啊,它默认的情况下,它其实是类似于这样的形式,我给大家看一下啊。我们还是留一个这个退出啊,剩下的呢都删掉,然后呢,我首先还是木BX给他一个零,然后呢,啥也不干,我直接开始跳转啊跳转为啥要跳转呢?我现在呢,比如说我这跳了一个LP1,那我这个LP1在这有一个标号,那我这个LP1我这个跳。啊,INC完BS之后我对比啊,这个西安PBX10。对比完这个CRP10之后啊,如果说啊,我们是这个BS等于或者大于十了,我就直接一个接啊,然后RP啊就我就退了,那我这个LP呢,肯定就是LP1下边了呗,我就就或者说叫LP2也行了,随便啊,然后呢,我直接就退出去了,否则呢,它就继续往中间执行,那中间执行什么东西呢?中间肯定就是执行一些我们比如说move啊这个asbs,然后呢,给他A一下这个AS30啊,然后就转换成字符的这么一个过程。
21:26
但是这儿呢,还有一个问题,就是你当现在啊,从上边过来执行啊,执行完之后,你这占直接占到这儿了,然后执行,执行完之后啊,你现在没有办法跳回去啊,没有办法跳回去,所以呢,你要在这个打印完之后,加一个无条件跳转啊P,然后跳回去,它跳到哪呢?跳到我们后边。啊,否则他不就直接又跳走了嘛,所以说你要放的后边,所以他现在的流程是什么样的呢?首先给E给BS个零,然后到这个LP1的位置上,然后呢,进行一个正常的打印,打转成阿阿字符之后打印出去,打完之后呢,我们在这无条件的跳转,跳转到我们这边,然后呢,进行一个B索引的一个自增,因为这个BS相当于一个啊一个索引,然后进行自增,自增之后对比这个索引和到底谁大,如果说这个B啊没有这个啊大于十,那就往下走,如果大于十了,或者等于十了,直接跳到LP,也就是退出这边来退出,所以说呢,它的循环条件呢,就是BX啊要小于啊小于十,那这种情况下呢,也就是说它会便利多少次呢?会便利十次,因为呢,零啊一二三四五六七八九十啊,那么多啊。
22:42
好啊,0123456789啊,14啊没有十啊,就是这么一个循环的一个流程啊,然后呢,我来给他这个复制一下。放到我们的虚拟机里。然后我们还是ML啊,然后RK啊as么给它标汇编,汇编之后我们调用R k.EE啊,你看啊,它就打印出来了,0123456789啊,他呢跟刚才呢啊,其实呢,没有什么太多的这个本质上的一个区别啊,但是呢,有一些细节上的区别,比如说我们刚才那个,哎呀显示出来了啊那个比如说我们刚才那些东西啊,就是我们使用的方式啊,跟现在不一样,我们刚才呢是首先给这个BS,然后呢使用这个先然后的形式,现在是什么呢?现在是我直接转后呢,执行完之后接这个再跳回来啊这么来执行啊,这种方式呢,就比较接近于什么呢?比较接近于我们的这个,呃,For循环的debug编译模式啊for循环的debug编译模式,然后呢,我们还有其他的这种方式啊,那比如说我们还有这个,正常情况下,大家如果学过高级语源,应该是还有循环那。
24:00
循环的形式也是一种啊,但是while循环其实还有什么呢?Well和do well,但是咱们do well呢,跟咱们这些东西呢,比较接近啊,我们咱们就不单独说了,它那个玩意儿,只是说先无条件执行一次啊,所以说呢,对咱们没有什么帮助,咱们来看一下他的这个while循环的这种形式啊。呃,外循环这种形式呢,其实也跟刚才那个比较接近啊,我这儿呢,我也也是留一个最后吧,然后给他进行一个。哎,算了,我从上面开始写,然后粘一些吧,首先啊木一个啊BX啊,给他一个零啊,还这还是索引,然后呢,我这里呢,我给他对比啊,对比CMP啊CMMP一个BX啊,一个十啊,看它是不是这个大于等于十,然后呢,我直接一个GZ啊,然后L就要跳转出,那如果说我们这跳出,那么我们什么呢?中间很明显我们还是干这套,我们还是要进行一个打印。
25:02
啊,然后呢,后边呢是跳转退出。剩下的我们删掉好,那这样的逻辑就完整了吗?没有完整,因为它现在呢,实际上类似于一种选择结构啊,它并没有进行循环,为什么有进行循环呢?因为我们打印之后啊,我们的索引没有变化,没有变化,我们如果想要形成循环判断这种东西,那你首先你这个索引要有变化啊,要不然就是死循环,要么就循环不起来,所以说呢,现在呢,我们需要进行一个INC,一个BX,就是给它的这个索引进行自增,自增之后呢,我们调用一个GP进行一个无条件跳转,跳去哪呢?跳去我们对比之前啊,对比之前为什么要跳之呢?因为我们在这个位上对B的索引啊进行了一个自增,所以说呢,我现在自增之后要跳到上边来啊,跳到上面来,它就会重被这个负零,要跳到这个其他地方呢,比如到这儿它就直接跳下去了,那你只有调这个位置上,它才会根据你的这个节新增完的啊,比如说我现在是零下来的,那我现在自增完INC之后呢,我变成一了啊一和这个十进行对比,然后再决定啊,我这个BS是不是。
26:09
或者大于十了,然后一退出,那如果没有的情况下呢,就继续执行,然后再跳上去,然后再对比啊,再增啊这么一回事,那现在呢,我们来啊给他看一下。MLRK啊,点asm啊,然后呢,我们R k.ESE运行一下,你可以看到还是0123456789啊,然后呢,我们也可以来简单的再debug一下啊艾一下R k.exe好,我们直接R看一下它第一行啊,它给一个BX一个零赋值,没有问题,我们直接U一下,U完之后我们PP完之后你可以看到它的BX现在是零,然后呢,他直接就要对比BX和十啊是谁大,然后呢我们再PP完之后你可以看到啊在这啊G啊,如果说啊,它是这个,如果说B是等于十或者大于十的,那么这个G会直接跳到16这个位置上,那16这个位置是什么?你可以看到16这个位置是啊,Move了一个ah,一个零七,也就是说呢,它这个调用个零七,一个in特一,它就在这接收一个字符,然后底下呢,就等着退出了,那这个情况下呢,就是判断它就已经这个大于了啊,那我们如果要符合条件呢,它会往下走,就像现在一样,把这个B给到AX,然后加30,加完30之后呢。
27:32
再给他DL之后呢,给一个二号,然后用二一,然后你看这有一个零之后呢,对BS进行一个自增,现在是BS0,然后BS现在就变成接了呢,偏又行和这个A,那到这么加加加加加加啊等B等于时,这个程就结束了,然后呢就会跳呢,就会跳我们刚才那个。
28:04
我看一下啊,刚才这个位置上啊,跳到16这个位置上,然后进行一个退出。好啊,那有没有什么问题啊,有没有什么问题啊,我们今天的这个技术部分啊,基本上就结束了啊,有什么问题咱们回答一下,没有问题呢,咱们就换人回来。但是都听懂了没有问题啊,那我把那个录播先关一下。的。
我来说两句