汇编入门小例子

来源:互联网 发布:淘宝上自粘墙纸有毒吗 编辑:程序博客网 时间:2024/05/05 08:14

: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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
备注:
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):INFOR2DB0AH,0DH,PleaseInputtheSecondData(<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 21HSUB AL,30H        ;输入的位ASCII码,所以减去48MOV BL,ALLEA DX,INFOR2MOV AH,09HINT 21HMOV AH,01HINT 21HSUB AL,30HXOR AH,AH       ;将AH清空ADD AL,BL       AAA             ;加法ASCII码调整指令PUSH AXLEA DX,INFOR3MOV AH,09HINT 21HPOP AXPUSH AXMOV DL,AHADD DL,30H     ;计算结束之后加上48输出。MOV AH,02H     ;2号系统调用,输出单个字符,在汇编中想输出数字只能单个ASCII码的输出。INT 21HPOP AXMOV DL,ALADD DL,30H  MOV AH,02HINT 21HMOV AH,4CHINT 21H

CODE ENDS
END START
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
备注:
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
1
2
3
4
5
1
2
3
4
5
3:编写一段程序比较两个字符串是否相同,相同输出MATCH!,不相同输出NO MATCH!。

思路:

先计算两个串长度,如果不同直接退出,相同执行第2步
挨个比较字符是否相同,若有不相同结束,直到比较结束全部相同
输出match
DATA SEGMENT
STR1 DB ‘ABCDEFGNEQU-STR1 ;给N赋值,-STR1表示当前位置到STR1头部的距离,也就是STR1的长度。
STR2 DB ‘BCDEFGMEQU-STR2
MESS DB ‘NO MATCH!RIGHTDBMATCH!
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
备注:
1:CMP指令:
不影响两个操作数的原大小,影响的是状态标志位,如果相等,ZF=1。否则ZF=0

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

JNZ(ZF == 0) {
//如果ZF == 0 ,则跳转
}
//如果ZF == 1,则不跳转
1
2
3
4
1
2
3
4
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:;newFileInputTipdbpleaseinputnewfilepath:’;提示新文件路径
openErrorTip db ‘open file error !!;readErrorTipdbreadfileerror!!’ ;提示读文件失败
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
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-7div bl mov al, ahmov ah, 0inc al     ; 加1 得到范围为1-8ret

;*****
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 cxloop 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-7div bl mov al, ahmov ah, 0inc al     ; 加1 得到范围为1-8ret

;*****

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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    ;先拿出最高位是不是1cmp dh,00H          ;如果为0jz _1   mov dh,01h          ;如果不为0就置为1_1:mov [si],dh         ;将dh的值也就是0给[si]inc simov dh,dl  and dh,01000000Bcmp dh,00Hjz _2mov dh,01H_2:mov [si],dhinc simov dh,dl  and dh,00100000Bcmp dh,0jz _3mov dh,01H_3:mov [si],dhinc simov dh,dl and dh,00010000Bcmp dh,00Hjz _4mov dh,01h_4:mov [si],dhinc simov dh,dl  and dh,00001000Bcmp dh,00Hjz _5mov dh,01h_5:mov [si],dhinc simov dh,dl  and dh,00000100Bcmp dh,00Hjz _6mov dh,01h_6:mov [si],dhinc simov dh,dl  and dh,00000010Bcmp dh,00Hjz _7mov dh,01h_7:mov [si],dhinc simov dh,dl  and dh,00000001Bcmp dh,00Hjz _8mov dh,01h_8:mov [si],dhret

;*****

0 0