• 8086 汇编小程序


    仅以此文记录我在Centos上使用DosBox写8086汇编小程序,不知为何DosBox总是会将我当前用户Logout,然后我必须重新登录的艰苦岁月……

    1:HelloWorld

    1. DATA SEGMENT
    2. str db 'Hello World$' ;要输出的字符串必须要以$结尾
    3. DATA ENDS
    4. CODE SEGMENT
    5. ASSUME CS:CODE,DS:DATA ;将CS和CODE,DS和DATA段建立联系
    6. START:
    7. MOV BX,DATA
    8. MOV DS,BX
    9. LEA DX,str
    10. MOV AH,9
    11. INT 21H
    12. MOV AH,4CH ;将控制权返回给终端。
    13. INT 21H
    14. CODE ENDS
    15. END START

    备注:
    1:
    MOV BX,DATA
    MOV DS,BX
    将数据段的值给DS寄存器,但是不能直接 MOV DS,DATA,因为mov操作中不允许将立即数给DS。
    2:LEA指令:将源操作数的地址移入目的操作数。
    LEA BX,Buffer
    源操作数:必须是一个存储器操作数
    目的操作数:16位通用寄存器
    3:mov AH,9 ;使用9号系统调用从DX中读取字符串输出
    int 21H; 产生系统中断。

    2:从键盘输入两个一位十进制数,计算两个数之和,并将结果在屏幕上显示出来。

    1. DATA SEGMENT
    2. INFOR1 DB 'Please Input the First Data(<10):$'
    3. INFOR2 DB 0AH,0DH,'Please Input the Second Data(<10):$' ; 0A 是 '\n' 0D 是 '\r',回车换行
    4. INFOR3 DB 0AH,0DH,'The Result is:$'
    5. DATA ENDS
    6. CODE SEGMENT
    7. ASSUME CS:CODE,DS:DATA
    8. START:
    9. MOV AX,DATA
    10. MOV DS,AX
    11. LEA DX,INFOR1 ;输出第一条提示语句
    12. MOV AH,09H
    13. INT 21H
    14. MOV AH,01H ;1号系统调用将字符输入至AL中。
    15. INT 21H
    16. SUB AL,30H ;输入的位ASCII码,所以减去48
    17. MOV BL,AL
    18. LEA DX,INFOR2
    19. MOV AH,09H
    20. INT 21H
    21. MOV AH,01H
    22. INT 21H
    23. SUB AL,30H
    24. XOR AH,AH ;将AH清空
    25. ADD AL,BL
    26. AAA ;加法ASCII码调整指令
    27. PUSH AX
    28. LEA DX,INFOR3
    29. MOV AH,09H
    30. INT 21H
    31. POP AX
    32. PUSH AX
    33. MOV DL,AH
    34. ADD DL,30H ;计算结束之后加上48输出。
    35. MOV AH,02H ;2号系统调用,输出单个字符,在汇编中想输出数字只能单个ASCII码的输出。
    36. INT 21H
    37. POP AX
    38. MOV DL,AL
    39. ADD DL,30H
    40. MOV AH,02H
    41. INT 21H
    42. MOV AH,4CH
    43. INT 21H
    44. CODE ENDS
    45. END START

    备注:
    1: AAA指令:加法ASCII码调整指令。

    MOV AX,0007H ;AL=07H AH=00H MOV BL,08H ;BL=08H ADD AL,BL ;AL=0FH AAA ;AL=05H AH=01H 

    3:编写一段程序比较两个字符串是否相同,相同输出MATCH!,不相同输出NO MATCH!

    思路:

    1. 先计算两个串长度,如果不同直接退出,相同执行第2步
    2. 挨个比较字符是否相同,若有不相同结束,直到比较结束全部相同
    3. 输出match
    1. DATA SEGMENT
    2. STR1 DB 'ABCDEFG$'
    3. N EQU $-STR1 ;给N赋值,$表示当前指令的地址,$-STR1表示当前位置到STR1头部的距离,也就是STR1的长度。
    4. STR2 DB 'BCDEFG$'
    5. M EQU $-STR2
    6. MESS DB 'NO MATCH!$'
    7. RIGHT DB 'MATCH!$'
    8. DATA ENDS
    9. CODE SEGMENT
    10. ASSUME CS:CODE,DS:DATA,ES:DATA
    11. BEGIN:
    12. MOV AX,DATA
    13. MOV DS,AX
    14. MOV AX,DATA
    15. MOV ES,AX
    16. MOV AL,N
    17. CMP AL,M ;比较长度是否相等,相等ZF=0,否则ZF=1
    18. JNZ EXIT ;JNZ:jump if not zero ,zero 指的是比较结果,而不是ZF标志位的值
    19. LEA SI,STR1
    20. LEA DI,STR2
    21. MOV CL,N
    22. MOV CH,0
    23. CLD
    24. REPE CMPSB ;挨个比较单个字符,如果有一个不等就跳EXIT
    25. JNZ EXIT
    26. LEA DX,RIGHT
    27. JMP OUT1
    28. EXIT:
    29. LEA DX,MESS
    30. OUT1:
    31. MOV AH,9
    32. INT 21H
    33. MOV AH,4CH
    34. INT 21H
    35. CODE ENDS
    36. END BEGIN

    备注:
    1:CMP指令:
    不影响两个操作数的原大小,影响的是状态标志位,如果相等,ZF=1。否则ZF=0

    2:JNZ指令的逻辑写出来就是下面这样

    JNZ(ZF == 0) { //如果ZF == 0 ,则跳转 } //如果ZF == 1,则不跳转

    4:汇编读写文件

    输入原文件名->将文件读入预先定义好的缓冲区->输入新的文件名->将缓冲区的内容写入新文件。

    (这部分代码是马辉完成的,我们共同做的汇编程序大赛http://blog.csdn.net/yangbodong22011/article/details/53716225,他负责文件读写部分,我负责加密解密算法部分)

    1. data segment
    2. filePath db 20,?,20 dup(?);存储原文件名称
    3. newFilePath db 10,?,10 dup(?),00 ;存储加密或者解密的文件的路径
    4. fileHandle db 2 dup(?);存储文件代号
    5. fileBuffer db 10000 dup(?);文件缓冲区
    6. fileInputTip db 'please input source file path:$';提示源文件路径
    7. newFileInputTip db 'please input new file path:$';提示新文件路径
    8. openErrorTip db 'open file error !!$';提示打开文件失败
    9. readErrorTip db 'read file error !!$' ;提示读文件失败
    10. fileCount db ? ;定义实际读取的字节数
    11. data ends
    12. code segment
    13. assume cs:code,ds:data
    14. start:
    15. mov ax,data
    16. mov ds,ax
    17. call openFile ;打开文件
    18. call readFile ;将文件读至缓冲区
    19. call closeFile ;关闭文件
    20. call createFile ;创建新文件
    21. call writeFile ;写文件
    22. call closeFile ;关闭文件
    23. call returnDos ;返回DOS
    24. ;***************
    25. ;打开文件
    26. openFile proc near
    27. ;9号功能调用,提示输入文件名
    28. mov dx,offset fileInputTip
    29. mov ah,9
    30. int 21h
    31. ;10号功能调用,将文件名存储在filePath中
    32. mov dx,offset filePath
    33. mov ah,10
    34. int 21h
    35. ;换行处理
    36. call nextLine
    37. ;取得键盘上输入的实际的个数
    38. lea bx,filePath+1
    39. ; 清空cx
    40. xor cx,cx
    41. ;将键盘上实际输入的个数送给cx
    42. mov cl,[bx]
    43. ;取得文件实际的存储路径
    44. lea bx,filePath+2
    45. ;处理enter的ascall码
    46. call findEnter
    47. ;系统调用,打开文件
    48. mov ah,3dh
    49. mov al,00
    50. lea dx,filePath+2
    51. int 21h
    52. ; 若CF1,打开失败
    53. jc openError
    54. ;若CF0,打开成功,获取返回的ax中的文件代号
    55. jmp getFileHandle
    56. getFileHandle:
    57. ;取得fileHandle的地址空间
    58. lea bx,fileHandle
    59. ;将文件代号保存在fileHandle中
    60. mov [bx],ax
    61. ret
    62. openError:
    63. ;9号功能调用,提示打开文件失败
    64. mov dx,offset openErrorTip
    65. mov ah,9
    66. int 21h
    67. ;返回dos
    68. call returnDos
    69. ret
    70. openFile endp
    71. ;***************
    72. ;***************
    73. ;读文件
    74. readFile proc near
    75. ;系统调用,读文件
    76. mov ah,3fh
    77. lea si,fileHandle
    78. mov bx,[si]
    79. mov cx,10000
    80. lea dx,fileBuffer
    81. int 21h
    82. ;cf1,读文件失败,cf0,读文件成功
    83. ;提示读取文件失败
    84. jc readError
    85. jmp getFileCount
    86. getFileCount:
    87. ;将实际读取的字节数放在fileCount中
    88. lea bx,fileCount
    89. mov [bx],ax
    90. ret
    91. readError:
    92. ;9号功能调用,提示读文件失败
    93. mov dx,offset readErrorTip
    94. mov ah,9
    95. int 21h
    96. ;返回dos
    97. call returnDos
    98. ret
    99. readFile endp
    100. ;***************
    101. ;***************
    102. ;换行处理
    103. nextLine proc near
    104. mov dl,0dh
    105. mov ah,2
    106. int 21h
    107. mov dl,0ah
    108. mov ah,2
    109. int 21h
    110. ret
    111. nextLine endp
    112. ;***************
    113. ;***************
    114. ;将回车所占的地址空间的值设为00h
    115. findEnter proc near
    116. next1:
    117. inc bx
    118. loop next1
    119. mov al,00h
    120. mov [bx],al
    121. ret
    122. findEnter endp
    123. ;***************
    124. ;***************
    125. ;返回dos
    126. returnDos proc near
    127. mov ah,4ch
    128. int 21h
    129. ret
    130. returnDos endp
    131. ;***************
    132. ;***************
    133. ;关闭文件
    134. closeFile proc near
    135. mov ah,3eh
    136. int 21h
    137. ret
    138. closeFile endp
    139. ;***************
    140. ;***************
    141. ;创建文件,cf0,返回文件代号,保存在ax中;cf1,创建失败
    142. createFile proc near
    143. create:
    144. ;9号功能调用,提示输入新的文件名加路径
    145. mov dx,offset newFileInputTip
    146. mov ah,9
    147. int 21h
    148. ;10号功能调用,将新文件名艺伎路径保存在newFilePath中
    149. mov dx,offset newFilePath
    150. mov ah,10
    151. int 21h
    152. ;换行处理
    153. call nextLine
    154. ;取得newFilePath缓冲区中实际输入的字符的个数
    155. lea bx,newFilePath+1
    156. ;清空cx
    157. xor cx,cx
    158. ;将newFilePath缓冲区实际存储的个数送给cx
    159. mov cl,[bx]
    160. ;判断是否输入
    161. cmp cx,00h
    162. ;如果输入的不为空,则跳转continue
    163. jnz continue
    164. ;如果输入的为空,则重新输入
    165. jmp create
    166. continue:
    167. ;取得实际的存储路径
    168. lea bx,newFilePath+2
    169. ;处理enter的ascall码
    170. call findEnter
    171. ;系统调用,创建文件
    172. mov ah,3ch
    173. mov cx,00
    174. lea dx,newFilePath+2
    175. int 21h
    176. ; 将文件代号保存在fileHandle中
    177. lea si,fileHandle
    178. mov [si],ax
    179. ret
    180. createFile endp
    181. ;***************
    182. ;***************
    183. ;向文件写数据
    184. writeFile proc near
    185. ;系统调用,写文件
    186. mov ah,40h
    187. lea si,fileHandle
    188. mov bx,[si]
    189. lea di,fileCount
    190. mov cx,[di]
    191. lea dx,fileBuffer
    192. int 21h
    193. ret
    194. writeFile endp
    195. ;***************
    196. code ends
    197. end start

    5:汇编生成随机数

    8086 定时器模式生成随机数

    1. ;***************
    2. ;获取随机数 范围1-8
    3. getRand:
    4. xor al,al
    5. mov ax, 0h; 间隔定时器
    6. out 43h,al; 将0送到43h端口
    7. in al, 40h; 将40h端口的数据送至al
    8. mov bl, 8 ;除8 得到范围为0-7
    9. div bl
    10. mov al, ah
    11. mov ah, 0
    12. inc al ; 加1 得到范围为1-8
    13. ret
    14. ;***************

    6:汇编生成1-N共N位不重复随机数

    例如生成1-8不重复的序列,比如 12435786或者43256718,结合上面生成随机数的程序完成如下。

    1. ;***************
    2. ;创建随机数并存入文件
    3. createRandNum:
    4. lea si,randNum1 ;randNum1是保存随机数串的字符串
    5. mov cx,8 ;设定需要产生的个数
    6. doRand:
    7. push cx
    8. createRandNumdo1: ;循环产生
    9. call getRand ;获得一个随机数
    10. xor di,di
    11. xor cx,cx
    12. lea di,randNum1
    13. mov cx,8
    14. createRandNumdo2: ;将新产生的数字和已经保存的比对
    15. mov bh,[di]
    16. cmp bh,al
    17. jz createRandNumdo1 ;如果出现重复就继续产生
    18. inc di
    19. loop createRandNumdo2
    20. mov bh,RandNum[0] ;保存目前一共产生的随机数个数
    21. add bh,1
    22. mov RandNum[0],bh
    23. cmp bh,9 ;如果为Num+1 就结束
    24. jz mRet
    25. mov [si],al
    26. inc si
    27. pop cx
    28. loop doRand
    29. ;***************
    30. ;获取随机数 范围1-8
    31. getRand:
    32. xor al,al
    33. mov ax, 0h; 间隔定时器
    34. out 43h,al; 将0送到43h端口
    35. in al, 40h; 将40h端口的数据送至al
    36. mov bl, 8 ;除8 得到范围为0-7
    37. div bl
    38. mov al, ah
    39. mov ah, 0
    40. inc al ; 加1 得到范围为1-8
    41. ret
    42. ;***************

    7:将一个db类型的每一位取出来保存进一个8个db大小的字符串。

    例如 A的二进制是01000001我们将它每一位分别保存进一个db,得到0 1 0 0 0 0 0 1 ,将其保存入temp1

    1. fetchBinary:
    2. xor dx,dx;
    3. lea si,temp1
    4. mov dl,[bx]
    5. mov dh,dl;
    6. and dh,10000000B ;先拿出最高位是不是1
    7. cmp dh,00H ;如果为0
    8. jz _1
    9. mov dh,01h ;如果不为0就置为1
    10. _1:
    11. mov [si],dh ;将dh的值也就是0给[si]
    12. inc si
    13. mov dh,dl
    14. and dh,01000000B
    15. cmp dh,00H
    16. jz _2
    17. mov dh,01H
    18. _2:
    19. mov [si],dh
    20. inc si
    21. mov dh,dl
    22. and dh,00100000B
    23. cmp dh,0
    24. jz _3
    25. mov dh,01H
    26. _3:
    27. mov [si],dh
    28. inc si
    29. mov dh,dl
    30. and dh,00010000B
    31. cmp dh,00H
    32. jz _4
    33. mov dh,01h
    34. _4:
    35. mov [si],dh
    36. inc si
    37. mov dh,dl
    38. and dh,00001000B
    39. cmp dh,00H
    40. jz _5
    41. mov dh,01h
    42. _5:
    43. mov [si],dh
    44. inc si
    45. mov dh,dl
    46. and dh,00000100B
    47. cmp dh,00H
    48. jz _6
    49. mov dh,01h
    50. _6:
    51. mov [si],dh
    52. inc si
    53. mov dh,dl
    54. and dh,00000010B
    55. cmp dh,00H
    56. jz _7
    57. mov dh,01h
    58. _7:
    59. mov [si],dh
    60. inc si
    61. mov dh,dl
    62. and dh,00000001B
    63. cmp dh,00H
    64. jz _8
    65. mov dh,01h
    66. _8:
    67. mov [si],dh
    68. ret
  • 相关阅读:
    安卓开发面试题
    CPP_D2
    Centos SFTP搭建
    数据结构——二叉树搜索树(二叉搜索树的概念、实现、先序遍历、中序遍历、后序遍历)
    javaScript基础
    基于jacoco和CI做代码覆盖率检测
    JAVA毕业设计潮流奢侈品购物网站计算机源码+lw文档+系统+调试部署+数据库
    vue3+ts+vant移动端H5项目搭建
    C# 第二章『基础语法』◆第2节:switch case语句
    mybatis-plus
  • 原文地址:https://blog.csdn.net/apple_51426592/article/details/127642172