5.1 汇编语言:汇编语言概述

汇编语言是一种面向机器的低级语言,用于编写计算机程序。汇编语言与计算机机器语言非常接近,汇编语言程序可以使用符号、助记符等来代替机器语言的二进制码,但最终会被汇编器编译成计算机可执行的机器码。

相较于高级语言(如C、Python等),汇编语言学习和使用难度相对较大,需要对计算机内部结构、指令集等有深入的了解,以及具有良好的编程习惯和调试能力。但对于需要对计算机底层进行操作的任务,汇编语言是极其高效的,因为其可以实现对计算机底层资源的精细控制,极大地提高了计算机运行效率。

尽管在当今计算机界已经不再使用汇编语言来开发程序,但作为一名安全从业者掌握汇编语言将会是高手与专家之间最大的差距,汇编语言作为底层语言,具有直接访问计算机硬件和系统资源的能力,因此在系统级漏洞挖掘、内核安全、计算机反病毒等领域中具有非常重要的作用。

以下是关于汇编语言的应用场景:

  • 系统级漏洞挖掘:许多系统级漏洞,如堆栈溢出、整数溢出等,都是由于程序员没有理解底层操作系统和硬件的工作原理而导致的。因此,理解汇编语言可以帮助安全研究人员更好地了解底层的操作系统和硬件原理,从而更好地挖掘漏洞。

  • 内核安全:汇编语言是编写内核模块或驱动程序所必需的语言,例如,Linux内核中的大部分代码都是使用汇编语言实现的。因此,对于理解内核原理和进行内核安全研究来说,掌握汇编语言非常重要。

  • 计算机反病毒:许多计算机病毒和恶意软件都使用汇编语言编写,因此掌握汇编语言可以帮助研究人员更好地理解这些恶意软件的工作原理和行为,并提高反病毒软件的捕获率和准确性。

总之,熟练掌握汇编语言对于进行系统级漏洞挖掘、内核安全研究、计算机反病毒等领域都非常有帮助。虽然汇编语言相对来说比较底层和难以理解,但是深入掌握汇编语言将会极大地提高软件安全研究人员的技能和水平,让读者从一个高手蜕变成一名安全专家。

本章中所提到的汇编语言为Windows汇编,在Windows平台下读者可使用MASM工具对汇编语言进行编译测试,也可以使用通用的集成开发环境实现编译,笔者推荐使用RadASM工具,RadASM 是一个面向汇编编程的开发环境,提供了一系列工具和功能,用于编写、调试和优化汇编语言程序。该工具具有良好的可定制性和扩展性,且能提供丰富的工具和功能,方便程序员进行汇编语言的开发和调试工作。

1.1 RadASM

当读者准备好开发环境后可打开RadASM工具,选择文件新建工程按钮,并选择ConsoleApp选项填入自定义工程名称并一直点击下一步即可,当读者进入到主页面后会看到如下图所示的窗体,其中最右侧则是我们的项目目录,该目录下的Resources则是我们需要测试代码的地方,读者可自行点开*.asm文件并在此处写代码,当读者需要编译代码可使用快捷键Ctrl+Shift+V快速构建,也可点击右上角的编译构建按钮自行构建;

使用Win32汇编语言做开发其开发感觉与高级语言基本一致,并没有像大家想象中的那么困难,唯一的区别只是在高级语言中可以很容易实现的语句,而到了汇编语言这里将会变得较为繁琐,读者只要认真理解汇编语言中的每一条指令所代表的含义,则同样可以灵活的运用汇编语言开发大型项目,首先笔者来解释一下关于上述图片中代码的具体含义;

根据上述代码中第一行的定义.386p代表了指令集的选择,此处代表我们选用Intel 80386处理器的指令集,其中的p则代表将代码对齐到32位指令上,接着看第二行.model flat, stdcall此处代表了调用约定采用stdcall模式,并设置代码和数据段都使用平坦模型(flat model)来处理内存,第三行option casemap:none代表后续程序不区分大小写,当有了上述这三行定义后汇编语言的预定义部分也就结束了。

接着就是比较熟悉的定义语法了,这里的include/includelib分别代表头文件以及库文件的引用,如果读者需要调用Windows系统内的函数定义,则此处的头文件则是必须要包含windows.inc以及kernel32.inc头的,此外还需要导入kernel32.lib库来完成头文件功能的导入;

  • .data:定义已初始化变量。该指令定义了一个16位的可赋值变量Main,并将其初始化为1024。
  • .data?:定义未初始化变量。该指令定义了一个32位的未初始化变量lyshark。
  • .const:定义常量。该指令定义了一个以0h(十六进制)为结尾的字符串常量var1,内容为“lyshark”。
  • .code:代码段开始。该指令表示代码段的开始。

接下来就是main PROC以及main ENDP定义了,此处的定义部分读者可理解为int main()函数,此处的功能同样是定义主程序入口和结束,而当我们需要编写应用程序时只需要在上方不同的段内填充参数即可,其开发流程可以与高级语言一致。

1.2 汇编中的变量

MASM 定义了多种内部数据类型,每种数据类型都描述了该类型的变量和表达式的取值集合,汇编语言中数据类型的基本特征是以数据位数为度量单位,8,16,32,48,64,80位,而除此之外其他的特征如(符号,指针,浮点数)主要是为了方便我们记忆变量中存储的数据类型,如下表中所定义的部分,则是IEEE委员会发布的标准内部数据类型;

数据类型作用(无符号)数据类型作用(有符号)
BYTE8位无符号整数SBYTE8位有符号整数
WORD16位无符号整数SWORD16位有符号整数
DWORD32位无符号整数SWORD32位有符号整数
FWORD48位整数(远指针)QWORD64位整数定义
REAL432位(4字节)短实数REAL864位(8字节)长实数

数据类型定义语句为变量在内存中保留存储空间,并且可以选择为变量指定一个名字,在汇编语言中所有的数据无非就是BYTE的集合,数据的定义语句格式如下;

[变量名] 数据定义伪指令 初始值[....]

在数据定义语句中使用BYTE(定义字节)SBYTE(定义有符号字节)伪指令,可以为每一个或多个有符号或无符号字节分配存储空间,每个初始值必须是8位整数表达式或字符常量,例如下面的定义:

.data
  var1 BYTE 'A'      ; 定义字符常量
  var2 BYTE ?        ; 定义未初始化变量
  var3 BYTE 0        ; 最小的无符号字节常量
  var4 BYTE 255      ; 最大的无符号字节常量
  var5 SBYTE -128    ; 最小的有符号字节常量
  var6 SBYTE +127    ; 最大的有符号字节常量

如果一条数据定义语句中有多个初始值,那么标号仅仅代表第一个初始值的偏移,如下我们首先定义一个BYTE数组,然后通过反汇编查看地址的偏移变化就能看到效果啦:

.data
  list BYTE 10,20,30,40,50

00E71000 | B8 0030E700        | mov eax,main.E73000                 | E73000=10
00E71005 | B8 0130E700        | mov eax,main.E73001                 | E73001=20
00E7100A | B8 0230E700        | mov eax,main.E73002                 | E73002=30
00E7100F | B8 0330E700        | mov eax,main.E73003                 | E73003=40
00E71014 | B8 0430E700        | mov eax,main.E73004                 | E73004=50

并非所有的数据定义都需要标号,如果想继续定义以list开始的字节数组,可以在随后的行上接着上面的定义:

.data
  list BYTE 10,20,30,40,50
  list BYTE 60,70,80,90,100

当然除了定义整数字符以外,还可以定义字符串,要想定义字符串应将一组字符用单引号或双引号括起来,最常见的字符串是以空格结尾0h,在C/C++中定义字符串无需添加结尾0h,这是因为编译器会在编译的时候自动的在字符串后面填充了0h,在汇编语言中我们需要手动添加字符串结尾的标志,以告诉汇编器字符串的结束。

.data
  string1 BYTE "hello lyshark",0h
  string2 BYTE "good night",0h

00F23000  68 65 6C 6C 6F 20 6C 79 73 68 61 72 6B 00 67 6F hello lyshark.go 
00F23010  6F 64 20 6E 69 67 68 74 00 00 00 00 00 00 00 00 od night........ 

字符串也可以占用多行,而无须为每行都提供一个编号,如下代码也是合法的:

.data
  string1 BYTE "welcom to the Demo program"
      BYTE "created by lyshark",0dh,0ah,
      BYTE "url:lyshark"
      BYTE "send me a copy",0dh,0ah,0

十六进制0dh,0ah也称为CR/LF(回车换行符),或者是行结束的字符,在向标准输出设备上写的时候,回车换行符可以将光标移动到下一行的开头位置,从而继续填充新的字符串。

有时我们需要初始化一些空值的内存空间,在为内存地址分配空间的时候,DUP伪指令就显得尤为重要,初始化和未初始化数据均可使用DUP指令定义,其定义语法如下:

.data
  string1 BYTE 20 DUP(0)       ; 分配20字节,全部填充0
    BYTE 20 DUP(?)             ; 分配20字节,且未初始化
    BYTE 50 DUP("stack")       ; 分配50字节,"stackstack..."

.data
  smallArray DOWRD 10 DUP(0) ; 分配40字节
  bigArray DOWOR 5000 DUP(?) ; 分配20000字节

除了上面的例子以外,我们也可以直接定义常量,常量是不可以动态修改的数据类型,一般情况下一旦定义,那么在程序运行期间不可以被修改,常量的定义很简单,只需要将.data换成.const即可。

.const
  var1 BYTE  "hello world",0h   ; 初始化为BYTE的字符串
  var2 DWORD 10                 ; 初始化为10的DWORD类型
  var3 DWORD 100 dup(1,2)       ; 200个DWORD的缓冲区
  var4 BYTE  1024 dup(?)        ; 1024字节的缓冲区
  var5 BYTE "welcome",0dh,0ah,0 ; 0dh,0ah为换行符

有时我们需要计算一个指定数组的所占空间的大小,但手动计算显得特别麻烦,此时我们可以使用MASM提供的$符号来进行数组大小的计算过程,如下定义汇编器会将其进行预处理后回写到变量中存储。

.data
  list BYTE 10,20,30,40,50
  listsize = ($ - list)       ; 计算字节数据大小

.data
  list WORD 1000h,2000h,3000h,4000h
  listsize = ($ - list) /2    ; 计算字数据大小

.data
  list DWORD 100000h,200000h,300000h,400000h
  listsize = ($ - list) /4    ; 计算双字数据大小

.data
  MyString BYTE "hello lyshark",0h
  MyString_len = ($ - MyString)
1.3 标准输入与输出

在汇编语言中,有时我们需要获取到数据的输入输出,由于汇编中并不存在屏幕打印功能,此处如果读者需要使用此功能,则必须调用系统所提供的库函数来实现,一般要想实现输入输出有多种图形,具体来说,StdInStdOut分别代表标准输入流和标准输出流;WriteFile函数用于向文件或其他输出设备写入数据;crt_scanfcrt_printf是格式化输入/输出函数,这些库函数的调用都可以使用invoke这个伪指令来实现,invoke是MASM中提供的调用关键字,使用它可实现调用各类API函数的目的。

StdIn/StdOut

如果读者需要使用该函数输出,则需要包含masm32.inc头文件,该头文件为汇编语言程序员提供了一组常用的宏和函数,在这个头文件中,定义了StdIn、StdOutStdErr三个宏,它们分别代表标准输入流、标准输出流和标准错误流。

使用masm32.inc中的这些宏,可以方便地将输入输出重定向到控制台或文件中,而无需直接调用Windows API函数。例如,可以使用StdIn宏从控制台读取用户输入,使用StdOut宏向控制台输出字符流。这些宏的使用方式与在C语言中使用 stdin 和 stdout 类似。

下面是一些示例代码,使用masm32.inc头文件来实现标准的输入输出:

  .386
  .model flat, stdcall
  
  include masm32.inc
  include kernel32.inc
  includelib masm32.lib
  includelib kernel32.lib

.data
  len equ 20
  OutText dw ?
  ShowText db "请输入一个数: ",0

.code
  main PROC
    invoke StdOut, addr ShowText    ; 输出提示信息
    invoke StdIn, addr OutText,len  ; 等待用户的输入
    invoke StdOut, addr OutText     ; 输出刚才输入的内容
    ret
  main ENDP
END main

crt_printf/crt_scanf

除了使用MASM定义的宏之外,读者也可以使用C语言库函数中的一些输出函数,为了使用crt_printf,需要在程序中包含msvcrt.inc头文件,并将msvcrt.lib库作为链接器参数之一。然后,可以使用crt_printf宏来输出格式化的文本信息到控制台或文件中。

下面是一个简单的使用crt_printf的示例程序:

  .386
  .model flat, stdcall
  
  include msvcrt.inc
  includelib msvcrt.lib
  
.data
  PrintText db "EAX=%d;EBX=%d;EDX=%d | InPut ->: ",0
  ScanFomat db "%s",0
  PrintTemp db ?
.code
  main PROC
    mov eax,10
    mov ebx,20
    mov ecx,30
    invoke crt_printf,addr PrintText,eax,ebx,ecx        ; 打印提示内容
    invoke crt_scanf, addr ScanFomat, addr PrintTemp    ; 输入内容并接收参数
    invoke crt_printf, addr PrintTemp                   ; 输出输入的内容
    ret
  main ENDP
END main
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第Ο章 写在前面...................................................................................................................2 第一章汇编语言简介.............................................................................................................3 第二章认识处理器.................................................................................................................4 2.1 寄存器........................................................................................................................4 2.2 使用寄存器................................................................................................................6 第三章操作内存...................................................................................................................12 3.1 实模式......................................................................................................................12 3.2 保护模式..................................................................................................................16 3.3 操作内存..................................................................................................................19 3.4 串操作......................................................................................................................21 3.5 关于保护模式中内存操作的一点说明.................................................................22 3.6 堆栈.........................................................................................................................23 本章小结.........................................................................................................................25 第四章利用子程序与中断...................................................................................................25 4.1 子程序......................................................................................................................25 4.2 中断..........................................................................................................................31 第五章编译优化概述...........................................................................................................34 5.1 循环优化:强度削减和代码外提.........................................................................36 5.2 局部优化:表达式预计算和子表达式提取.........................................................37 5.3 全局寄存器优化.....................................................................................................38 5.4 x86体系结构上的并行最大化和指令封包..........................................................40 5.5 存储优化..................................................................................................................42 第六章 Linux X86汇编程序设计........................................................................................46 6.1编译和链接...............................................................................................................46 6.2基本示例...................................................................................................................46 第七章 X86汇编指令集汇总...............................................................................................47 一.数据传输指令............................................................................................................47 二、算术运算指令.........................................................................................................49 三、逻辑运算指令.........................................................................................................49 四、串指令.....................................................................................................................50 五、程序转移指令.........................................................................................................50 六、伪指令.....................................................................................................................52 七、寄存器.....................................................................................................................52 八、位操作指令,处理器控制指令.............................................................................52 九、FPU instructions......................................................................................................54 第八章 GCC内联汇编基础..................................................................................................54 1. GCC汇编格式...........................................................................................................55 2.内联汇编基本形式......................................................................................................56 3. 扩展形式内联汇编....................................................................................................56 4. 深入constra................................................................................................................59 5.结束语..........................................................................................................................63
第1章 基础知识 1.1 机器语言 1.2 汇编语言的产生 1.3 汇编语言的组成 1.4 存储器 1.5 指令和数据 1.6 存储单元 1.7 CPU对存储器的读写 1.8 地址总线 1.9 数据总线 1.10 控制总线. 1.11 内存地址空间(概述) 1.12 主板 1.13 接口卡 1.14 各类存储器芯片 1.15 内存地址空间 第2章 寄存器 2.1 通用寄存器 2.2 字在寄存器中的存储 2.3 几条汇编指令 2.4 物理地址 2.5 16位结构的CPU 2.6 8086CPU给出物理地址的方法 2.7 “段地址x16+偏移地址=物理地址”的本质含义 2.8 段的概念 2.9 段寄存器 2.10 CS和IP 2.11 修改CS、IP的指令 2.12 代码段 实验1 查看CPU和内存,用机器指令和汇编指令编程 第3章 寄存器(内存访问) 3.1 内存中字的存储 3.2 DS和[address] 3.3 字的传送 3.4 mov、add、sub指令 3.5 数据段 3.6 栈 3.7 CPU提供的栈机制. 3.8 栈顶超界的问题 3.9 push、pop指令 3.10 栈段 实验2 用机器指令和汇编指令编程 第4章 第—个程序 4.1 —个源程序从写出到执行的过程 4.2 源程序 4.3 编辑源程序 4.4 编译 4.5 连接 4.6 以简化的方式进行编译和连接. 4.7 1.exe的执行 4.8 谁将可执行文件中的程序装载进入内存并使它运行? 4.9 程序执行过程的跟踪 实验3 编程、编译、连接、跟踪 第5章 [BX]和loop指令 5.1 [BX] 5.2 Loop指令 5.3 在Debug中跟踪用loop指令实现的循环程序 5.4 Debug和汇编编译器masm对指令的不同处理 5.5 loop和[bx]的联合应用 5.6 段前缀 5.7 —段安全的空间 5.8 段前缀的使用 实验4 [bx]和loop的使用 第6章 包含多个段的程序 6.1 在代码段中使用数据 6.2 在代码段中使用栈 6.3 将数据、代码、栈放入不同的段 实验5 编写、调试具有多个段的程月 第7章 更灵活的定位内存地址的方法 7.1 and和or指令. 7.2 关于ASCII码 7.3 以字符形式给出的数据 7.4 大小写转换的问题 7.5 [bx+idata]. 7.6 用[bx+idata]的方式进行数组的处理 7.7 SI和DI. 7.8 Lbx+si]和[bx+di] 7.9 [bx+si+idata]和[bx+di+idata] 7.10 不同的寻址方式的灵活应用 实验6 实践课程中的程序 第8章 数据处理的两个基本问题 8.1 bx、Sl、di币口bp 8.2 机器指令处理的数据在什么地方 8.3 汇编语言中数据位置的表达 8.4 寻址方式 8.5 指令要处理的数据有多长 8.6 寻址方式的综合应用 8.7 div指令 8.8 伪指令dd. 8.9 dUp 实验7 寻址方式在结构化数据访问中的应用 第9章 转移指令的原理 9.1 操作符offset 9.2 jmp指令 9.3 依据位移进行转移的jmp指令. 9.4 转移的目的地址在指令中的jmp指令 9.5 转移地址在寄存器中的jmp指令. 9.6 转移地址在内存中的jmp指令. 9.7 jcxz指令 9.8 loop指令 9.9 根据位移进行转移的意义 9.10 编译器对转移位移超界的检测 实验8 分析—个奇怪的程序 实验9 根据材料编程 第10章 CALL和RET指令 10.1 ret和retf. 10.2 call指令 10.3 依据位移进行转移的call指令 10.4 转移的目的地址在指令中的call指令 10.5 转移地址在寄存器中的call指令 10.6 转移地址在内存中的call指令. 10.7 call和ret的配合使用 10.8 mul指令 10.9 模块化程序设计 10.10 参数和结果传递的问题 10.11 批量数据的传递 10.12 寄存器冲突的问题 实验10 编写子程序 课程设计1 第11章 标志寄存器 11.1 ZF标志 11.2 PF标志 11.3 SF标志 11.4 CF标志 11.5 0F标志 …… 第12章 内中断 第13章 int指令 第14章 端口 第15章 外中断 第16章 直接定址表 第17章 使用BIOS进行键盘输入和磁盘读写
第1章 基础知识   1.1 机器语言   1.2 汇编语言的产生   1.3 汇编语言的组成   1.4 存储器   1.5 指令和数据   1.6 存储单元   1.7 CPU对存储器的读写   1.8 地址总线   1.9 数据总线   1.10 控制总线   1.11 内存地址空间(概述)   1.12 主板   1.13 接口卡   1.14 各类存储器芯片   1.15 内存地址空间  第2章 寄存器  2.1 通用寄存器         2.2 字在寄存器中的存储     2.3 几条汇编指令        2.4 物理地址          2.5 16位结构的CPU       2.6 8086cPu给出物理地址的方法 2.7 “段地址xl6+偏移地址=物理地址”的本质含义         2.8 段的概念          2.9 段寄存器          2.10 CS和IP          2.11 修改CS、IP的指令     2.12 代码段          实验1 查看CPU和内存,用机器指令和汇编指令编程    第3章 寄存器(内存访问)    3.1 内存中字的存储      3.2 DS 31:1[address]         3.3 字的传送         3.4 ITIOV、add、sub指令    3.5 数据段          3.6 栈                3.7 CPU提供的栈机制     3.8 栈顶超界的问题       3.9 puSh、pop指令       3.10 栈段           实验2 用机器指令和汇编指令编程  第4章 第一个程序          4.1 一个源程序从写出到执行的过程  4.2 源程序             4.3 编辑源程序           4.4 编译              4.5 连接              4.6 以简化的方式进行编译和连接   4.7 1.exe的执行           4.8 谁将可执行文件中的程序装载进入内存并使它运行?        4.9 程序执行过程的跟踪       实验3 编程、编译、连接、跟踪   第5章 【BX】和loop指令       5.1 【BX】              5.2 Loop指令            5.3 在Debu9中跟踪用loop指令实现酮循环程序            5.4 Debu9和汇编编译器masm对指令的不同处理         5.5 loop和【bx】的联合应用     …… 第3章 寄存器(内存访问)  第4章 第一个程序  第5章 [BX]和loop指令  第6章 包含多个段的程序  第7章 更灵活的定位内存地址的方法  第8章 数据处理的两个基本问题  第9章 转移指令的原理  第10章 CALL和RET指令  第11章 标志寄存器  第12章 内中断  第13章 int指令  第14章 端口  第15章 外中断  第16章 直接定址表  第17章 使用BIOS进行键盘输入和磁盘读写  综合研究  附注
中文名: 80x86汇编语言程序设计教程 版本: [PDF] 发行时间: 1998年 地区: 大陆 简介: 本书分为三部分。第一部分是基础部分,以8086/8088为背景,以DOS和PC兼容机为软硬件平台,以MASM和TASM为汇编器,介绍汇编语言的有关概念,讲解汇编语言程序设计技术。第二部分是提高部分,以80386为背景,以新一代微处理器Pentium为目标,细致和通俗地介绍了保护方式下的有关概念,系统和详细地讲解了保护方式下的编程技术,真实和生动地展示了保护方式下的编程细节。第三部分是上机实验指导。 本书的第一部分适合初学者,可作为学习汇编语言程序设计的教材。本书的第二部分适合已基本掌握8086/8088汇编语言的程序员,可作为学习保护方式编程技术的教材或参考书,也可作为其他人员了解高档微处理器和保护方式编程技术的参考书,还可作为程序员透彻地了解Windows程序设计技术的参考书。 第一部分 基础部分 第1章 绪论 1.1 汇编语言概述 1.1.1 汇编语言 1.1.2 汇编语言的特点 1.1.3 恰当地使用汇编语言 1.2 数据的表示和类型 1.2.1 数值数据的表示 1.2.2 非数值数据的表示 1.2.3 基本数据类型 1.3 Intel系列CPU简介 1.3.1 8位微处理器 1.3.2 16位微处理器 1.3.3 32位微处理器 1.3.4 Pentium和Pentium Pro 1.4 习题 第2章 8086/8088寻址方式和指令系统 2.1 8086/8088寄存器组 2.1.1 8086/8088 CPU寄存器组 2.1.2 标志寄存器 2.2 存储器分段和地址的形成 2.2.1 存储单元的地址和内容 2.2.2 存储器的分段 2.2.3 物理地址的形成 2.2.4 段寄存器的引用 2.3 8086/8088的寻址方式 2.3.1 立即寻址方式 2.3.2 寄存器寻址方式 2.3.3 直接寻址方式 2.3.4 寄存器间接寻址方式 2.3.5 寄存器相对寻址方式 2.3.6 基址加变址寻址方式 2.3.7 相对基址加变址寻址方式 2.4 8086/8088指令系统 2.4.1 指令集说明 2.4.2 数据传送指令 2.4.3 堆栈操作指令 2.4.4 标志操作指令 2.4.5 加减运算指令 2.4.6 乘除运算指令 2.4.7 逻辑运算和移位指令 2.4.8 转移指令 2.5 习题 第3章 汇编语言及其程序设计初步 3.1 汇编语言的语句 3.1.1 语句的种类和格式 3.1.2 数值表达式 3.1.3 地址表达式 3.2 变量和标号 3.2.1 数据定义语句 3.2.2 变量和标号 3.3 常用伪指令语句和源程序组织 3.3.1 符号定义语句 3.3.2 段定义语句 3.3.3 汇编语言源程序的组织 3.4 顺序程序设计 3.4.1 顺序程序举例 3.4.2 简单查表法代码转换 3.4.3 查表法求函数值 3.5 分支程序设计 3.5.1 分支程序举例 3.5.2 利用地址表实现多向分支 3.6 循环程序设计 3.6.1 循环程序举例 3.6.2 多重循环程序举例 3.7 习题 第4章 子程序设计和DOS功能调用 4.1 子程序设计 4.1.1 过程调用和返回指令 4.1.2 过程定义语句 4.1.3 子程序举例 4.1.4 子程序说明信息 4.1.5 寄存器的保护与恢复 4.2 主程序与子程序间的参数传递 4.2.1 利用寄存器传递参数 4.2.2 利用约定存储单元传递参数 4.2.3 利用堆栈传递参数 4.2.4 利用CALL后续区传递参数 4.3 DOS功能调用及应用 4.3.1 DOS功能调用概述 4.3.2 基本I/O功能调用 4.3.3 应用举例 4.4 磁盘文件管理及应用 4.4.1 DOS磁盘文件管理功能调用 4.4.2 应用举例 4.5 子程序的递归和重入 4.5.1 递归子程序 4.5.2 可重入子程序 4.6 习题 第5章 输入输出与中断 5.1输 入和输出的基本概念 5.1.1 I/O端口地址和I/O指令 5.1.2 数据传送方式 5.1.3 存取RT/CMOS RAM 5.2 查询方式传送数据 5.2.1 查询传送方式 5.2.2 读实时钟 5.2.3 查询方式打印输出 5.3 中断 5.3.1 中断和中断传送方式 5.3.2 中断向量表 5.3.3 中断响应过程 5.3.4 外部中断 5.3.5 内部中断 5.3.6 中断优先级和中断嵌套 5.3.7 中断处理程序的设计 5.4 基本输入输出系统BIOS 5.4.1 基本输入输出系统BIOS概述 5.4.2 键盘输入 5.4.3 显示输出 5.4.4 打印输出 5.5 软中断处理程序举例 5.5.1 打印I/O程序 5.5.2 时钟显示程序 5.6 习题 第6章 简单应用程序的设计 6.1 字符串处理 6.1.1 字符串操作指令 6.1.2 重复前缀 6.1.3 字符串操作举例 6.2 十进制数算术运算调整指令及应用 6.2.1 组合BCD码的算术运算调整指令 6.2.2 未组合BCD码的算术运算调整指令 6.2.3 应用举例 6.3 DOS程序段前缀和特殊情况处理程序 6.3.1 DOS程序段前缀PSP 6.3.2 对Ctrl+C键和Ctrl+Break键的处理 6.4 TSR程序设计举例 6.4.1 驻留的时钟显示程序 6.4.2 热键激活的TSR程序 6.5 习题 第7章 高级汇编语言技术 7.1 结构和记录 7.1.1 结构 7.1.2 记录 7.2 宏 7.2.1 宏指令的定义和使用 7.2.2 宏指令的用途 7.2.3 宏指令中参数的使用 7.2.4 特殊的宏运算符 7.2.5 宏与子程序的区别 7.2.6 与宏有关的伪指令 7.2.7 宏定义的嵌套 7.3 重复汇编 7.3.1 伪指令REPT 7.3.2 伪指令IRP 7.3.3 伪指令IRPC 7.4 条件汇编 7.4.1 条件汇编伪指令 7.4.2 条件汇编与宏结合 7.5 源程序的结合 7.5.1 源程序的结合 7.5.2 宏库的使用 7.6 习题 第8章 模块化程序设计技术 8.1 段的完整定义 8.1.1 完整的段定义 8.1.2 关于堆栈段的说明 8.1.3 段组的说明和使用 8.2 段的简化定义 8.2.1 存储模型说明伪指令 8.2.2 简化的段定义伪指令 8.2.3 存储模型说明伪指令的隐含动作 8.3 模块间的通信 8.3.1 伪指令PUBLIC和伪指令EXTRN 8.3.2 模块间的转移 8.3.3 模块间的信息传递 8.4 子程序库 8.4.1 子程序库 8.4.2 建立子程序库 8.4.3 使用举例 8.5 编写供Turbo C调用的函数 8.5.1 汇编格式的编译结果 8.5.2 汇编模块应该遵守的约定 8.5.3 参数传递和寄存器保护 8.5.4 举例 8.6 习题 第二部分 提高部分 第9章 80386程序设计基础 9.1 80386寄存器 9.1.1 通用寄存器 9.1.2 段寄存器 9.1.3 指令指针和标志寄存器 9.2 80386存储器寻址 9.2.1 存储器寻址基本概念 9.2.2 灵活的存储器寻址方式 9.2.3 支持各种数据结构 9.3 80386指令集 9.3.1 数据传送指令 9.3.2 算术运算指令 9.3.3 逻辑运算和移位指令 9.3.4 控制转移指令 9.3.5 串操作指令 9.3.6 高级语言支持指令 9.3.7 条件字节设置指令 9.3.8 位操作指令 9.3.9 处理器控制指令 9.4 实方式下的程序设计 9.4.1 说明 9.4.2 实例 9.5 习题 第10章 保护方式下的80386及其编程 10.1 保护方式简述 10.1.1 存储管理机制 10.1.2 保护机制 10.2 分段管理机制 10.2.1 段定义和虚拟地址到线性地址转换 10.2.2 存储段描述符 10 2.3 全局和局部描述符表 10.2.4 段选择子 10.2.5 段描述符高速缓冲寄存器 10.3 80386控制寄存器和系统地址寄存器 10.3.1 控制寄存器 10 3.2 系统地址寄存器 10.4 实方式与保护方式切换实例 10.4.1 演示实方式和保护方式切换的实例(实例一) 10.4.2 演示32位代码段和16位代码段切换的实例(实例二) 10.5 任务状态段和控制门 10.5.1 系统段描述符 10.5.2 门描述符 10.5.3 任务状态段 10.6 控制转移 10.6.1 任务内无特权级变换的转移 10.6.2 演示任务内无特权级变换转移的实例(实例三) 10.6.3 任务内不同特权级的变换 10.6.4 演示任务内特权级变换的实例(实例四) 10.6.5 任务切换 10.6.6 演示任务切换的实例(实例五) 10.7 80386的中断和异常 10.7.1 80386的中断和异常 10.7.2 异常类型 10.7.3 中断和异常的转移方法 10.7.4 演示中断处理的实例(实例六) 10.7.5 演示异常处理的实例(实例七) 10.7.6 各种转移途径小结 10.8 操作系统类指令 10.8.1 实方式和任何特权级下可执行的指令 10.8.2 实方式及特权级0下可执行的指令 10 8.3 只能在保护方式下执行的指令 10.8.4 显示关键寄存器内容的实例(实例八) 10.8.5 特权指令 10.9 输入/输出保护 10.9.1 输入/输出保护 10.9.2 重要标志保护 10.9.3 演示输入/输出保护的实例(实例九) 10.10 分页管理机制 10.10.1 存储器分页管理机制 10.10.2 线性地址到物理地址的转换 10.10.3 页级保护和虚拟存储器支持 10.10.4 页异常 10.10.5 演示分页机制的实例(实例十) 10.11 虚拟8086方式 10.11.1 V86方式 10.11.2 进入和离开V86方式 10.11.3 演示进入和离开V86方式的实例(实例十一) 10.11.4 V86方式下的敏感指令 10.12 习题 第11章 80486及Pentium程序设计基础 11.1 80486程序设计基础 11.1.1 寄存器 11.1.2 指令系统 11.1.3 片上超高速缓存 11.2 80486对调试的支持 11 2.1 调试寄存器 11.2.2 演示调试故障/陷阶的实例 11.3 Pentium程序设计基础 11.3.1 寄存器 11.3.2 指令系统 11.3.3 处理器的识别 11.3.4 片上超高速缓存 11.4 基于Pentium的程序优化技术 11.4.1 流水线优化技术 11.4.2 分支优化技术 11.4.3 超高速缓存代化技术 11.5 习题 第三部分 上机实验指导 第12章 实验指导 12.1 实验的一般步骤 12.2 汇编器和连接器的使用 12.2.1 MASM的使用 12.2.2 LINK的使用 12.2.3 TASM的使用 12.2.4 TLINK的使用 12.3 调试器DEBUG的使用 12.3.1 启动和退出DEBUG 12.3.2 命令一览 12.3.3 利用DEBUG调试程序 12.4 Turbo Debugger的使用 12.4.1 启动和退出TD 12.4.2 利用TD调试汇编程序
根据引用中的错误信息,ImportError: liblua5.1.so: cannot open shared object file: No such file or directory,这个错误是由于缺少liblua5.1.so文件导致的。根据引用的建议,您可以尝试安装liblua5.1-0-dev来解决这个问题。您可以执行以下命令来安装该库: sudo apt install liblua5.1-0-dev 如果安装过程中出现其他错误,您可以尝试执行以下命令来修复依赖关系并重新安装: apt --fix-broken install 这样应该能够解决缺少liblua5.1.so文件的问题。希望对您有帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [nginx出现 liblua5.1.so.0: cannot open shared object file:](https://blog.csdn.net/iohappyoi/article/details/117767608)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [rpm: error while loading shared libraries: libgcc_s.so.1: cannot open shared object file: No such fi...](https://blog.csdn.net/weixin_34392843/article/details/86123500)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微软技术分享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值