8086 汇编小程序

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

1:HelloWorld

DATA SEGMENT
str db 'Hello World$'    ;要输出的字符串必须要以$结尾
DATA ENDS

CODE SEGMENT
ASSUME CS:CODE,DS:DATA    ;将CS和CODE,DS和DATA段建立联系
START: 
       MOV BX,DATA 
       MOV DS,BX
       LEA DX,str 
       MOV AH,9
       INT 21H

       MOV AH,4CH        ;将控制权返回给终端。
       INT 21H
CODE ENDS
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:从键盘输入两个一位十进制数,计算两个数之和,并将结果在屏幕上显示出来。

DATA SEGMENT
    INFOR1 DB 'Please Input the First Data(<10):$'
    INFOR2 DB 0AH,0DH,'Please Input the Second Data(<10):$' ; 0A 是 '\n' 0D 是 '\r',回车换行
    INFOR3 DB 0AH,0DH,'The Result is:$'
DATA ENDS

CODE SEGMENT
    ASSUME CS:CODE,DS:DATA
START:
    MOV AX,DATA
    MOV DS,AX
    LEA DX,INFOR1      ;输出第一条提示语句
    MOV AH,09H
    INT 21H

    MOV AH,01H        ;1号系统调用将字符输入至AL中。
    INT 21H
    SUB AL,30H        ;输入的位ASCII码,所以减去48
    MOV BL,AL

    LEA DX,INFOR2
    MOV AH,09H
    INT 21H

    MOV AH,01H
    INT 21H
    SUB AL,30H

    XOR AH,AH       ;将AH清空
    ADD AL,BL       
    AAA             ;加法ASCII码调整指令

    PUSH AX
    LEA DX,INFOR3
    MOV AH,09H
    INT 21H

    POP AX
    PUSH AX
    MOV DL,AH
    ADD DL,30H     ;计算结束之后加上48输出。
    MOV AH,02H     ;2号系统调用,输出单个字符,在汇编中想输出数字只能单个ASCII码的输出。
    INT 21H
    POP AX
    MOV DL,AL
    ADD DL,30H  
    MOV AH,02H
    INT 21H

    MOV AH,4CH
    INT 21H
CODE ENDS
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
DATA  SEGMENT
    STR1 DB 'ABCDEFG$'              
    N EQU $-STR1               ;给N赋值,$表示当前指令的地址,$-STR1表示当前位置到STR1头部的距离,也就是STR1的长度。
    STR2 DB 'BCDEFG$'  
    M EQU $-STR2                   
    MESS DB 'NO MATCH!$'
    RIGHT DB 'MATCH!$'
DATA  ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:DATA

BEGIN:
    MOV AX,DATA
    MOV DS,AX                
    MOV AX,DATA
    MOV ES,AX                
    MOV AL,N                   
    CMP AL,M          ;比较长度是否相等,相等ZF=0,否则ZF=1
    JNZ EXIT           ;JNZ:jump if not zero ,zero 指的是比较结果,而不是ZF标志位的值
    LEA SI,STR1              
    LEA DI,STR2
    MOV CL,N
    MOV CH,0
    CLD               
    REPE CMPSB        ;挨个比较单个字符,如果有一个不等就跳EXIT
    JNZ EXIT                                                                
    LEA DX,RIGHT              
    JMP OUT1

EXIT:   
    LEA DX,MESS
OUT1:      
    MOV AH,9                   
    INT 21H
    MOV AH,4CH                
    INT 21H

CODE  ENDS
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,他负责文件读写部分,我负责加密解密算法部分)

data segment

filePath db 20,?,20 dup(?);存储原文件名称
newFilePath db 10,?,10 dup(?),00 ;存储加密或者解密的文件的路径
fileHandle db 2 dup(?);存储文件代号
fileBuffer db 10000  dup(?);文件缓冲区
fileInputTip db 'please input source file path:$';提示源文件路径
newFileInputTip db 'please input new file path:$';提示新文件路径
openErrorTip db 'open file error !!$';提示打开文件失败
readErrorTip db 'read file error !!$' ;提示读文件失败
fileCount db ? ;定义实际读取的字节数

data ends

code segment
assume cs:code,ds:data

start:
 mov ax,data
 mov ds,ax

 call openFile ;打开文件
 call readFile ;将文件读至缓冲区
 call closeFile ;关闭文件

 call createFile ;创建新文件
 call writeFile ;写文件
 call closeFile ;关闭文件

 call returnDos ;返回DOS




;***************
;打开文件
openFile proc near
 ;9号功能调用,提示输入文件名
 mov dx,offset fileInputTip
 mov ah,9
 int 21h
 ;10号功能调用,将文件名存储在filePath中
 mov dx,offset filePath
 mov ah,10
 int 21h
 ;换行处理
 call nextLine
 ;取得键盘上输入的实际的个数
 lea bx,filePath+1
 ; 清空cx
 xor cx,cx
 ;将键盘上实际输入的个数送给cx
 mov cl,[bx]
 ;取得文件实际的存储路径
 lea bx,filePath+2
 ;处理enter的ascall码
 call findEnter
 ;系统调用,打开文件
 mov ah,3dh
 mov al,00
 lea dx,filePath+2
 int 21h
 ; 若CF为1,打开失败
 jc openError
 ;若CF为0,打开成功,获取返回的ax中的文件代号
 jmp getFileHandle
getFileHandle:
 ;取得fileHandle的地址空间
 lea bx,fileHandle
 ;将文件代号保存在fileHandle中
 mov [bx],ax
 ret
openError:
 ;9号功能调用,提示打开文件失败
 mov dx,offset openErrorTip
 mov ah,9
 int 21h
 ;返回dos
 call returnDos
 ret
openFile endp
;***************


;***************
;读文件
readFile proc near
 ;系统调用,读文件
 mov ah,3fh
 lea si,fileHandle
 mov bx,[si]
 mov cx,10000
 lea dx,fileBuffer
 int 21h
 ;cf=1,读文件失败,cf=0,读文件成功
 ;提示读取文件失败
 jc readError
 jmp getFileCount
getFileCount:
 ;将实际读取的字节数放在fileCount中
 lea bx,fileCount
 mov [bx],ax
 ret
readError:
 ;9号功能调用,提示读文件失败
 mov dx,offset readErrorTip
 mov ah,9
 int 21h
 ;返回dos
 call returnDos
 ret
readFile endp
;***************



;***************
;换行处理
nextLine proc near
 mov dl,0dh
 mov ah,2
 int 21h
 mov dl,0ah
 mov ah,2
 int 21h
 ret
nextLine endp
;***************


;***************
;将回车所占的地址空间的值设为00h
findEnter proc near
next1:
 inc bx
 loop next1
 mov al,00h
 mov [bx],al
 ret
findEnter endp
;***************


;***************
;返回dos
returnDos proc near
 mov ah,4ch
 int 21h
 ret
returnDos endp
;***************

;***************
;关闭文件
closeFile proc near
 mov ah,3eh
 int 21h
 ret
closeFile endp
;***************

;***************
;创建文件,cf=0,返回文件代号,保存在ax中;cf=1,创建失败
createFile proc near
create:
 ;9号功能调用,提示输入新的文件名加路径
 mov dx,offset newFileInputTip
 mov ah,9
 int 21h
 ;10号功能调用,将新文件名艺伎路径保存在newFilePath中
 mov dx,offset newFilePath
 mov ah,10
 int 21h
 ;换行处理
 call nextLine
 ;取得newFilePath缓冲区中实际输入的字符的个数
 lea bx,newFilePath+1
 ;清空cx
 xor cx,cx
 ;将newFilePath缓冲区实际存储的个数送给cx
 mov cl,[bx]
 ;判断是否输入
 cmp cx,00h
 ;如果输入的不为空,则跳转continue
 jnz continue
 ;如果输入的为空,则重新输入
 jmp create
continue:
 ;取得实际的存储路径
 lea bx,newFilePath+2
 ;处理enter的ascall码
 call findEnter
 ;系统调用,创建文件
 mov ah,3ch
 mov cx,00
 lea dx,newFilePath+2
 int 21h
 ; 将文件代号保存在fileHandle中
 lea si,fileHandle
 mov [si],ax
 ret
createFile endp
;***************


;***************
;向文件写数据
writeFile proc near
 ;系统调用,写文件
 mov ah,40h
 lea si,fileHandle
 mov bx,[si]
 lea di,fileCount
 mov cx,[di]
 lea dx,fileBuffer
 int 21h
 ret
writeFile endp
;***************

code ends
end start

5:汇编生成随机数

8086 定时器模式生成随机数

;***************
;获取随机数 范围1-8
getRand:
    xor al,al
    mov ax, 0h; 间隔定时器
    out 43h,al; 将0送到43h端口
    in al, 40h; 将40h端口的数据送至al

    mov bl, 8   ;除8 得到范围为0-7
    div bl 

    mov al, ah
    mov ah, 0

    inc al     ; 加1 得到范围为1-8

    ret

;***************

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

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

;***************
;创建随机数并存入文件
createRandNum:
      lea si,randNum1      ;randNum1是保存随机数串的字符串
      mov cx,8             ;设定需要产生的个数
      doRand:
        push cx
        createRandNumdo1:           ;循环产生
            call getRand   ;获得一个随机数

            xor di,di
            xor cx,cx

            lea di,randNum1
            mov cx,8
            createRandNumdo2:  ;将新产生的数字和已经保存的比对
                mov bh,[di]
                cmp bh,al 
                jz createRandNumdo1   ;如果出现重复就继续产生
                inc di
                loop createRandNumdo2

        mov bh,RandNum[0]         ;保存目前一共产生的随机数个数
        add bh,1
        mov RandNum[0],bh

        cmp bh,9               ;如果为Num+1 就结束
        jz mRet

        mov [si],al
        inc si


        pop cx
    loop doRand

;***************
;获取随机数 范围1-8
getRand:
    xor al,al
    mov ax, 0h; 间隔定时器
    out 43h,al; 将0送到43h端口
    in al, 40h; 将40h端口的数据送至al

    mov bl, 8   ;除8 得到范围为0-7
    div bl 

    mov al, ah
    mov ah, 0

    inc al     ; 加1 得到范围为1-8

    ret

;***************

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

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

fetchBinary:
    xor dx,dx;

    lea si,temp1 
    mov dl,[bx]

    mov dh,dl; 
    and dh,10000000B    ;先拿出最高位是不是1
    cmp dh,00H          ;如果为0
    jz _1   
    mov dh,01h          ;如果不为0就置为1
    _1:
    mov [si],dh         ;将dh的值也就是0给[si]
    inc si

    mov dh,dl  
    and dh,01000000B
    cmp dh,00H
    jz _2
    mov dh,01H
    _2:
    mov [si],dh
    inc si

    mov dh,dl  
    and dh,00100000B
    cmp dh,0
    jz _3
    mov dh,01H
    _3:
    mov [si],dh
    inc si

    mov dh,dl 
    and dh,00010000B
    cmp dh,00H
    jz _4
    mov dh,01h
    _4:
    mov [si],dh
    inc si

    mov dh,dl  
    and dh,00001000B
    cmp dh,00H
    jz _5
    mov dh,01h
    _5:
    mov [si],dh
    inc si

    mov dh,dl  
    and dh,00000100B
    cmp dh,00H
    jz _6
    mov dh,01h
    _6:
    mov [si],dh
    inc si

    mov dh,dl  
    and dh,00000010B
    cmp dh,00H
    jz _7
    mov dh,01h
    _7:
    mov [si],dh
    inc si

    mov dh,dl  
    and dh,00000001B
    cmp dh,00H
    jz _8
    mov dh,01h
    _8:
    mov [si],dh

    ret
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

apple_51426592

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

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

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

打赏作者

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

抵扣说明:

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

余额充值