仅以此文记录我在Centos
上使用DosBox
写8086汇编小程序,不知为何DosBox
总是会将我当前用户Logout
,然后我必须重新登录的艰苦岁月……
- 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; 产生系统中断。
- 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
MATCH!
,不相同输出NO 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,则不跳转
输入原文件名->将文件读入预先定义好的缓冲区->输入新的文件名->将缓冲区的内容写入新文件。
(这部分代码是马辉完成的,我们共同做的汇编程序大赛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
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
-
- ;***************
例如生成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
-
- ;***************
-
例如 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