0 写在前面

  为了更深入的了解程序的实现原理,近期我学习了IBM-PC相关原理,并手工编写了一些x86汇编程序。

  在2017年的计算机组成原理中,曾对MIPS体系结构及其汇编语言有过一定的了解,考虑到x86体系结构在目前的广泛应用,我通过两个月左右的时间对x86的相关内容进行了学习。

  在《x86汇编语言实践》系列中(包括本篇、x86汇编语言实践(1)、x86汇编语言实践(2)、x86汇编语言实践(3)以及x86汇编语言实践(4)),我通过几个具体案例对x86汇编语言进行实践操作,并记录了自己再编写汇编代码中遇到的困难和心得体会,与各位学习x86汇编的朋友共同分享。

  我将我编写的一些汇编代码放到了github上,感兴趣的朋友可以点击屏幕左上角的小猫咪进入我的github,或请点击这里下载源代码。

  这是《x86汇编语言实践》系列的最后一篇文章,明天就要迎来x86汇编的期末考试了,希望所有朋友们以及先先能够考试顺利!

1 基础知识

1.Intel 8086/8088PC机的CPU字长为16位,16位的信息称为1个字,内存的基本单元为1个字节,但任何相邻两个单元都可以组成1个字。Intel 8086/8088PC机共有20根地址线,其寻址范围为00000H~FFFFFH。

2.用于间接寻址的寄存器有BX,SP,BP,SI,DI,其中,BX一般用于存放基址;在采用基址变址寻址时,采用SI或BX或DI寄存器,基址寻址默认的段是DS段(DS:[SI]);采用BP或SP寄存器,基址寻址默认的段是SS段(堆栈的位置和大小是由SP和SS共同决定的)。

3.串操作指令如MOVSB,STOSB,LODSB,SCASB,CMPSB,MOVSW,LODSW,STOSW,SCASW,CMPSW等,源操作数对应的地址是DS:[SI],目的操作数对应的地址是ES:[DI]。

4.Intel8086/8088CPU共有9个1为的标志寄存器(标志位),为了便于CPU的加工,他们被组合在一起形成一个16位的程序状态字寄存器PSW中。几个比较重要的标志位有:

  • ZF:当运算结果为0时,ZF=1,否则ZF=0
  • SF:运算结果为负时,SF=1,否则SF=0
  • CF:算术运算最高位产生进位,CF=1.否则CF=0;还用于移位指令保存最高位左移或最低位右移移出的代码。
  • DF:DF=1时每次串操作SI和DI减1,DF=0时每次串操作SI和DI加1。使用CLD可以将DF清零,即规定为正向操作字符串。
  • TF:TF=1时执行完一条产生单步中断,中断处理程序将TF置0。TF标志用于调试。
  • PF,AF,IF,OF这里我斗胆预测一啵,不考(因为真的没有使用过)。

5.STD是将DF置1的指令,与CLD将DF清零的效果相反。使用STD后,串指令对应的DI,SI寄存器每次操作后根据是SB还是SW操作自动减少1或2

6.逻辑地址向物理地址的转化(书上P24)。地址转化的动机:20位物理地址无法直接在16位字长的机器中直接运算,因此可以采用Intel的分段方法将其划分为16位段地址和16位段内地址(也称为偏移地址)逻辑地址的基本形式为0000H:0000H,该逻辑地址表示物理地址的00000H。

 那么逻辑地址向物理地址的转换方式可以表述为以下公式:段地址x10H + 偏移地址 = 物理地址

 举例说明:逻辑地址1234H:5678H转换为物理地址为:1234Hx10H + 5678H = 12340H + 5678H = 179B8H。再如:1234H:2001H = 12340H + 2001H = 14341H

7.几个重要的数据传送指令PUSH,POP,PUSHF,POPF

  • PUSH SRC:先SP = SP - 2 再 SS:[SP] <- SRC
  • PUSHF    :先SP = SP - 2 再 SS:[SP] <- PSW
  • POP   SRC:先SRC <- SS:[SP] 再 SP = SP + 2
  • POPF         :先PSW <- SS:[SP] 再SP = SP + 2

 总结而言,PUSH和POP是将操作数压(弹)栈,POPF和PUSHF是将PSW标志寄存器压(弹)栈

2 寻址方式

2-1 六种与数据有关的寻址方式

2-1-1 立即寻址

  直接将立即数写到指令中的寻址方式。注意不得超出寄存器的字节范围:AL8位,AX16位。

  【例】

  • AND AX,0FFFEH
  • MOV AL,100H
  • MOV AL,00000101B
  • MOV AX,512

  【不能使用】

  • MOV AL,100H
  • MOV AX,10000H (超出了字节范围)

2-1-2 寄存器寻址

  使用寄存器的寻址方式。可以显示使用,也可以隐式使用。也可以使用段寄存器CS,DS,SS,ES。

  【例】

  • MOV DS,AX
  • PUSH DS
  • PUSHF (隐式操作PSW)
  • STD (隐式操作PSW)
  • CMC  (对CF取反操作,隐式操作PSW)

2-1-3 直接寻址

  直接使用操作数的偏移地址进行寻址的方式,偏移地址用[立即数]的形式表示,或者直接用数据段中定义的变量名表示,或用数据段中定义的变量名+立即数的形式表示。

  【例】

  • AND AX,[0FFFEH]
  • MOV AX,X    ;其中X为数据段中定义好的数据
  • MOV AX,STR+1   ;其中STR为数据段中定义好的数据,STR+1直接寻址到STR下一个字节单元的内容

2-1-4 寄存器间接寻址

  使用寄存器中存储的偏移地址进行寻址。注意只能使用寻址寄存器BX,BP,SI,DI进行寻址,而不能用DX等进行寻址。此外,寻址的地址必须为16位,即不能使用BL等进行寻址。

  【例】

  • MOV AX.[BX]
  • MOV BH,[BP]
  • MOV CX,[SI]
  • MOV DL,[DI]

  以上四条指令等价于

  • MOV AX.DS:[BX]
  • MOV BH,SS:[BP]
  • MOV CX,DS:[SI]
  • MOV DL,ES:[DI]

  但是在每条指令前加上一个段超越的段名,既麻烦又没必要,因此通常都默认缺省为上述隐含段规则。

  【不能使用】

  • MOV AX,[DX]  (不能用DX)
  • MOV DL,[BL]  (必须为16位寻址)

2-1-5 寄存器相对寻址

  在寄存器间接寻址的基础上,再增加一个常偏移量。形式多变,大致有如下几种

  【例】

  • MOV AX,[BX+100]
  • MOV AX,[SI+10H]   <==>  MOV AX,10H[SI]
  • MOV AX,ARRAY[SI]
  • MOV TABLE[DI],AL
  • MOV TABLE[DI+1],AL  3~5展示了立即数也可以是数据段中定义好的变量名

  最终在debug下所有的寻址有效地址会被计算成[DI+XXXX]的形式,XXXX是一个十六进制数。

2-1-6 基址变址寻址

  即基址加变址寻址方式,基址采用BX,BP寻址,变址采用DI,SI寻址,寻址规则相对固定。

  【例】

  • MOV AX,[BX][SI]
  • MOV AX,[BX+SI]
  • MOV ES:[BX+SI],AL
  • MOV [BP+DI],AX
  • MOV AX,[BX+SI+200]
  • MOV ARRAY[BP+SI],AX

  其中,段取决于基址寄存器,如BX的段就默认为DS;BP缺省为SS。当然,有指定段的情况除外。也可以在两个寄存器加和的基础上再增加一个立即数。

  【不能使用】

  • MOV [BX+CX],AX  (CX不能做变址寄存器)
  • MOV [BX+BP],AX  (BP不能做变址寄存器)
  • MOV [BX+DI],ARRAY  (两个全在内存中的操作数,不符合语法)

2-1 五种与转移地址有关的寻址方式

2-2-1 标号与过程名

  与转移地址相关的指令主要是JMP和CALL指令,而要让代码能够跳跃执行到指定的IP处则需要通过标号指示某行代码,或是通过过程名定义进行CALL调用。

2-2-2 段内直接寻址

  即直接使用标号与过程名进行跳转。根据位移量的不同,可以加SHORT(8BITS)和NEAR PTR(16BITS)操作符。其中,条件跳转只能是8位因此省略SHORT,而JMP则缺省为16位位移量。因此,在跳转位移已知的前提下,使用JMP SHORT可以提高程序的执行效率。

  【例】

  • JMP L1
  • CALL P1
  • JMP SHORT L1
  • JMP NEAR PTR L1  (L!与当前IP位移量为16位的数值)

2-2-3 段内间接寻址

  即将转移目的地址放入寄存器中进行存储,调用的也是寄存器中的相应数值。

  【例】

  • MOV AX,OFFSET P1     CALL AX
  • JMP BX

  这里要特别注意段内间接寻址与数据寻址中寄存器间接寻址的区别,后者有[]进行寻址。

  • MOV AX,OFFSET P1    MOV ADD1,AX    CALL ADD1
  • MOV BX,OFFSET ADD1   CALL [BX]

  以上两种也是段内间接寻址,注意这里ADD1不是过程名,而是数据段中的一个数据的地址,存放了子程序P1的位移量。BX则存放了ADD1的地址,因此调用CALL [BX]也属于段内间接寻址。

2-2-4 段间直接寻址

  具备FAR属性的寻址。例如P2为一个有FAR属性定义的过程:

  • CALL FAR P2

2-2-5 段间间接寻址

  形式如下:

  • JMP DWORD PTR [BX+INTERS]

  只要DWORD PTR后面是除了立即寻址和寄存器寻址之外的任何一种数据寻址方式即可。

3 语法知识

【判断指令正误】

  • MOV [CX],AL     不正确。CX不能作为寄存器间接寻址的寄存器
  • MOV BH,320     不正确。320超出了8位范围(255)
  • MOV DS,2000H     不正确。不存在从立即数到段寄存器的数据通路。此外,段寄存器作目的操作数时,不允许使用CS作为目的操作数。
  • ADD SI,FDDH     不能确定。如果在数据段定义过一个名为FDDH的数据变量,且该数据在字节范围内,则此指令正确。否则会认为FDDH是一个未定义的变量,改成0FFDH后正确。
  • SHL AX,2     不正确。移位指令格式中,移位的数量count只能是1或CL。移动位数大于1(0和1也可以)必须放入CL寄存器中操作。
  • CMP BYTE PTR [SI],X     不正确。源操作数和目的操作数不能同时为内存中的数。
  • LEA BX,[SI]       正确。
  • LDS BX,[DX]     不正确。DX不能用作寄存器间接寻址的寄存器
  • JMP BYTE PTR AX     不正确。转移只有NEAR/FAR PTR + 标号或SHORT+标号或只有标号/寄存器的形式。没有JMP BYTE PTR的形式
  • JMP AX     正确。
  • JMP [AX]     不正确。AX不能用作间接寻址的寄存器。
  • RET 5     不正确。后面的立即数必须为偶数。这是为了带参数调用的子程序在返回时要弹出几个参数的位置,进而维持堆栈的平衡。
  • MOV [BX+SI+10],100     不正确。注意只有在寄存器相对寻址取数(作为源操作数)时直接寻址即可,若作为目的操作数则必须指定size。修改为MOV BYTE PTR[BX+SI+10],100即可。
  • DIV AL    正确。执行结果为AX=0001即除以本身,商1余0。

4 简答问题

4-1 解读指令执行过程

1. RET EXP

  IP ← [SP]

  SP ← SP + 2

  SP ← SP + EXP

2.RETF

  注意如果是FAR属性的过程,返回时是段间返回(即在汇编器中会被汇编成RETF指令),会执行以下过程

  IP ← [SP]

  SP ← SP + 2

  CS ← [SP]

  SP ← SP + 2

3.PUSH SRC

  SP ← SP - 2

  SS:[SP] ← SRC

4.PUSHF

  SP ← SP - 2

  SS:[SP] ← PSW

5.POP DST

  DST ← SS:[SP]

  SP ← SP + 2

6.POPF

  PSW ← SS:[SP]

  SP ← SP + 2

7.LEA REG,SRC

  将SRC的偏移地址送入REG  

8.LDS/LES REG,SRC

  将SRC中的双字内容分别送REG和DS/ES中。

  这里的SRC中的双字通常保存的是某个程序或变量的逻辑地址(SEG:OFFSET),前面的低字送入REG,后面的高字送入DS/ES。

9.CALL FAR PTR P1

  SP ← SP - 2

  SS:[SP] ← 返回地址段值

  SP ← SP - 2

  SS:[SP] ← 返回地址偏移值

  IP  ← 目的偏移地址

  CS ← 目的段地址  

10.CALL AX(假设为段内间接调用)

  SP ← SP - 2

  SS:[SP] ← 返回地址偏移值

  IP ← AX中有效地址

11.JMP [BX]

  从内存中根据BX间接寻址,取得的标号值送IP进行跳转。

12.JMP DX

  将DX中有效地址偏移值送入IP进行跳转。

13.CALL DWORD PTR [BX]

  段间间接调用,过程地址CS:IP(这是一个双字,因此用DWORD PTR)位于数据段中通过BX间接寻址得到。

14.LOOP LP1

  CX = CX - 1

  若CX ≠ 0,则跳转至LP1,否则顺序执行之后代码。

15.CMP BX,X1

  分别通过寄存器寻址和直接寻址取得BX与X1的值,计算BX-X1并影响标志位。(如可用ZF判断两数是否相等、CF=1或SF=1则BX<X1等等,再配合JC,JS等指令即可进行条件跳转)

16.INT 21H / IRET

  Intel8086/8088指令系统中用于支持中断调用的指令为INT n,返回中断的指令时IRET。此外,CLI用于清除中断标志,STI用于设置中断标志。

                                               ----《书》P173

  INT 21H的执行过程:

  • SP ← SP - 2
  • SS:[SP] ← PSW
  • SP ← SP - 2
  • SS:[SP] ← INT N 下一条指令的CS
  • SP ← SP - 2
  • SS:[SP] ← INT N 下一条指令的IP
  • IP ← [0000 : N*4]
  • CS ← [0000 : N*4+2]

  IRET的执行过程:

  • IP ← SS:[SP]
  • SP ← SP + 2
  • CS ← SS:[SP]
  • SP ← SP + 2
  • PSW ← SS:[SP]
  • SP ← SP + 2

4-2 图解移位指令

4-3 指出目的寄存器中的内容

  已知:DS = 2100H,BX = 0100H,SI = 0002H;内存中:[21100H] = 12H,[21101H] = 34H,[21102H] = 56H,[21103H] = 78H。

  • MOV AX,[101H]  ;直接寻址,默认段DS。AX的结果为3456H ?在DOS下,汇编后变成了MOV AX,101这种立即寻址形式,使得AX最终的结果为0101H
  • MOV AX,WORD PTR [BX+2] ;寄存器相对寻址。AX结果为7856H
  • MOV AL,BYTE PTR [BX][SI+1] ;基址变址寻址。AL结果为78H
  • MOV AX,100H [SI] ;寄存器相对寻址。AX结果为7856H(注意取出的为一个字!而且是小端存储!低字节在高位!)

4-4 指出CS与IP的值

  已知:DS = 2100H,BX = 0101H,CS = 1900H;内存中:[21101H] = 0C7H,[21102H] = 0FFH,[21103H] = 00H,[21104H] = 0F0H。

  • JMP BX  ;CS = 1900H,IP=0101H
  • JMP [BX]        ;CS = 1900H,IP=0FFC7H
  • JMP WORD PTR [BX+1]          ;CS = 1900H,IP=00FFH   (注意小端存储,低字节在低地址)
  • JMP DWORD PTR [BX]            ;CS = 0F000H,IP=0FFC7H  (取双字分别取得的是段地址与偏移值)

4-5 根据要求画内存示意图

  1.定义MYSEG数据段,其中有S1,内容'ABCD'以00H结尾;S2是能用AH=9,INT 21H显示的字符串;S3为10x10的二维字数组。L1为S1+S2+S3的长度。

  则可以画出该数据段内存示意图如下:

  

  其中一个英文字母占据1字节,即一个内存单元;显示字符串必须以'$'结尾。常量定义形式应为 L1 EQU $-S1。注意,字数组一个字占两个字节。故L1的值为210。

  2.书P96第2题的数据段可以定义如下:

1 DATA SEGMENT PARA
2     X1 DB 'Display string',0DH,0AH,'$'
3     X2 DB 32
4     X3 DW 40H
5     X4 DD A000H,0120H
6     X5 DW 10 DUP(8 DUP(0))
7     X6 EQU $-X1
8 DATA ENDS

4-6 综合练习题

  【题签】有数据段定义如下:

1 DATA1 SEGMENT PARA
2     X1 DB 20H,?,'A'
3     X2 DW 2 DUP(1,2DUP(1,?))
4     X3 DD 12345678H
5     LEN EQU $-X2
6 DATA1 ENDS

  (1)画出内存图

  (2)执行MOV AX,X3+1后,AX为?

  (3)执行MOV CX,LEN后,CX为?

  【解】

  (1)内存图如下:

  

  说明:对于字和双字的定义,低字节在低位,因此如对于DW 1234H来说,在内存中由低地址到高地址依次为34H、12H;对于DD 12345678H而言,在内存中由低地址到高地址依次为78H、56H、34H、12H。而对于数组的定义而言,如DUP,则是按照其定义先后顺序在内存中由低到高排列的。必须注意的是:由于前面定义的是字DW,所以DUP中的每一个数值都占据两个内存单元,即1个字的空间,这在画内存图时必须要注意!

  (2)AX = 3456H这道题这里有点小bug,编译后会报告1个warning,更好的改进是使用MOV AX,WORD PTR X3+1。

    这道题可以改进成一个更有意思的考法:MOV AX,WORD PTR X3+2

    这样以来就要联系(1)中画的内存图了。内存中高地址存放的是数据中的高字节。因此结果应该是AX=1234H

  (3)CX = 18H(可以表示为16进制,一定注意数组定义DW DUP的问题!这会对LEN的计算产生影响)

5 编程题

5-1 加法

  计算Z=X+Y。其中X,Y为16位数,Z为32位数。

1 XOR     DX,DX
2 MOV     AX,X
3 ADD     AX,Y
4 ADC     DX,0
5 MOV     WORD PTR Z+2,DX
6 MOV     WORD PTR Z,AX

  这里引入一个技巧:为了操作32位数,我们需要借用DX:AX进行操作,我们一个一个地计算这两个寄存器中的数值,低位产生的进位补到DX中去,使用ADC指令。最后为内存中的Z使用WORD PTR进行赋值即可。

5-2 右移

  将32位X右移4位。

 1 MOV     AX,WORD PTR X
 2 MOV     DX,WORD PTR X+2
 3 SHR     DX,1
 4 RCR     AX,1
 5 SHR     DX,1
 6 RCR     AX,1
 7 SHR     DX,1
 8 RCR     AX,1
 9 SHR     DX,1
10 RCR     AX,1

  必须要注意的是这里必须使用SHR与RCR指令配合4次,每次移动1位进行使用,这是由于,CF只能存放1位数字!

5-3 乘法

  用移位及加法指令,将32位数X计算X = X * 10。

 1 MOV     AX,WORD PTR X
 2 MOV     DX,WORD PTR X+2
 3 SHL     AX,1
 4 RCL     DX,1
 5 MOV     BX,AX
 6 MOV     CX,DX
 7 SHL     AX,1
 8 RCL     DX,1
 9 SHL     AX,1
10 RCL     DX,1
11 ADD     AX,BX
12 ADC     DX,CX
13 MOV     WORD PTR X,AX
14 MOV     WORD PTR X+2,DX

  这里用到的技巧是将X*10分解成X*2 + X*8来计算,也就是将X左移1位保存下来再左移2位加上刚才保存的值即可。

5-4 打印

  将内存中16位X显示为十六进制ASCII码。

 1     MOV     BX,X
 2     MOV     CX,4
 3 LP:
 4     PUSH     CX
 5     MOV     CL,4
 6     ROL     BX,CL
 7     MOV     AL,BL
 8     AND     AL,0FH
 9     ADD     AL,30H
10     CMP     AL,39H
11     JBE     DISP
12     ADD     AL,7
13
14 DISP:
15     MOV     DL,AL
16     MOV     AH,2
17     INT     21H
18     POP     CX
19     LOOP     LP

  注意以下几点技巧:

  • 16位数字X需要输出4位数字,因此设置CX的值为4作为外层循环次数
  • 输出每次对X的值进行循环左移4位(不带CF)的ROL指令,这样每次BL的低4位即为当前要输出的值
  • 由于又用到了CL,因此外层循环的CX需要在第4行处压栈处理
  • 由于每次输出只有4位,而最少取出AL为8位,因此需要使用第8行AND AL,0FH来屏蔽AL的高4位
  • 需要注意的是,在16进制中超过9的数字变成了A,由于ASCII码中‘9’与‘A’之间相差8,因此需要判断是否需要给AL增加相应值,使用的是ADD AL,7实现
  • 输出单个字符的中断调用为2号中断调用

6 写在最后

  熊老师的《x86汇编语言》这门课程是本学期选的最成功的一门课程,熊老师对学生也十分认真负责。这也再次印证了那个真理,那就是只有实践,才能真正把理论中的内容理解、消化。

  从最开始的连课都听不懂、程序写不出、编程毫无头绪,到后来经历了几次作业的历练后,思路渐渐清晰,我不得不十分感谢熊老师的严格要求。

  汇编是一种十分贴近计算机底层的语言,它深刻的揭示了程序运行的过程以及内存的使用和分配机制,在本科阶段,有汇编编程的锻炼经历,我认为是十分有必要的。

  最后,在编写这篇笔记的过程中,还要特别感谢小马哥和乔给我提出的宝贵的修改意见!

  明天就要期末考试了。真心的希望先先能够发挥高水平,取得好成绩。与各位共勉!

转载于:https://www.cnblogs.com/chrischen98/p/10836078.html

x86汇编语言复习笔记相关推荐

  1. x86汇编语言复习总结

    x86汇编总结 寄存器 指令 数据传输指令 算术运算 位运算 逻辑运算 串操作 JCC 寻址方式 调用约定 汇编是逆向的基础,太重要了:把笔记上的又总结了一遍,如有错误,欢迎指正~~互相进步,逆向路漫 ...

  2. 任务切换——《x86汇编语言:从实模式到保护模式》读书笔记38

    任务切换--<x86汇编语言:从实模式到保护模式>读书笔记38 本文及后面的几篇博文是原书第15章的学习笔记. 本章依然使用第13章的主引导程序. 1. 协同式多任务与抢占式多任务 有两种 ...

  3. 任务和特权级保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记34

    任务和特权级保护(三)--<x86汇编语言:从实模式到保护模式>读书笔记34 5.2.7 在GDT中创建LDT描述符 处理器要求在GDT中安装每个LDT的描述符.当要使用这些LDT时,可以 ...

  4. 程序的加载和执行(六)——《x86汇编语言:从实模式到保护模式》读书笔记26

    程序的加载和执行(六)--<x86汇编语言:从实模式到保护模式>读书笔记26 通过本文能学到什么? NASM的条件汇编 用NASM编译的时候,通过命令行选项定义宏 Makefile的条件语 ...

  5. 程序的加载和执行(四)——《x86汇编语言:从实模式到保护模式》读书笔记24

    程序的加载和执行(四)--<x86汇编语言:从实模式到保护模式>读书笔记24 通过本文能学到什么? 怎样跳转到用户程序 用户程序通过调用内核过程完成自己的功能 怎样从用户程序返回到内核 接 ...

  6. 程序的加载和执行(一)——《x86汇编语言:从实模式到保护模式》读书笔记21

    程序的加载和执行(一) 本文及之后的几篇博文是原书第13章的学习笔记. 本章主要是学习一个例子,对应的代码分为3个文件: ;代码清单13-1;文件名:c13_mbr.asm;文件说明:硬盘主引导扇区代 ...

  7. 【OS修炼指南目录】----《X86汇编语言-从实模式到保护模式》读书笔记目录表

    学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 本文是将个人 ...

  8. 硬盘和显卡的访问与控制(一)——《x86汇编语言:从实模式到保护模式》读书笔记01

    本文是<x86汇编语言:从实模式到保护模式>(电子工业出版社)的读书实验笔记. 这篇文章我们先不分析代码,而是说一下在Bochs环境下如何看到实验结果. 需要的源码文件 第一个文件是加载程 ...

  9. 16位模式/32位模式下PUSH指令探究——《x86汇编语言:从实模式到保护模式》读书笔记16...

    一.Intel 32 位处理器的工作模式 如上图所示,Intel 32 位处理器有3种工作模式. (1)实模式:工作方式相当于一个8086 (2)保护模式:提供支持多任务环境的工作方式,建立保护机制 ...

  10. 《x86汇编语言:从实模式到保护模式》读书笔记之后记

    本来打算把整本书的读书笔记写完,可是由于有其他的计划(就叫做"B计划"吧)且优先级更高,所以我的读书笔记搁浅了.为了全力以赴执行B计划,我的博客要荒芜一段时间(我希望不要永远荒芜下 ...

最新文章

  1. Spring Boot 工程集成全局唯一ID生成器 Vesta
  2. 从游戏脚本语言说起,剖析Mono所搭建的脚本基础
  3. 网站建设中的五大常见问题
  4. 关于《如何阅读一本书》
  5. 大数据WEB阶段(二十)更新丢失
  6. 科普扫盲,HTTP Status Code详解,从此排错无忧!
  7. 科技人员在计算机前的肖像,首个全国科技工作者日来了 西南大学学子为科技工作者画像...
  8. dataset转换json格式
  9. 网页制作中如何自定义网页图标
  10. 华为在中国建立其全球最大的网络安全透明中心
  11. 我知道有中年危机,但没想到这么不堪
  12. h5 在线语音识别接口
  13. win10自带sftp服务器_用于Windows系统的免费SFTP服务器-Free SFTP Servers及各款软件功能对比...
  14. 相机模型坐标系关系及转换
  15. python浪漫代码表白npy_python – Cython使用MemoryView时关于NPY_NO_DEPRECATED_API的Numpy警告...
  16. 完美显示html的版权符号
  17. 算法-经典趣题-爱因斯坦阶梯问题
  18. 001-取整函数(ceil、floor、round)
  19. ARC093F Dark Horse 容斥原理+DP
  20. selenium利用cookie跳过验证码登录

热门文章

  1. 机器学习最简单算法——KNN算法(K-Nearest Neighbor)
  2. go mysql stmt exec_Go语言操作MySQL
  3. python获取昨天日期_python 获取今天、昨天、明天的时间时间戳
  4. latex 可视化生成表格代码
  5. DevOps使用教程 华为云(17)git 比较2个分支版本的差异 某个具体文件的差异
  6. Hyperledger Fabric教程(10)-- peer命令-链码chaincode
  7. Hyperledger Fabric教程(1)--Hyperledger Fabric 老版本 1.1.0 快速部署安装
  8. oracle将列名进行拼接,请教关于用拼接的字符串作为表的列名进行操作的问题
  9. asp 基础操作之增删改查
  10. 使用bat命令批量命名图片名称的方法及解决bat格式中文乱码的问题(如:图片.jpg)