zoukankan      html  css  js  c++  java
  • 系统中断流程 寻址方式 寄存器与触发器的关系 微处理器 用一个或多个中断号来对应所有的系统调用

    https://www.kancloud.cn/wintry/python3/742474

    微机性能指标:

    1)CPU类型:CPU型号决定了微机系统的档次
    2)字长:CPU一次可以同时传送和处理的数码的位数
    直接关系到计算机的计算精度、寻址速度和处理能力
    字长越长,表示一次处理范围越大,性能越好
    3)主频:计算机的时钟频率。
    CPU单位时间内(秒)发出的脉冲数,吉赫(GHz);主频越高运算越快
    4)内存容量:内存储器可容纳的二进制信息总量。
    以字节B(Byte)表示,8位二进制为1字节,1024B=1KB.
    

    微型计算机的组成:

    微型计算机是由大规模集成电路组成,体积较小的电子计算机。
    微机包括硬件系统和软件系统;
    硬件系统是组成微机的各种物理设备包括主机和外设。
    主机以微处理器为基础,配以存储器及I/O设备。

    计算机硬件5个基本组成部分:运算器、控制器、存储器、输入设备、输出设备
    微处理器:一片或几片大规模集成电路组成的,具有运算和控制功能的中央处理单元。主要由算数逻辑部件ALU、寄存器和控制器CU组成。
    现代计算机能实现自动化的信息处理,是由于采用了冯.诺依曼“存储程序”
    工作原理。
    主板是计算机各种部件相互连接的纽带和桥梁。
    寄存器与触发器的关系:

    由于一个触发器能够存储一位二进制码,所以把n个触发器的时钟端口连接起来就能构成一个存储n位二进制码的寄存器。

    总线:

    bus 是计算机系统各部件之间相互连接,传送信息的公共通道,由一组物理导线组成。
    一次传输信息的位数称为总线的宽度。

    按照传送信息类型可以分为:数据总线,地址总线和控制总线

    总线一共分为三大类:

    片内总线:芯片内部各部件之间的数据传输,例如CPU内控制器、运算器和各个寄存器之间的信息传输

    系统总线:CPU和主存、CPU和接口之间的信息传输。
    数据总线:(Data Bus)为双向线,用于实现在CPU、存储器、I/O接口之间的数据传送;
    数据总线的宽度等于计算机的字长
    地址总线:(Address)为单向线,用于传送CPU所要访问的存储单元和I/O端口的地址信息。地址总线的位数决定了系统所能直接访的问存储空间的容量。

    控制总线:(Control Bus)为双向线,用于控制总线上的操作和数据传送的方向;实现微处理器与外部逻辑部件之间的同步操作。
    外部总线:
    连接外部设备,如SCSI,IDE,USB(属于串口)

    机器数的表示与编码
    1.原码表示法:

    最高位表示符号,"0正,1负",其它n位表示数值的绝对值-0=1 0000000
    例如:
    设机器字长为8位,求X1=0.1011B,X2=-0.1011B的原码表示
    [x1]=0 1011000        [X2]=1 1011000
    设机器字长为8位,求X3=1011B,X4=-1011B的原码表示
    [X3]=0 0001011       [X4]=1 0001011
    

    2.反码表示法:

    正数的反码与其原码相同,负数的反码是对其原码符号位不变其它位取反。
    -0的反码=1 1111111
    

    3.补码表示法:

    正数的补码与原码相同,负数的补码,由其原码符号位不变,其它位取反,末尾位加1求得。
    在计算机系统中,存储有符号整数时,用该整数的补码进行存储,0的原码、补码都是0。
    

    4.移码表示法:

    [X补]求[X移]的规则:数值位不变,符号位取反
    浮点数的阶码部分一般采用整数形式的移码表示。
    0的移码对0的补码取反=1 0000000
    

    机器数的运算

    1.算数运算

    补码运算的公式:
    [X补]+[Y补]=[X+Y补]
    [X补-Y补]=[X补]+[-Y补]
    [Y补]-->[-Y补]:包含符号位,各位取反,末尾加1
    

    2.溢出的概念

    两正数相加,变负数,上溢(大于机器所能表示的最大数)
    两负数相加,变正数,下溢(小于机器所能表示的最小数)
    

    微型计算机的工作过程
    微型计算机的五大部分相互配合,协同工作。根据冯.诺依曼的设计,计算机应能自动执行程序,执行程序又归结为逐条执行指令,分为以下五个步骤:

    1.取指令:从存储器某个地址单元中取出要执行的指令送到指令寄存器暂存
    2.分析指令:把保存在指令寄存器中的指令送到指令译码器中,译出该指令对应的微操作信号,控制各个部件的操作
    3.取操作数:如果需要,发出取数据命令,到存储器取出需要的操作数
    4.执行指令:根据指令译码,向各个部件发出相应控制信号,完成指令规定的各种操作
    5.保存结果:如果需要保存计算结果,则把结果保存到指定的存储器单元中。
      完成一条指令所需要的时间称为指令周期。
      一个指令周期往往包含多个总线周期,一个总线周期又包含多个时钟周期,时钟周期是计算机中最小的时间单位。
    

    冯.诺依曼计算机的基本设计思想

    采用存储程序的方式,编制好的程序和数据存放在同一存储器中,
    计算机可以在无人干预的情况下自动完成逐条取出指令和执行指令的任务;
    在机器内部,指令和数据均以二进制码表示,指令在存储器中按执行顺序存放

    "存储程序控制"的概念

    程序输入到计算机中,存储在内存储器中(存储原理),在运行时,控制器按地址顺序取出存放在内存储器中的指令(按地址顺序访问指令),然后分析指令,执行指令的功能,遇到转移指令时,则转移到转移地址,再按地址顺序访问指令(程序控制)。

    https://www.kancloud.cn/wintry/python3/742476

    十六位微处理器

     

    8088/8086微处理器功能结构
    1.总线接口部件(BIU)
    (1)功能

    从内存取指令送到指令队列CPU执行指令时,
    总线接口部件要配合执行部件为指定的内存单元或者外设端口收发数据
    

    (2)组成

    4个段地址寄存器,即:
    CS,16位代码段寄存器
    DS,16位数据段寄存器
    ES,16位附加段寄存器
    SS,16位堆栈段寄存器
    16位指令指针寄存器
    20位地址加法寄存器
    4/6字节的指令队列缓冲器
    

    (3)BIU指令队列和20位地址加法器作用

    指令队列,指令一个一个预先排队等候传唤,称为流水线技术
    减少了CPU取指令等待的时间,提高了CPU的效率
    
    加法寄存器用来产生20位地址
    8086可用20位地址寻址1MB内存空间
    但8086内部所有的寄存器都是16位的,
    所以需要一个附加机构来根据16位寄存器提供的信息计算出20位的物理地址
    这个机构就是20位的地址加法器
    

    2.执行部件(EU)
    1.功能

    从指令队列中取出指令
    对指令进行译码
    发出相应的传送数据或算数运算的控制信号
    接收由总线接口部件传来的数据,或把数据传送到总线接口部件
    进行算数运算
    

    2.组成

    AX,BX,CX,DX--既可作为16位寄存器也可作为8位寄存器,
    分别为AH、BH、CH、DH、AL、BL、CL、DL
    
    AX又称为累加器,8086指令系统许多指令都通过累加器动作来执行
    AH为16位累加器,AL为8位累加器
    

    (2)四个专用寄存器

    基址指针寄存器BP
    堆栈指针寄存器SP
    源变址寄存器SI
    目的变址寄存器DI
    

    (3)算数逻辑单元ALU
    它是16位运算器,可用于8位或16位二进制算数和逻辑运算,也可按指令的寻址方式计算寻址寄存器所需的16位偏移量。
    (4)数据暂存运算器
    协助ALU完成运算,暂存参加运算的数据
    (5)EU控制电路。

    从指令队列取出指令操作码
    通过电路译码,发出相应控制命令
    控制ALU的数据的流向。
    
    如果是运算操作,操作数经过暂存寄存器送入ALU
    运算结果经过ALU数据总线送到相应寄存器,
    同时标志寄存器PSW根据运算结果改变状态
    

    (6)标志寄存器

    标志寄存器共有16位其中7位未用。
    其中6个标志位反应CPU指令运行后的运行状态信息
    SF、ZF、PF、CF、AF、OF这些标志位,
    用于根据指令执行后的操作结果进行判断转移。
    3个控制标志:DF、IF、TF
    程序员可通过指令设置控制标志,有专门的标志对控制标志置0或置1
    

    寄存器结构
    1.通用数据寄存器

    ABCD-X、16位可用作8位寄存器,分高低位,
    AX作为累加器
    BX作为基址寄存器
    CX作为计数寄存器
    DX作为数据寄存器
    

    2.指针变址寄存器

    分为两个指针寄存器SP(stack pointer)、BP(base pointer)
    和两个变址寄存器SI(source index)、DI(destination index)
    这组寄存器通常用来存放存储单元的16位偏移地址
    偏移地址:相对起始地址的距离
    

    (1)指针寄存器

    SP用来指示栈顶的偏移地址
    BP存放位于堆栈段中一个数据区的"基址"的偏移量
    

    (2)变址寄存器

    SI存放源操作数地址的偏移量
    DI存放目标操作数地址的偏移量
    

    3.段寄存器(segment registers)

    CS、DS、SS、ES;代码段、数据段、堆栈段、附加段
    这些寄存器指明了一个特定的现行段,用来存放各段的段基址
    

    4.指令指针

    IP(instruction pointer)为16位指令指针,
    ip的内容总是只想BIU将要取的下一条指令代码的16位偏移地址。
    

    8086指令队列的作用

    在执行指令的同时从内存中取了一条指令或下几条指令,取来的指令放在指令队列中这样它就不需要象以往的计算机那样让CPU轮番进行取指和执行的工作,从而提高CPU的利用率。

    8086/8088CPU有哪几个状态标志位,有哪几个控制标志位?其意义各是什么?

    状态标志位有6个:ZF、SF、CF、OF、AF、PF。
    其意思是用来反映指令执行的特征,通常是由CPU根据指令执行结果自动设置的;
    控制标志位有3个:DF、IF、TF。
    它是由程序通过执行特定的指令来设置的,以控制指令的操作方式。

    8086/8088微处理器内部有哪些寄存器,他们的主要作用是什么?

    执行部件有8个16位寄存器,AX、BX、CX、DX、SP、BP、DI、SI,
    AX、BX、CX、DX一般作为通用数据寄存器。
    SP为堆栈指针存器
    BP、DI、SI在间接寻址时作为地址寄存器或变址寄存器。
    总线接口部件设有段寄存器CS、DS、SS、ES和指令指针寄存器IP。
    段寄存器存放段地址,与偏移地址共同形成存储器的物理地址。
    IP的内容为下一条将要执行指令的偏移地址,与CS共同形成下一条指令的物理地址。

    INTR、INTA、NMI、ALE、HOLD、HLDA引脚的名称

    INTR 可屏蔽请求信号
    INTA 中断请求信号
    NMI 可屏蔽中断请求信号
    ALE 地址锁存允许信号
    HOLD 总线请求信号
    HLDA 总线请求响应信号

    什么是中断?什么是中断向量?中断向量表的地址范围?

    中断就是CPU在执行当前程序时由于内外部事件引起CPU暂时停止当前正在执行的程序而转向执行请求CPU暂时停止的内外部事件的服务程序,该程序处理完后又返回继续执行被停止的程序;中断向量是中断处理子程序的入口地址;地址范围是00000H-003FFH。

    中断向量表的功能是什么?若中断向量号分为1AH和20H,则他们的中断向量在中断向量表的什么位置上?

    中断向量表的功能是当中断源发出中断请求时,即可查找该表,找出其中断向量,就可转入相应的中断服务子程序。1AH在中断向量表的位置是1AH×4=68H在中断向量表0000H:0068H处;20H在中断向量表的位置是80H在中断向量表0000H:0080H处。

    通常解决中断优先级的方法有哪几种?

    3种
    软件查询确定优先级
    硬件优先级排队电路确定优先级
    中断屏蔽接口电路
    

    CPU响应可屏蔽中断的条件是什么?

    (1)CPU必须处于开中断状态IF=1
    (2)CPU现行指令执行结束
    (3)没有其他优先级高的中断请求。
    (没有内部中断,没有非屏蔽中断,没有总线请求)

    以可屏蔽中断为例,说明一次完整的中断过程主要包括哪些环节?

    中断请求:外设通过硬件信号的形式、向处理器引脚发送有效请求信号。
    中断响应:在满足一定条件时,处理器进入中断响应总线周期。
    关中断:处理器在响应中断后会自动关闭中断。
    断点保护:处理器在响应中断后将自动保护断点地址。
    中断源识别:处理器识别出当前究竟是哪个中断源提出了请求,
    并明确与之相应的中断服务程序所在主存位置。
    现场保护:对处理器执行程序有影响的工作环境(主要是寄存器)进行保护。
    中断服务:处理器执行相应的中断服务程序,进行数据传送等处理工作。
    恢复现场:完成中断服务后,恢复处理器原来的工作环境。
    开中断:处理器允许新的可屏蔽中断。
    中断返回:处理器执行中断返回指令,程序返回断点继续执行原来的程序。

    在中断响应过程中,8086往8259A发的两个INTA信号分别起什么作用?

    在中断响应过程中,CPU向8259A的INTR引脚发2个负脉冲。
    作用:
    第一个负脉冲通知8259A ,CPU允许中断请求,要求送中断类型;
    第二个负脉冲,8259传输中断类型码。

    https://www.kancloud.cn/wintry/python3/742477

    8086指令系统_寻址

     

    汇编语言指令由操作码和操作数两部分组成。

    操作码说明指令的功能,即计算机要执行的具体操作
    如:传送、移位、运算等,是指令中不可缺少的组成部分
    操作数是指令执行的参与者,即各种操作的对象。
    有些指令不需要操作数,有些指令有一个或两个操作数。
    有一个操作数的叫单操作数,有两个操作数的叫双操作数。

    操作码   目的操作数,源操作数
    MOV EAX,00401000
    

    要指令执行,就要找到指令中的操作数,
    要找到操作数,就要找到存放操作数的地址,
    寻找指令中的操作数地址的方式叫做寻址方式;

    全七类寻址方式:

    1.立即寻址
    操作数以字节形式紧跟在操作码后边
    常用于给CPU中的寄存器或存储单元赋值
    立即数只能用作源操作数,不能作为目的操作数。

    例子:

    MOV AL,56H        将立即数56H,送入8位寄存器AL
    MOV AX,1234H    将16位立即数1234H,送16位寄存器AX
    

    2.寄存器寻址
    操作数存放在CPU的寄存器中,寄存器可以是16位也可以是8位
    不用执行寻找操作数的总线周期,执行速度最快。
    MOV AX,BX

    3.存储器寻址
    操作数放在存储器中,除代码段之外的所有段数据。
    这种存储方式中,指令给出的是存放该操作数的存储单元的地址
    或产生该存储单元地址的表达试。

    CPU执行指令时,首先根据操作数字段提供的地址信息,由
    执行单元EU计算出有效地址EA,再由总线接口单元BIU
    根据物理地址公式"PA=段首地址X10H+有效地址"计算出物理地址
    然后到物理地址对应的内存单元取出操作数,执行对该数的操作

    存储器寻址根据计算偏移地址的方法不同分为以下5种
    (1)直接寻址
    这种寻址方式是从存储器中寻找操作数最简单的一种,
    指令中直接给出的是该操作数在存储器中的有效地址;其物理地址为:
    PA=段首地址X10H+EA(段首地址默认使用DS段寄存器,EA为指令中给出的有效地址)

    例子:
    MOV AX,[2000H]

    若操作数不在数据段,则应在指令中使用段跨越前缀,指明使用的数据在哪一个段
    例如:
    MOV AX,ES:[2000H]
    该指令将物理地址为PA=(ES)X10H+2000H单元的值送AX

    (2)寄存器间接寻址
    操作数的有效地址由指令中指定的寄存器BX,BP,SI或DI的内容指定。
    可分为下面两种情况

    ①SI,DI或BX寄存器间接寻址,通常操作数实在数据段DS中,因此,
    他们的物理地址是PA=(DS)X10H+EA

    例:
    MOV AX,[BX]
    设(DS)=2000H,(BX)=1000H,则该操作数的物理地址为:
    PA=2000HX10H+1000H=21000H
    这条指令的执行结果是把内存单元21000H中的数据送到AX寄存器中

    ②若是寄存器间接寻址,则该操作数在堆栈段SS中,即以堆栈段寄存器SS
    与BP组合形成操作数的物理地址:PA=(SS)X10H+(BP)

    例:
    MOV BX,[BP]
    设(SS)=1000H,(BP)=1500H,则PA=1000Hx10H+1500H=11500H
    该操作数把11500H存储单元的内容送到BX寄存器

    (3)寄存器相对寻址
    这种寻址方式的操作数存放在存储器中的内存单元中,
    是以基址寄存器(BX或BP)或变址寄存器(DI或SI)的内容为基地址
    然后在这个地址上加上8位或16位的位移量Disp,形成真正操作数的有效地址EA

    当寄存器为BX、SI、DI时,用段寄存器DS的内容作为段基地址,则物理地址:
    PA=(DS)X10H+(BX)/(SI)/(DI)+Disp8/Disp16

    若寄存器为BP,则段寄存器SS的内容作为段首地址,则物理地址为:
    PA=(SS)X10H+(BP)+Disp8/Disp16

    例:
    MOV DI,[BX+2]

    (4)基址变址寻址
    操作数存放在内存单元中,其偏移地址是基址寄存器的内容加上变址寄存器的内容之和。

    若基址寄存器为BX,则段寄存器为DS;
    若基址寄存器为BP,则段寄存器为SS;

    则操作数物理地址为:

    PA=(DS)X10H+(BX)+(SI)/(DI) 
    或
    PA=(SS)X10H+(BP)+(SI)/(DI)
    
    MOV DX,[BP][SI]
    

    (5)相对基址变址寻址
    操作数存放在内存单元中,其中有效地址由指令指定的基址寄存器加变址寄存器的内容在加上指令中的8位或16位偏移量Disp得到,

    其中物理地址为:

    PA=(DS)X10H+(BX)+(SI)/(DI)+Disp 
    或
    PA=(SS)X10H+(BP)+(SI)/(DI)+Disp
    

    例:

    MOV AX,MAS[BX][SI]      ;MAS为符号地址
    MOV DX,5[BX][DI]            ;将偏移地址为5+(BX)+(DI)所指的单元的值送D



    https://www.kancloud.cn/wintry/python3/742484

    标志寄存器

     

    6个状态标志位的功能分别叙述如下:

    CF(Carry Flag)——进位标志位。

    当执行一个加法(或减法)运算,使最高位产生进位(或借位)时
    CF为1,则为0。
    

    PF(Parity Flag)——奇偶标志位。

    该标志位反映运算结果中1的个数是偶数还是奇数。
    当指令执行结果的低8位中含有偶数个1时
    PF=1;否则PF=0。
    

    AF(Auxiliary carry Flag)——辅助进位标志位。

    当执行一个加法(或减法)运算,使结果的低4位向高4位有进位(或借位)时,
    AF=1;否则AF=0。
    

    ZF(Zero Flag)——零标志位。
    若当前的运算结果为零,ZF=1;否则ZF=0。

    SF(Sign Flag)——符号标志位。
    它和运算结果的最高位相同。

    OF(Overflow Flag)——溢出标志位。
    当补码运算有溢出时,OF=1;否则OF=0。


    3个控制标志位用来控制CPU的操作,由指令进行置位和复位。

    DF(Direction Flag)——方向标志位。

    它用以指定字符串处理时的方向,
    当该位置“1”时,字符串以递减顺序处理,即地址以从高到低顺序递减。
    反之,则以递增顺序处理。
    

    IF(Interrupt enable Flag)——中断允许标志位。

    它用来控制8086是否允许接收外部中断请求。
    若IF=1,8086能响应外部中断,反之则不响应外部中断。
    注意:IF的状态不影响非屏蔽中断请求(NMI)和CPU内部中断请求
    

    TF(Trap Flag)——跟踪标志位。

    它是为调试程序而设定的陷阱控制位。
    当该位置“1”时,8086 CPU处于单步状态,
    此时CPU每执行完一条指令就自动产生一次内部中断。
    当该位复位后,CPU恢复正常工作。

     https://my.oschina.net/clownfish/blog/142328

    8086汇编中的标识寄存器叫flag。16位每一位都标识不一样的含义,

    15 14 13 12 11(OF) 10(DF) 9(IF) 8(TF) 7(SF) 6(ZF) 5 4(AF) 3 2(PF) 1 0(CF)

    以上flag寄存器中各个位数表示的情况。在8086cpu中只用到了0,2,4,6,7,8,9,10,11这9个位数,其他的位数没有任何意义。

    CF Carry Flag ,进位标志位 在进行无符号运算的情况下,它记录了运算结果的最高位有效位像更高位的进位值,或从更高位的借位值 CY(carry yes 进位) NC(No carry 未进位)
    PF Parity Flag    奇偶标志位 相关指令执行后,其结果所在bit位中1的个数是奇数或偶数,如果1个个数为偶数,则pf=1,为基数则pf=0 PE(parity even 偶) PO(parity odd 奇数)
    AF Auxiliary Flag 辅助进位   AC(assistant carry进位) NA(no assistant carry 无进位)
    ZF Zero Flag 零标志位 相关指令执行后,其结果是否为零,如果结果为零则zf=1 如果结果不为零则zf=0 ZF(zero等于零) NZ(no  zero不等于零)
    SF Sign Flag 符号标识位 相关指令执行后,其结果是否为负,如果为负,则sf=1如果不为负数 则sf=0 NG(negative)负 PL(plus 正)
    TF Trap Flag 追踪标志 当追踪标志TF被置为1时,CPU进入单步执行方式,即每执行一条指令,产生一个单步中断请求。这种方式主要用于程序的调试。指令系统中没有专门的指令来改变标志位TF的值,但程序员可用其它办法来改变其值。    
    IF Interrupt Flag  中断标志位   EI(enable interrupt许可) DI(disable interrupt 禁止)
    DF Direction Flag  方向标志位   DN(Down减少) UP(UP增加)
    OF Overflow Flag 溢出标志位 在进行有符号数运算的情况下,运算结果是否溢出,如果发生溢出,则of=1,未发生溢出 of=0 OV(overflow溢出) NV(no overflow未溢出)
    指令 含义 检测的相关标识位
    je 等于则转移(equal) zf=1
    jne 不等于则转移(not equal) zf=0
    jb 低于则转移(below) cf=1
    jnb 不低于则转移(not below) cf=0
    ja 高于则转移(above ) cf=0 && zf=0
    jna 不高于则转移(not above) cf=1 && zf=1

     

    汇编语言, 即第二代计算机语言,用一些容易理解和记忆的字母,单词来代替一个特定的指令,比如:用“ADD”代表数字逻辑上的加减,“ MOV”代表数据传递等等,通过这种方法,人们很容易去阅读已经完成的程序或者理解程序正在执行的功能,对现有程序的bug修复以及运营维护都变得更加简单方便。当计算机的硬件不认识字母符号,这时候就需要一个专门的程序把这些字符变成计算机能够识别的二进制数。因为汇编语言只是将机器语言做了简单编译,所以并没有根本上解决机器语言的特定性,所以汇编语言和机器自身的编程环境息息相关,推广和移植很难,但是还是保持了机器语言优秀的执行效率,因为他的可阅读性和简便性,汇编语言到现在依然是常用的编程语言之一。 [2]  汇编语言不像其他大多数的程序设计语言一样被广泛用于程序设计。在今天的实际应用中,它通常被应用在底层,硬件操作和高要求的程序优化的场合。驱动程序、嵌入式操作系统和实时运行程序都需要汇编语言。 [1] 

    https://baike.baidu.com/item/汇编语言/61826

    机器语言

    计算机的硬件作为一种电路元件,它的输出和输入只能是有电或者没电,也就是所说的高电平和低电平,所以计算机传递的数据是由“0” 和“1”组成的二进制数,所以说二进制的语言是计算机语言的本质。计算机发明之初,人们为了去控制计算机完成自己的任务或者项目,只能去编写“0”、“ 1”这样的二进制数字串去控制电脑,其实就是控制计算机硬件的高低电平或通路开路,这种语言就是机器语言。直观上看,机器语言十分晦涩难懂,其中的含义往往要通过查表或者手册才能理解, 使用的时候非常痛苦,尤其当你需要修改已经完成的程序时,这种看起来无序的机器语言会让你无从下手,也很难找到程序的错误。而且,不同计算机的运行环境不同,指令方式操作方式也不尽相同,所以当你在这种机器语言就有了特定性,只能在特定的计算机上执行,而一旦换了机器就需要重新编程,这极大的降低了程序的使用和推广效率。但由于机器语言具有特定性,完美适配特定型号的计算机,故而运行效率远远高过其他语言。机器语言,也就是第一代编程语言。 [2] 
       

    汇编语言

    不难看出机器语言作为一种编程语言, 灵活性较差可阅读性也很差,为了减轻机器语言带给软件工程师的不适应,人们对机器语言进行了升级和改进:用一些容易理解和记忆的字母,单词来代替一个特定的指令。通过这种方法,人们很容易去阅读 已经完成的程序或者理解程序正在执行的功能,对现有程序的bug修复以及运营维护都变得更加简单方便,这种语言就是我们所说的汇编语言, 即第二代计算机语言。 [2] 
    比起机器语言,汇编语言具有更高的机器相关性,更加便于记忆和书写,但又同时保留了机器语言高速度和高效率的特点。汇编语言仍是面向机器的语言,很难从其代码上理解程序设计意图,设计出来的程序不易被移植,故不像其他大多数的高级计算机语言一样被广泛应用。所以在高级语言高度发展的今天,它通常被用在底层,通常是程序优化或硬件操作的场合。 [3] 
       

    高级语言

    在编程语言经历了机器语言,汇编语言等更新之后,人们发现了限制程序推广的关键因素——程序的可移植性。需要设计一个能够不依赖于计算机硬件,能够在不同机器上运行的程序。这样可以免去很多编程的重复过程,提高效率,同时这种语言又要接近于数学语言或人的自然语言。在计算机还很稀缺的50年代,诞生了第一个高级编程语言。当时计算机的造价不菲,但是每天的计算量有有限,如何有效的利用计算机有限的计算能力成为了当时人们面对的问题。同时,因为资源的稀缺, 计算机的运行效率也成为了那个年代工程师追寻的目标。为了更高效的使用计算机,人们设计出了高级编程语言,来满足人们对于高效简的编程语言的追求。 [2] 
     

    语言组成

    由于汇编指令系统庞大,因而需构建指令系统体系,其指令数量庞大,格式复杂,可记忆性差等。指令中最难的是指令所支持的寻址方式,其实质就是指令中操作数如何获取。对于处理器而言,就是如何找到他所需的数据。但对于计算机底层的汇编语言而言,这种寻址方式将涉及大量的计算存储格式,与 复杂的存储管理方式紧密相关,因而难以理解。最后,汇编指令还关系到如何影响标志位,但处理器标志位非常复杂,因而对其机制掌握就比较困难。 [4] 
       

    传送指令

    包括通用数据传送指令MOV、条件传送指令CMOVcc、堆栈操作指令PUSH/PUSHA/PUSHAD/POP/POPA/POPAD、交换指令XCHG/XLAT/BSWAP、地址或段描述符选择子传送指令LEA/LDS/LES/LFS/LGS/LSS等。 [1]  
       

    逻辑运算

    这部分指令用于执行算术和逻辑运算,包括加法指令ADD/ADC、减法指令SUB/SBB、加一指令INC、减一指令DEC、比较操作指令CMP、乘法指令MUL/IMUL、除法指令DIV/IDIV、符号扩展指令CBW/CWDE/CDQE、十进制调整指令DAA/DAS/AAA/AAS、逻辑运算指令NOT/AND/OR/XOR/TEST等。 [1]  
       

    移位指令

    这部分指令用于将寄存器或内存操作数移动指定的次数。包括逻辑左移指令SHL、逻辑右移指令SHR、算术左移指令SAL、算术右移指令SAR、循环左移指令ROL、循环右移指令ROR等。 [1]  
       

    位操作

    这部分指令包括位测试指令BT、位测试并置位指令BTS、位测试并复位指令BTR、位测试并取反指令BTC、位向前扫描指令BSF、位向后扫描指令BSR等。 [1]  
       

    控制转移

    这部分包括无条件转移指令JMP、条件转移指令Jcc/JCXZ、循环指令LOOP/LOOPE/LOOPNE、过程调用指令CALL、子过程返回指令RET、中断指令INTn、INT3、INTOIRET等。 [1]  
       

    串操作

    这部分指令用于对数据串进行操作,包括串传送指令MOVS、串比较指令CMPS、串扫描指令SCANS、串加载指令LODS、串保存指令STOS,这些指令可以有选择地使用REP/REPE/REPZ/REPNE和REPNZ的前缀以连续操作。 [1]  
       

    输入输出

    这部分指令用于同外围设备交换数据,包括端口输入指令IN/INS、端口输出指令OUT/OUTS。 [1] 
     

    https://www.kancloud.cn/wintry/python3/742485

    常用汇编指令

     

    汇编语言指令大致分为以下几类

    一、传送类指令
    二、算数运算类指令
    三、位操作指令
    四、串操作指令
    五、控制转移类指令
    六、处理器控制类指令
    七、汇编指令伪指令


    一、传送类指令
    1.数据传送指令
    (1) MOV 目的操作数,源操作数
    将源操作数送到目的操作数,目的和源的数的长度要相同,否则会长度不匹配
    (2)XCHG 传送指令
    XCHG 目的操作数,源操作数 //把源和目的操作数交换数值
    2.有效地址传送指令LEA

    LEA 目的操作数,源操作数
    把源操作数的偏移地址送目的操作数,
    源操作数必须是一个内存操作数,
    目的操作数必须是16位通用寄存器
    

    3.堆栈指针操作指令
    堆栈是一块特殊的存储器区域,这块区域是以先进后出的方式工作,系统为此提供了特殊的指针SP,和段寄存器SS
    主要特点是:
    (1)堆栈是以字方式操作的
    (2)压入堆栈。
    ①先修改指针:SP=SP -2
    ②再存入一个字
    (3)弹出堆栈。
    ①先弹出一个字
    ②再修改指针:SP=SP +2

    (4)入栈指令PUSH
    格式:PUSH 操作数
    该指令为数据入栈指令
    即将操作数指定的一个字节的内容传送至SP所指的栈顶
    寻址方式有寄存器寻址(段寄存器SS除外)和存储器寻址,
    不能用立即数作操作数。
    该指令不影响标志位。

    过程:
    首先,堆栈SP=SP-2
    然后,操作数的高位字节——>存入((SP)+1)单元中
    操作数的低位字节——>送入(SP)

    (5)出栈指令:POP
    POP 操作数
    将SP所指的栈顶内容传送至操作数指定的一个字。

    寻址方式有:
    寄存器寻址(段寄存器SS除外)和存储器寻址
    不能用立即数作操作数。
    该指令不影响标志位。

    过程:
    首先堆栈((SP)+1)单元字节——>操作数的高字节位,
    (SP)单元字节——>操作数的低位字节。
    然后SP=SP-2
    4.输入输出指令
    (1)IN 输入指令

    IN AL,N     ; (N)——>AL
    IN AX,N     ;  (N+1:N)——>AX
    IN AL,63H  ; 将端口地址为63H的一个字节内容输入到AL
    IN AX,55H  ;将两个相邻端口地址58H和59H的16位数据输入到AX
    

    (2)OUT 输出指令

    OUT N,AL  ;(AL)字节——>N端口地址的单元中
    OUT N,AX  ;(AX)字——>N+1和N端口地址的单元中
    
    OUT 66H,AL  ;将AL内容送端口地址66H的单元中
    OUT 66H,AX  ;将AX内容送66H和67H端口地址的单元中
    

    !注意:

    在汇编语言中,端口地址小于256(十六进制00H~FFH)时
    可以直接在指令中写出端口地址
    如果端口地址大于256,先将端口地址送入DX寄存器中,
    然后在IN或OUT指令中用DX代表端口地址。


    二、算数运算类指令
    参加运算的可以是无符号数或带符号数,带符号的数以补码的形式存放或参与运算
    1.加法指令
    (1)ADD 目的操作数,源操作数
    目的操作数+源操作数——>目的操作数
    (2)ADC带进位的加法指令
    ADC 目的操作数,源操作数
    目的操作数+源操作数+CF——>目的操作数
    例子:

    MOV AH,0     ;0——>AH
    MOV AL,92H ;92H——>AL
    ADD AL,86H  ;92H+86H=18H——>AL,CF=1
    ADC AH,0      ;(AH)+0+CF=0+0+1=1——>AH,即01H=AH
    

    (3)INC 加|指令
    INC 操作数 //操作数加1,结果送操作数
    操作数可以是任意一个8或16位的通用寄存器或存储单元,不能是立即数
    指令中操作数当作无符号数时,主要用于计数器计数或修改指针地址的值。
    如:

    INC DI   ;(DI)=DI+1
    INC CX  ;(CX)=CX+1
    

    说明:除了指令INC对标志位CF不影响外,其它加法指令对标志位的影响如下

    ①CF:两个数相加,最高有效位有进位时,即字节运算超出无符号输的范围
    0~255,字运算超出无符号数的范围0~65535时,CF=1,否则CF=0.
    故两个无符号数相加时,可用CF值来判断是否超出了无符号数的表示范围
    如果CF=1表示此无符号数加法运算结果发生了溢出。
    ②PF:运算结果以二进制数表示时,若"1"的个数为偶数时PF=1,否则PF=0
    ③AF:运算中D3向D4有进位时,AF=1,否则为0
    ④ZF:运算结果为0时,ZF=1;否则ZF=0
    ⑤SF:运算结果最高位为1时,SF=1,否则为0
    ⑥OF:当两个操作数的符号相同,而相加的结果的符号与操作数的符号相反时
    OF=1,否则OF=0。该标志位用来判断带符号数相加的溢出

    例如:

    ADD AL,30H      ;(AH)+30H ——> AL
    ADD AX,3000H  ;(AX)+3000H ——> AX
    ADD BX,[SI]        ;(BX)+((SI))——>BX
    

    2.减法指令
    (1)SUB
    SUB 目的操作数,源操作数
    目的操作数=目的操作数-源操作数
    (2)SBB 带错位的减法指令
    SBB 目的操作数,源操作数
    目的操作数=目的操作数-源操作数-CF
    (3)DEC 减1指令 格式:DEC 操作数
    DEC DI ;DI=(DI)-1
    (4)NEG 求补指令

    NEG 操作数   //0-操作数的内容后结果回送操作数
    MOV DI,05H
    NEG DI      ;DI=0-(DI)=0-05H=0FBH
    

    (5)CMP 比较指令
    CMP 目的操作数,源操作数
    执行时目的操作数与源操作数相减,只根据结果设置标志位
    操作数均保持原值不变
    3.类型扩展指令
    为了解决操作数长度的匹配,有时需要把数据类型进行扩展。
    主要有把字节扩展成字,把字扩展成双字

    CBW:字节扩展成字
    CWD:字扩展成双字
    

    例子:
    正数的扩展

    MOV AL,52H
    CBW    ;执行指令后,AX=0052H
    CWD    ;执行指令后,DX=0000H,AX=0052H
    

    负数的扩展

    MOV AL,86H
    CBW   ;执行指令后,AX=FF86H
    CWD   ;执行指令后,DX=FFFFH,FF86H
    

    4.乘法指令

    MUL :无符号数乘法
    IMUL:带符号数乘法
    

    目的操作数必须是累加器,不必在指令中写出。
    例子:
    无符号数乘法

    MOV AL,05H
    MOV BL,06H
    MUL BL      //执行结果AX=30=001EH
    

    有符号数乘法

    MOV AL,-5
    MOV BL,+6
    IMUL BL  //AX=-30=FFE2H
    

    5.除法指令
    DIV:无符号除法

    SRC(源操作数)为字节时,AL=AX/SRC的商,AH=AX/SRC的余数
    SRC为字时:AX=(DX,AX)/SRC的商,DX=(DX,AX)/SRC的余数
    

    商和余数都是无符号数。
    IDIV:有符号除法
    操作同上类似,目的操作数必须是累加器AX和DX,不必写出。


    三、位操作指令

    AND 与运算.
    or 或运算.
    XOR 异或运算.
    NOT 取反.
    TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
    SHL 逻辑左移.
    SAL 算术左移.(=SHL)
    SHR 逻辑右移.
    SAR 算术右移.(=SHR)
    ROL 循环左移.
    ROR 循环右移.
    RCL 通过进位的循环左移.
    RCR 通过进位的循环右移.
    以上八种移位指令,其移位次数可达255次.
    移位一次时, 可直接用操作码. 如 SHL AX,1.
    移位>1次时, 则由寄存器CL给出移位次数.
    如 MOV CL,04
    SHL AX,CL
    

    四、串操作指令

    DS:SI 源串段寄存器 :源串变址.
    ES:DI 目标串段寄存器:目标串变址.
    CX 重复次数计数器.
    AL/AX 扫描值.
    D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
    Z标志 用来控制扫描或比较操作的结束.
    MOVS 串传送.
    ( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )
    CMPS 串比较.
    ( CMPSB 比较字符. CMPSW 比较字. )
    SCAS 串扫描.
    把AL或AX的内容与目标串作比较,比较结果反映在标志位.
    LODS 装入串.
    把源串中的元素(字或字节)逐一装入AL或AX中.
    ( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )
    STOS 保存串.
    是LODS的逆过程.
    REP 当CX/ECX<>0时重复.,也就是直到CX=0时结束
    REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复.
    REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
    REPC 当CF=1且CX/ECX<>0时重复.
    REPNC 当CF=0且CX/ECX<>0时重复.
    

    五、控制转移类指令
    1>无条件转移指令 (长转移)

    JMP 无条件转移指令
    CALL 过程调用
    RET/RETF过程返回.
    

    2>条件转移指令 (短转移,-128到+127的距离内)

    ( 当且仅当(SF XOR OF)=1时,OP1<OP2 )
    JA/JNBE 不小于或不等于时转移.
    JAE/JNB 大于或等于转移.
    JB/JNAE 小于转移.
    JBE/JNA 小于或等于转移.
    以上四条,测试无符号整数运算的结果(标志C和Z).
    JG/JNLE 大于转移.
    JGE/JNL 大于或等于转移.
    JL/JNGE 小于转移.
    JLE/JNG 小于或等于转移.
    以上四条,测试带符号整数运算的结果(标志S,O和Z).
    JE/JZ 等于转移.
    JNE/JNZ 不等于时转移.
    JC 有进位时转移.
    JNC 无进位时转移.
    JNO 不溢出时转移.
    JNP/JPO 奇偶性为奇数时转移.
    JNS 符号位为 "0" 时转移.
    JO 溢出转移.
    JP/JPE 奇偶性为偶数时转移.
    JS 符号位为 "1" 时转移.
    

    3>循环控制指令(短转移)

    LOOP CX不为零时循环.
    LOOPE/LOOPZ CX不为零且标志Z=1时循环.
    LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
    JCXZ CX为零时转移.
    JECXZ ECX为零时转移.
    

    4>中断指令

    INT 中断指令
    INTO 溢出中断
    IRET 中断返回
    

    六、处理器控制类指令
    处理器控制类指令只能完成对CPU的简单控制功能。
    共有12条
    对标志位操作

    CLC(进位位置0指令)
    CMC(进位位求反指令)
    STC(进位位置为1指令)
    CLD(方向标志置1指令)
    STD(方向标志位置1指令)
    CLI(中断标志置0指令)
    STI(中断标志置1指令)
    

    同步控制

    WAIT(等待)
    ESC(交权)
    LOCK(封锁总线)
    

    其他

    NOP(无操作)
    HLT(暂停)
    

    七、汇编指令伪指令

    DW 定义字(2字节).
    PROC 定义过程.
    ENDP 过程结束.
    SEGMENT 定义段.
    ASSUME 建立段寄存器寻址.
    ENDS 段结束.
    END 程序结束.

    https://baike.baidu.com/item/汇编指令

    汇编指令是汇编语言中使用的一些操作符和助记符,还包括一些伪指令(如assume,end)。用于告诉汇编程序如何进行汇编的指令,它既不控制机器的操作也不被汇编成机器代码,只能为汇编程序所识别并指导汇编如何进行。

    数据传输

    它们在存储器寄存器、寄存器和输入输出端口之间传送数据。
    1. 通用数据传送指令
    MOV 传送字或字节.
    MOVSX 先符号扩展,再传送.
    MOVZX 先零扩展,再传送.
    PUSH 把字压入堆栈.
    POP 把字弹出堆栈.
    PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
    POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
    PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
    POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
    BSWAP 交换32位寄存器里字节的顺序
    XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数)
    CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX )
    XADD 先交换再累加.( 结果在第一个操作数里 )
    XLAT 字节查表转换.
    ── BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即
    0-FFH); 返回 AL 为查表结果. ( [BX+AL]->AL )
    2. 输入输出端口传送指令.
    IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
    OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )
    输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,
    其范围是 0-65535.
    3. 目的地址传送指令.
    LEA 装入有效地址.
    例: LEA DX,string ;把偏移地址存到DX.
    LDS 传送目标指针,把指针内容装入DS.
    例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
    LES 传送目标指针,把指针内容装入ES.
    例: LES DI,string ;把段地址:偏移地址存到ES:DI.
    LFS 传送目标指针,把指针内容装入FS.
    例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
    LGS 传送目标指针,把指针内容装入GS.
    例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
    LSS 传送目标指针,把指针内容装入SS.
    例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
    4. 标志传送指令.
    LAHF标志寄存器传送,把标志装入AH.
    SAHF 标志寄存器传送,把AH内容装入标志寄存器.
    PUSHF 标志入栈.
    POPF 标志出栈.
    PUSHD 32位标志入栈.
    POPD 32位标志出栈.

    算术运算

    ADD 加法.
    ADC 带进位加法.
    INC 加 1.
    AAA 加法的ASCII码调整.
    DAA 加法的十进制调整.
    SUB 减法.
    SBB 带借位减法.
    DEC 减 1.
    NEG 取补
    CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
    AAS 减法的ASCII码调整.
    DAS 减法的十进制调整.
    MUL 无符号乘法.
    IMUL 整数乘法.
    以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算),
    AAM 乘法的ASCII码调整.
    DIV 无符号除法.
    IDIV 整数除法.
    以上两条,结果回送:
    商回送AL,余数回送AH, (字节运算);
    或 商回送AX,余数回送DX, (字运算).
    AAD 除法的ASCII码调整.
    CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
    CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
    CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
    CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)

    逻辑运算

    AND 与运算.
    or 或运算.
    XOR 异或运算.
    NOT 取反.
    TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
    SHL 逻辑左移.
    SAL 算术左移.(=SHL)
    SHR 逻辑右移.( 每位右移, 低位进 CF, 高位补 0)
    SAR 算术右移.(每位右移, 低位进 CF, 高位不变)
    ROL 循环左移.
    ROR 循环右移.
    RCL 通过进位的循环左移.
    RCR 通过进位的循环右移.
    以上八种移位指令,其移位次数可达255次.
    移位一次时, 可直接用操作码. 如 SHL AX,1.
    移位>1次时, 则由寄存器CL给出移位次数.
    如 MOV CL,04
    SHL AX,CL

    串指令

    DS:SI 源串段寄存器 :源串变址.
    ES:DI 目标串段寄存器:目标串变址.
    CX 重复次数计数器.
    AL/AX 扫描值.
    D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
    Z标志 用来控制扫描或比较操作的结束.
    MOVS 串传送.
    ( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )
    CMPS 串比较.
    ( CMPSB 比较字符. CMPSW 比较字. )
    SCAS 串扫描.
    把AL或AX的内容与目标串作比较,比较结果反映在标志位.
    LODS 装入串.
    把源串中的元素(字或字节)逐一装入AL或AX中.
    LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )
    STOS 保存串.
    是LODS的逆过程.
    REP 当CX/ECX<>0时重复.
    REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复.
    REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
    REPC 当CF=1且CX/ECX<>0时重复.
    REPNC 当CF=0且CX/ECX<>0时重复.

    程序转移

    1>无条件转移指令 (长转移)
    JMP 无条件转移指令
    CALL 过程调用
    RET/RETF过程返回.
    2>条件转移指令 (短转移,-128到+127的距离内)
    ( 当且仅当(SF XOR OF)=1时,OP1<OP2 )
    JA/JNBE 大于转移
    JAE/JNB 大于或等于转移.
    JB/JNAE 小于转移.
    JBE/JNA 小于或等于转移.
    以上四条,测试无符号整数运算的结果(标志C和Z).
    JG/JNLE 大于转移.
    JGE/JNL 大于或等于转移.
    JL/JNGE 小于转移.
    JLE/JNG 小于或等于转移.
    以上四条,测试带符号整数运算的结果(标志S,O和Z).
    JE/JZ 等于转移.
    JNE/JNZ 不等于时转移.
    JC 有进位时转移.
    JNC 无进位时转移.
    JNO 不溢出时转移.
    JNP/JPO 奇偶性为奇数时转移.
    JNS 符号位为 "0" 时转移.
    JO 溢出转移.
    JP/JPE 奇偶性为偶数时转移.
    JS 符号位为 "1" 时转移.
    3>循环控制指令(短转移)
    LOOP CX不为零时循环.
    LOOPE/LOOPZ CX不为零且标志Z=1时循环.
    LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
    JCXZ CX为零时转移.
    JECXZ ECX为零时转移.
    4>中断指令
    INTO 溢出中断
    IRET 中断返回

    其他指令

    伪指令

    DB定义字节(1字节)
    DW 定义字(2字节).
    DD定义双字(4字节)
    PROC 定义过程.
    ENDP 过程结束.
    SEGMENT 定义段.
    ASSUME 建立段寄存器寻址.
    ENDS 段结束.
    END 程序结束.

    控制指令

    标志处理指令 CLC(进位位置0指令)
    CMC(进位位求反指令)
    CLC(进位位置为0指令)
    STC(进位位置为1指令)
    CLD(方向标志位置0指令)
    STD(方向标志位置1指令)
    CLI(中断标志置0指令)
    STI(中断标志置1指令)
    NOP(无操作)
    HLT(停机)
    WAIT(等待)
    ESC(换码)
    LOCK(封锁)

    [原创]【老刘谈算法001】这位运算玩的真溜—strlen函数的汇编实现分析-『密码算法』-看雪安全论坛 https://bbs.pediy.com/thread-229243.htm

    ;原函数作者为Agner Fog,出处为MASM32开发包,在此表示感谢。
    ;中文注释修改&添加 By 老刘。
      
      
        .486
        .model flat, stdcall
        option casemap :none
      
        .code
      
      
    OPTION PROLOGUE:NONE
    OPTION EPILOGUE:NONE
      
    align 4
      
    StrLen proc item:DWORD
      
        mov     eax, [esp+4]            ;获得参数item,即字符串指针
        lea     edx, [eax+3]            ;edx=指针+3
        push    ebp                     ;备份ebp edi
        push    edi
        mov     ebp, 80808080h
      
      @@:     
      REPEAT 3
        mov     edi, [eax]              ;edi=读4个字节
        add     eax, 4                  ;字符串指针指到下4个字节起始,即+4
        lea     ecx, [edi-01010101h]    ;ecx=四字节每个字节-1
        not     edi                     ;edi=四字节逻辑取反
        and     ecx, edi                ;ecx=取反后的每个字节和没取反后-1的每个字节进行逻辑与
        and     ecx, ebp                ;判断每个字节的二进制第8位是否为1,为1则说明原字节=0
        jnz     nxt                     ;如果出现了一个null异端,跳到nxt继续判断
      ENDM
      
        mov     edi, [eax]              ;和上面的一样
        add     eax, 4                  
        lea     ecx, [edi-01010101h]    
        not     edi                    
        and     ecx, edi               
        and     ecx, ebp
        jz      @B                      ;如果没有异端,回去上面循环,有的话都不用跳了,下面就是nxt
      
      nxt:
        test    ecx, 00008080h          ;测试null是否在前2个字节中
        jnz     @F
        shr     ecx, 16                 ;不在前2字节,ecx右移16个二进制位,即右移2字节,使原来的第3、4字节移位到1、2字节处。
        add     eax, 2                  ;字符串指针+2
      @@:
        shl     cl, 1                   ;第一个字节逻辑左移1位,如果第一个字节为Null,则CF=1,否则即说明第二个字节为Null
        sbb     eax, edx                ;eax=eax-edx-CF=eax-(item+3)-CF=字符串长度
        pop     edi
        pop     ebp
      
        ret     4
      
    StrLen endp
      
    OPTION PROLOGUE:PrologueDef 
    OPTION EPILOGUE:EpilogueDef 
      
      
    end
    

      

     
    http://blog.luoyuanhang.com/2015/07/07/几种基本汇编指令详解/ 

    ##常见寄存器

    寄存器16位32位64位
    累加寄存器 AX EAX RAX
    基址寄存器 BX EBX RBX
    计数寄存器 CX ECX RCX
    数据寄存器 DX EDX RDX
    堆栈基指针 BP EBP RBP
    变址寄存器 SI ESI RSI
    堆栈顶指针 SP ESP RSP
    指令寄存器 IP EIP RIP

    ##汇编指令

    ##mov

    • movb(8位)、movw(16位)、movl(32位)、movq(64位)

    • 寄存器寻址:

      movl %eax, %edx

      eax -> edx

    • 立即数寻址:

      movl $0x123, %edx

      数字->寄存器

    • 直接寻址:

      movl 0x123, %edx

      直接访问内存地址数据,edx = *(int32_t *)0x123;

    • 间接寻址:

      movl (%ebx), %edx

      %ebx 是个内存地址,(%ebx)指的是该地址中的数据,edx = *(int32_t*)ebx;

    • 变址寻址:

      movl 4(%ebx), %edx

      edx = *(int32_t*)(ebx+4);

    ##push & pull

    ###堆栈数据结构简介

    ####作用:

    • 程序调用框架
    • 传递参数
    • 保存返回地址
    • 提供局部变量
    • ……

    ####结构:

    image

    • 相关寄存器: esp, ebp

    • 相关操作: pop, push

      //建立被调用者函数的堆栈框架
      pushl %ebp
      movl %esp, %ebp
      
      //拆除框架
      movl %ebp, %esp
      popl %ebp
      ret
      

    ###push:压栈

    • push %eax

      相当于:

      subl $4, %esp
      //栈顶指针减4
      movl %eax, (%esp)
      //%eax -> esp 地址
      

    ###pop:出栈

    • pop %eax

      相当于:

      movl (%esp), %eax
      addl %4, %esp
      //栈顶指针加4
      

    ##call&ret

    ###call

    • call 0x12345

      相当于:

      pushl %eip
      movl $0x12345, %eip
      //当前地址压栈,存入新地址
      

    ###ret

    • 相当于:

      popl %eip
      //栈 -> eip
      

    ##enter&leave

    ###enter

    push %ebp
    movl %esp, %ebp
    //将堆栈置空(栈上重堆)
    

    ###leave

    movl %ebp, %esp
    popl %ebp
    //将堆栈置空(撤销堆栈)
    

    ##例子:分析一段汇编代码

    pushl $8    ①
    movl %ebp, %esp        ②
    subl $4, %esp    ③
    movl $8, (%esp)        ④
     
     
     
     中断号有限,用一个或多个中断号来对应所有的系统调用

    linux系统中断流程

    内核态               中断向量表--->查找0x80--->0x80 中断服务程序(system_call)--->调用--->系统调用表--->查表eax=2--->系统调用sys_fork

    |

    |                    ^
                        |                                      |
                        |
    用户态 用户代码--->fork--->eax=2 int 0x80

  • 相关阅读:
    maven安装和四大特性
    rabbitMQ的安装和创建用户
    java小白之面向对象
    java初级笔记
    laravel 的升级
    prepare
    获取客户端真实IP
    apache nginx 区别
    七猫面试
    linux基本命令
  • 原文地址:https://www.cnblogs.com/rsapaper/p/9824147.html
Copyright © 2011-2022 走看看