x86汇编语言实践(2)

时间:2021-11-10 13:03:23

0 写在前面

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

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

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

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

1 十进制输入输出的乘法练习

1-1 练习要点

  • 输入输出中断调用练习
  • 宏练习
  • 子程序编写与调用

1-2 实现思路

  • 数据区使用byte类型存放两个十进制乘数NUM1和NUM2
  • 输入采用宏GETNUM实现,从百位读到个位,调用乘法宏MULTI计算出NUM1和NUM2的值
  • 调用乘法宏MULTI计算出结果,并保存到RESULT,以便debug调试
  • 调用OUTPUT子程序进行输出,输出从RESULT中保存的结果
  • 其他对于输入输出的控制对输出结果进行改进

1-3 代码实现

 STACK     SEGMENT    PARA    STACK
DW 100H DUP(?)
STACK ENDS DATA SEGMENT PARA
NUM1 DB ?
NUM2 DB ?
RESULT DW ?
DATA ENDS CODE SEGMENT PARA
ASSUME CS:CODE,DS:DATA,SS:STACK GETNUM MACRO
MOV AH,
INT 21H
SUB AL,30H
ENDM MULTI MACRO N1,N2
MOV AL,N1
MOV BL,N2
MUL BL
ENDM DIVIDE MACRO N1,N2
MOV AX,N1
MOV BX,N2
XOR DX,DX
DIV BX
ENDM DISPNUM MACRO
PUSH DX
MOV AH,
MOV DL,AL
ADD DL,30H
INT 21H
POP DX
ENDM INPUT MACRO NUM
GETNUM
MULTI AL,
MOV NUM,AL
GETNUM
MULTI AL,
ADD NUM,AL
GETNUM
ADD NUM,AL
ENDM NEWLINE MACRO
MOV AH,
MOV DL,0DH
INT 21H
MOV AH,
MOV DL,0AH
INT 21H
ENDM OUTPUT PROC
DIVIDE AX,
DISPNUM
DIVIDE DX,
DISPNUM
DIVIDE DX,
DISPNUM
DIVIDE DX,
DISPNUM
MOV AL,DL
DISPNUM
RET
OUTPUT ENDP MAIN PROC FAR
MOV AX,DATA
MOV DS,AX
;get num1
INPUT NUM1
;getchar
GETNUM
XOR AX,AX
;get num2
INPUT NUM2
;num1 * num2
MULTI NUM1,NUM2
MOV RESULT,AX
;newline
NEWLINE
;output result
MOV AX,RESULT
CALL OUTPUT EXIT: MOV AX,4C00H
INT 21H
MAIN ENDP CODE ENDS
END MAIN

1-4 实现效果截图

x86汇编语言实践(2)

经验证,发现输出结果符合预期。

2 字符串操作与跳转表练习

2-1 练习要点

  • 字符串的操作,包括:字符串的拼接、比较、查找
  • 子程序调用与宏
  • 跳转表的使用

2-2 重点难点

  • 子程序调用需要对子程序中使用到的变量进行压栈处理,以免变量污染
  • 字符串操作通常都需要对ES:DI和DS:SI进行初始化
  • 宏的内容不能有标签

2-3 实现思路

  • 首先为输入和输出单独编写子程序,程序主体采用跳转表实现
  • 为每一个条件单独编写一个子程序,有4个条件,因此共需编写4个子程序

2-4 代码实现

 STACK     SEGMENT    PARA    STACK
DW 100H DUP(?)
STACK ENDS DATA SEGMENT PARA
LEN EQU
MSG1 DB 'INPUT OPRAND:',,,'$' ;THE MSG TO OUTPUT
MSG2 DB 'INPUT STRING 1:',,,'$'
MSG3 DB 'INPUT STRING 2:',,,'$'
MSG4 DB '<','$'
MSG5 DB '=','$'
MSG6 DB '>','$'
MSG7 DB 'S3=','$'
MSG8 DB 'INPUT A CHAR:',,,'$'
MSG9 DB 'CHAR FOUND IN STR1!',,,'$'
MSG10 DB 'CHAR NOT FOUND IN STR1!',,,'$'
STR1 DB LEN-
DB ?
DB LEN DUP(?)
STR2 DB LEN-
DB ?
DB LEN DUP(?)
STR3 DB LEN-
DB ?
DB LEN DUP(?)
CHAR DB ?
OP DB ? ;THE OPRAND USER INPUT
DATA ENDS CODE SEGMENT PARA
ASSUME CS:CODE,DS:DATA,SS:STACK HINT MACRO MSG
LEA DX,MSG ;OUTPUT MSG1
MOV AH,09H
INT 21H
ENDM GETOP MACRO
MOV AH,
INT 21H
SUB AL,30H
MOV OP,AL
ENDM NEWLINE MACRO
PUSH AX
PUSH DX
MOV AH,
MOV DL,0DH
INT 21H
MOV AH,
MOV DL,0AH
INT 21H
POP DX
POP AX
ENDM GETCHAR MACRO
MOV AH,
INT 21H
MOV CHAR,AL
ENDM GETSTR1 PROC
MOV DX,OFFSET STR1
MOV AH,0AH
INT 21H
MOV CL,STR1+
XOR CH,CH
MOV SI,OFFSET STR1+
LP1: INC SI
LOOP LP1
MOV BYTE PTR [SI],'$'
RET
GETSTR1 ENDP GETSTR2 PROC
MOV DX,OFFSET STR2
MOV AH,0AH
INT 21H
MOV CL,STR2+
XOR CH,CH
MOV SI,OFFSET STR2+
LP2:INC SI
LOOP LP2
MOV BYTE PTR [SI],'$'
RET
GETSTR2 ENDP STRCAT PROC
PUSH AX
CLD
CAT_LP1:LODSB
STOSB
CMP AL,
JNZ CAT_LP1
POP AX
RET
STRCAT ENDP P2_PUTEND PROC
MOV CL,STR1+ ;SET CX TO LEN FOR LOOP
ADD CL,STR2+
XOR CH,CH
MOV SI,OFFSET STR3+ ;GET ACTUAL STRING
PLP2: INC SI
LOOP PLP2
MOV BYTE PTR [SI],'$' ;PUT END TO STRING
RET
P2_PUTEND ENDP
;STRCMP
P1 PROC
PUSH CX
CLD
PUSH SI
MOV CX,
SLP1: LODSB
CMP AL,00H
JZ SLP1_1
INC CX
JMP SHORT SLP1
SLP1_1: POP SI
REPE CMPSB
HINT STR1+
JA SL1
JB SL2
HINT MSG5
MOV AL,
JMP SHORT RETURN
SL1: HINT MSG6
MOV AL,
JMP SHORT RETURN
SL2: HINT MSG4
MOV AL,
RETURN: HINT STR2+
POP CX
RET
P1 ENDP
;STRCAT(S1,S2)+STRCPY(S3,S1)
P2 PROC
;STRCAT(S1,S2)
PUSH AX
MOV SI,OFFSET STR2+
MOV CL,STR1+
XOR CH,CH
MOV DI,OFFSET STR1+
CATLP1: INC DI
LOOP CATLP1
CALL STRCAT
;STRCPY(S3,S1)
MOV SI,OFFSET STR1+
MOV DI,OFFSET STR3+
CALL STRCAT
CALL P2_PUTEND
HINT MSG7
HINT STR3+
POP AX
RET
P2 ENDP
;STRCAT(S2,S1)+STRCPY(S3,S2)
P2_2 PROC
;STRCAT(S2,S1)
PUSH AX
MOV SI,OFFSET STR1+
MOV CL,STR2+
XOR CH,CH
MOV DI,OFFSET STR2+
CATLP2: INC DI
LOOP CATLP2
CALL STRCAT
;STRCPY(S3,S1)
MOV SI,OFFSET STR2+
MOV DI,OFFSET STR3+
CALL STRCAT
CALL P2_PUTEND
HINT MSG7
HINT STR3+
POP AX
RET
P2_2 ENDP
;STRFIND
P3 PROC
HINT MSG8
GETCHAR
NEWLINE
MOV DI,OFFSET STR1+
MOV CL,STR1+
XOR CH,CH
MOV AL,CHAR
CLD
REPNZ SCASB
JZ FOUND
HINT MSG10
JMP P3_RETURN
FOUND: HINT MSG9
P3_RETURN:RET
P3 ENDP
;SRTCMP+STRCAT+STRCPY
P4 PROC
MOV SI,OFFSET STR1+
MOV DI,OFFSET STR2+
CALL P1
NEWLINE
CMP AL,
JNE LA41
CALL P2
JMP CONTINUE4
LA41: CMP AL,
JNE LA42
CALL P2
JMP CONTINUE4
LA42: CMP AL,
JNE CONTINUE4
CALL P2_2
CONTINUE4:
RET
P4 ENDP SWITCH PROC
CMP OP,
JNE LA1
MOV SI,OFFSET STR1+
MOV DI,OFFSET STR2+
CALL P1
JMP CONTINUE
LA1: CMP OP,
JNE LA2
CALL P2
JMP CONTINUE
LA2: CMP OP,
JNE LA3
CALL P3
JMP CONTINUE
LA3: CMP OP,
JNE LAN
CALL P4
JMP CONTINUE
LAN: HINT MSG3
CONTINUE:RET
SWITCH ENDP MAIN PROC FAR
MOV AX,DATA
MOV DS,AX
MOV ES,AX ;input str1
HINT MSG2
CALL GETSTR1
NEWLINE
;input str2
HINT MSG3
CALL GETSTR2
NEWLINE
;input op
HINT MSG1
GETOP
NEWLINE
;SWITCH OP
CALL SWITCH EXIT: MOV AX,4C00H
INT 21H
MAIN ENDP CODE ENDS
END MAIN

2-5 运行结果

2-5-1 操作类型为1,即比较str1和str2的字典序

x86汇编语言实践(2)

2-5-2 操作类型为2,即将str2拼接到str1后,并将整个串拷贝至str3

x86汇编语言实践(2)

2-5-3 操作类型为3,即再输入一个字符char,判断char是否属于str1

x86汇编语言实践(2)

2-5-4 操作类型为4,即比较str1和str2的字典序按降序进行拼接,并拷贝到str3

x86汇编语言实践(2)

显然,运行结果符合预期。

3 字符串按字典序排序

3-1 练习要点

  • 字符串的操作,LODSB,STOSB,CMPSB,REPE等等
  • 各个字符串操作指令对PSW和SI,DI的影响
  • 子程序调用与宏
  • 冒泡排序算法
  • 复杂程序的调试

3-2 重点难点

  • 冒泡排序
  • 宏和子程序的编写时必须注意堆栈的维护,用到的变量必须压栈处理
  • 字符串交换的逻辑
  • 操作字符串的子程序必须对SI,DI压栈保存,因为会隐式修改SI,DI

3-3 实现思路

  • 调用输出子程序输出原单词表
  • 调用排序子程序
  • 调用输出子程序输出排序后的单词表

3-4 代码实现

  • 输出子程序中每输出一个单词,就将SI增加STR_LEN,循环输出TABLE_LEN次
  • 排序子程序采用冒泡,在相邻两单词比较时,将当前单词置于DS:SI,相邻下一单词置于ES:DI,并比较其字典序,若当前单词字典序较大,则调用交换子程序,并将标志位BX置0,表示这一趟外层循环排序有调整。当一趟外层循环排序无调整,则表示当前单词表有序,即可退出排序子程序。
  • 比较子程序要注意对SI的维护,以及REPE CMPSB的含义:当CX≠0且ZF=1时执行CMPSB,CMPSB返回SI和DI的比较结果,并将二者分别+1,CX为提前计算好的两字符串的长度。含义是,当两字符串的前若干位字符相同时,就继续向后比较,直到比较到长度的结尾,或出现不同时结束。后接JA,JB指令,根据比较结果进行跳转与执行相关逻辑。
  • 交换S1,S2的逻辑:S1->TMP , S2->S1 , TMP->S2。
 STACK     SEGMENT    PARA    STACK
DW 100H DUP(?)
STACK ENDS DATA SEGMENT PARA
TABLE_LEN EQU
STR_LEN EQU
TABLE DB 'QIQI',20H,,'$'
DB 'CHEN',20H,,'$'
DB 'XIAN',20H,,'$'
DB 'QIQJ',20H,,'$'
DB 'XHAN',20H,,'$'
DB 'XIBN',20H,,'$'
DB 'XHQI',20H,,'$'
DB 'LOVE',20H,,'$'
DB 'SURE',20H,,'$'
TEMP DB STR_LEN DUP(?)
NEW_LINE DB 0DH,0AH,'$'
DATA ENDS CODE SEGMENT PARA
ASSUME CS:CODE,DS:DATA,SS:STACK NEWLINE MACRO
PUSH DX
PUSH AX
MOV DX,OFFSET NEW_LINE
MOV AH,
INT 21H
POP AX
POP DX
ENDM OUTPUT PROC
PART1:
MOV CX,TABLE_LEN
MOV SI,OFFSET TABLE
LP1:
MOV DX,SI
MOV AH,
INT 21H
ADD SI,STR_LEN
LOOP LP1
NEWLINE
RET
OUTPUT ENDP COMP PROC
COMPARE:
PUSH SI
PUSH CX
CLD
PUSH SI
MOV CX,
SLP1:
LODSB
CMP AL,00H
JZ SLP1_1
INC CX
JMP SHORT SLP1
SLP1_1:
POP SI
REPE CMPSB
JA SL1
JB SL2
MOV AL, ;SI=DI
JMP SHORT RETURN
SL1:
MOV AL, ;SI>DI
JMP SHORT RETURN
SL2:
MOV AL, ;SI<DI
RETURN:
POP CX
POP SI
RET
COMP ENDP STRCPY PROC
STRING_COPY:
PUSH SI
PUSH DI
PUSH AX
CLD
CPY_LP1:
LODSB
STOSB
CMP AL,
JNZ CPY_LP1
POP AX
POP DI
POP SI
RET
STRCPY ENDP EXCHG PROC
EXCHANGE:
PUSH SI
PUSH DI MOV DI,OFFSET TEMP
CALL STRCPY MOV DI,SI
ADD SI,STR_LEN
CALL STRCPY MOV DI,SI
MOV SI,OFFSET TEMP
CALL STRCPY
POP DI
POP SI
RET
EXCHG ENDP SORT PROC
PART2:
MOV CX,TABLE_LEN
DEC CX
LP2:
MOV BX,
MOV SI,OFFSET TABLE
PUSH CX LP2_1:
MOV AX,SI
ADD AX,STR_LEN
MOV DI,AX
CALL COMP
CMP AL,
JBE CONTINUE
CALL EXCHG
MOV BX,
CONTINUE:
ADD SI,STR_LEN
LOOP LP2_1 POP CX
DEC CX
CMP BX,
JZ SORT_RETURN
JMP SHORT LP2
SORT_RETURN:
RET
SORT ENDP MAIN PROC FAR
MAIN_PART:
MOV AX,DATA
MOV DS,AX
MOV ES,AX
;DISPLAY ORIGIN TABLE
CALL OUTPUT
;SORT
CALL SORT
;DISPLAY ORDERED TABLE
CALL OUTPUT EXIT:
MOV AX,4C00H
INT 21H
MAIN ENDP CODE ENDS
END MAIN

3-5 运行结果

在DATA段预置字典如下图所示

x86汇编语言实践(2)

编译、链接并执行程序,得到结果如下,第一行为元单词表,第二行为排序后的单词表(按字典序升序)

x86汇编语言实践(2)

显然,运行结果符合预期。

x86汇编语言实践(2)的更多相关文章

  1. x86汇编语言实践(3)

    0 写在前面 为了更深入的了解程序的实现原理,近期我学习了IBM-PC相关原理,并手工编写了一些x86汇编程序. 在2017年的计算机组成原理中,曾对MIPS体系结构及其汇编语言有过一定的了解,考虑到 ...

  2. x86汇编语言实践(1)

    0 写在前面 为了更深入的了解程序的实现原理,近期我学习了IBM-PC相关原理,并手工编写了一些x86汇编程序. 在2017年的计算机组成原理中,曾对MIPS体系结构及其汇编语言有过一定的了解,考虑到 ...

  3. 进入保护模式(三)——《x86汇编语言:从实模式到保护模式》读书笔记17

    (十)保护模式下的栈 ;以下用简单的示例来帮助阐述32位保护模式下的堆栈操作 mov cx,00000000000_11_000B ;加载堆栈段选择子 mov ss,cx mov esp,0x7c00 ...

  4. VS2013的x86汇编语言开发环境配置

    转载:https://blog.csdn.net/infoworld/article/details/45085415 转载:https://blog.csdn.net/u014792304/arti ...

  5. 存储器的保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记20

    存储器的保护(三) 修改本章代码清单,使之可以检测1MB以上的内存空间(从地址0x0010_0000开始,不考虑高速缓存的影响).要求:对内存的读写按双字的长度进行,并在检测的同时显示已检测的内存数量 ...

  6. 存储器的保护(一)——《x86汇编语言:从实模式到保护模式》读书笔记18

    本文是原书第12章的学习笔记. 说句题外话,这篇博文是补写的,因为让我误删了,可恶的是CSDN的回收站里找不到! 好吧,那就再写一遍,我有坚强的意志.司马迁曰:“文王拘而演<周易>:仲尼厄 ...

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

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

  8. 进入保护模式(二)——《x86汇编语言:从实模式到保护模式》读书笔记14

    首先来段题外话:之前我发现我贴出的代码都没有行号,给讲解带来不便.所以从现在起,我要给代码加上行号.我写博客用的这个插入代码的插件,确实不支持自动插入行号.我真的没有找到什么好方法,无奈之下,只能按照 ...

  9. linux平台学x86汇编语言学习集合帖

    linux平台学x86汇编语言学习集合帖 linux平台学x86汇编(一):https://blog.csdn.net/shallnet/article/details/45543237 linux平 ...

随机推荐

  1. 坐标系统与投影变换及在ARCGIS中的应用

      首先提几个问题:是否有遇到坐标转换的问题?又是否有遇到投影转换的问题?坐标转换与投影转换有什么区别?下面看几个概念:1.地球椭球体( Ellipsoid,Spheroid)2.大地基准面( Geo ...

  2. RBAC类的方法

    rbac类的 方法 authenticate($map,$model='')方法 传入查询用户的条件和用户表的MODEL 返回数组包含用户的信息 saveAccessList($authId=null ...

  3. Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理

    Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理 本博文主要介绍 Laravel 框架中 Eloquent  对一对多关系的处理以及在 Laravel Administra ...

  4. Spring IOC之基于JAVA的配置

    基础内容:@Bean 和 @Configuration 在Spring中新的支持java配置的核心组件是 @Configuration注解的类和@Bean注解的方法. @Bean注解被用于表明一个方法 ...

  5. 什么是 stack?- 每天5分钟玩转 Docker 容器技术(111)

    什么是 stack ?在回答这个问题之前我们先回忆一下前面部署 WordPress 应用的过程: 首先创建 secret. 然后创建 MySQL service,这是 WordPress 依赖的服务. ...

  6. Scala actor的使用

    Actor 为什么需要Actor? Actor的本质即万物皆Actor, Actor之间只有发送消息这一种通信方式.例如,无论是管理员让工作者干活,还是工作者把成果交还给管理员,它们之间也要通过发送消 ...

  7. python 编译源文件

    背景 近期项目到了部署的阶段.由于项目后台和算法都是用Python "撸的",但是又不希望将源代码直接 "release" 到 “客户”哪里.于是开始思考... ...

  8. Anaconda安装及使用

    前言 在Linux系统上一般会预安装python,但有时候版本过低,通过apt或yum无法安装较新的python版本,只能通过编译python源码进行安装.然而通过源码安装会依赖大量的库,手动安装这些 ...

  9. javaScript drag对象进行拖拽使用详解

    目录 drag简介 兼容性 drag事件 拖拽流程 DataTransfer对象 drag拖放桌面文件 drag实例 小结 drag简介 HMTL5提供的支持原生拖拽的实现 兼容性如何? 桌面端的支持 ...

  10. 【webpack学习笔记】a01-基础构建

    webpack基于nodejs环境运行,首先确认已经安装了node.js. 基础构建流程 新建一个文件夹,这个就是你项目的根目录. 在命令行中使用npm init命令初始化npm,会得到一个 ==pa ...