1. 判断语句正确错误
1)、MOV BL, CX: 可行但mov的源比目标长度大,会导致数据丢失。警告:Operand types must match
2)、MOV DS, SS: 错误,ds是数据段寄存器,ss是栈寄存器,都属于段寄存器。8086不支持段寄存器之间传送数据。报错:Wrong type of register
3)、MOV [BX], [DI]: 错误,不能从存储单元到存储单元。报错: Improper operand type
4)、MOV AL, BX: 可行但mov的源比目标长度大,会导致数据丢失。警告:Operand types must match
5)、MOV ES, AL: 源不能比目标长度短,报错:Wrong type of register
6)、MOV DS, DX: OK
7)、MOV CS, AX: 错误,CS不能作为目标寄存器。Illegal use of CS register
8)、MOV BX, CS:正确。
9)、MOV DS, 1230H: 错误,立即数不能直接送段寄存器。Immediate mode illegal
10)、MOVSX DS, AL: 错误,8086中不支持该指令。报错: Expected: instruction or directive
11)、XCHG BX, 3: 寄存器间交换指令任何一个操作数不能是立即数。报错: Immediate mode illegal
12)、POP CS: 不能POP CS段寄存器。报错:llegal use of CS register
13)、MOV IP, SI:IP不能作为目标寄存器。报错:Symbol not defined:IP
14)、PUSH CS: 正确
15)、PUSH BL: BL的大小不符合。警告:Illegal size for operand
16)、MOV [SP], BX: 正确
17)、MOV AX, BX+3: 错误,BX+3是一个值,不是内存地址指针。 报错: Illegal use of register
18)、MOV AX, [BX+3]: 正确
19)、MOV BX, [BX]:正确
20)、MOV BH, [BL]:错误,BL不能作为内存地址。报错:Must be index or base register
21)、XCHG ES, AX: 错误, XCHG操作任何一个操作数都不能为段寄存器。报错:Improper use of segment register
22)、LEA AX, [BX+SI]:正确。
23)、MUL 10H: 错误,MUL的操作数不能是立即数。报错:Immediate mode illegal
24)、IMUL DX, 10H:错误,IMUL只有一个操作数。警告:Extra characters on line
25)、DIV 10:错误,DIV的操作数不能是立即数。报错:Immediate mode illegal
26)、IDIV DX, 10H:错误,IDIV只有一个操作数。警告:Extra characters on line
27)、SHL AX, CX:错误,移动位数要用1或者CL指示。报错:Constant expected
28)、SHR BX, CH:错误,移动位数要用1或者CL指示。报错:Constant expected
29)、ROL BX, 20:错误,循环左移的位数大于1时必须用CL指示。报错:Improper operand type
30)、RCR AX, CL:正确
31)、CMP AX,1234H:正确
32)、CMP 12H, CL:错误,CMP第一个操作数不能是立即数。报错:Immediate mode illegal
33)、JCXZ next:正确。
34)、JEBXZ next:错误: 8086中没有该指令。报错:Expected:instruction or directive。
2. 汇编程序
13.编写一个程序,统计在双字变量DDVAR的内容中二进制位是1的位数,并存入变量COUNT中
.model small
.data
num dd 0fffffffh
nl EQU word ptr num
nh EQU word ptr num+2
count dw 0
.code
start:
mov ax,@data
mov ds,ax
mov ax,nl ;计算低16位1的个数
call count1
mov ax,nh ;计算高16位1的个数
call count1
mov dx,count ;将count放在dx寄存器中,便于调试观察
mov ax,4c00h
int 21h
count1 proc near
mov cl,16
work:
shl ax,1 ;左移1位,最高位放入cf
jnc ctn
inc count ;cf为1则计数器加1
ctn:loop work
ret
count1 endp
end start
15.编写一个程序把字符串String两端的空格删除(字符串以0结束)。
.model small
.data
str db " Bow to Hungry. ",0
EndOfString EQU 0 ;字符串尾标志
Blank EQU 20h ;空格
.stack 200h
.code
start:
mov ax,@data
mov ds,ax
call trim
mov ax,4c00h
int 21h
;删除字符串两端的空格
trim proc near
lea bx,str
lea ax,str
;找到第一个非空格
pre:
cmp byte ptr [bx],EndOfString
je exit
cmp byte ptr [bx],Blank
jne mv
inc bx
jmp pre
;将非空格位置起的字符串前移
mv:
push bx
mov dl,[bx]
mov bx,ax
mov [bx],dl
inc ax
pop bx
inc bx
cmp byte ptr [bx],EndOfString
je suf
jmp mv
;从后向前找到最后一个非空格
suf:
dec bx
cmp byte ptr [bx],Blank
jne prnt
jmp suf
;输出字符串
prnt:
mov byte ptr [bx+1],'$'
lea dx,str
mov ah,9
int 21h
exit:
ret
trim endp
end start
17.用双重循环将下三角乘法表存入从Result开始的45字节中。
自己添加了输出显示。
.model small
.data
result db 45 dup(?)
tmp db 5 dup(0),'$' ;十进制输出缓冲区
buf EQU offset tmp+5 ;输出缓冲区尾
cr = 0dh ;回车符
lf = 0ah ;换行符
blk = 20h ;空格
num = 9 ;循环次数
.stack 200h
.code
start:
mov ax,@data
mov ds,ax
;将result地址放入B寄存器
lea bx,result
;也可以相对基址变址寻址方式 mov bx,0
mov cl,num ;外层循环 9~1
for1:
mov ax,cx ;内层循环 cx~9
push cx ;保护外层循环的c寄存器
for2:
push ax
mul cl ;计算 ax <- al*cl
mov word ptr [bx],ax
;相对基址变址寻址方式 mov word ptr result[bx],ax
inc bx
call output
call blank
pop ax
inc ax
cmp ax,num
jle for2
pop cx
call endl
loop for1
mov ax,4c00h
int 21h
;输出ax中的十进制数
output proc near
push ax
push bx
push cx
push dx
mov bx,buf
outloop:
or ax,ax
jz outloopfin ;ax为0则结束
mov dx,0
mov cx,10
div cx ;dx:ax除以10,余数在dx中
add dx,'0';转换为字符
dec bx
mov byte ptr [bx],dl
jmp outloop
outloopfin:
mov dx,bx
mov ah,9
int 21h
pop dx
pop cx
pop bx
pop ax
ret
output endp
;输出换行
endl proc near
push ax
push dx
mov dl,cr
mov ah,2
int 21h
mov dl,lf
mov ah,2
int 21h
pop dx
pop ax
ret
endl endp
;输出空格
blank proc near
push ax
push dx
mov dl,blk
mov ah,2
int 21h
pop dx
pop ax
ret
blank endp
end start
4.22分别编写以下子程序实现下列功能(所有变量都是字类型)
1)ABS(x)=|x|
2) \(F(x)=3x^2+5x-8\)
3) strlen(String),(求字符串长度,字符串以0结束)
.model small
.data
x dw -2
z dw ?
str db "sekai ichi kawaii.",0
len dw 0
.stack 200h
.code
start:
mov ax,@data
mov ds,ax
call absx
mov ax,16
mov x,ax
call f
call strlen
mov ax,4c00h
int 21h
;ABS(x)
absx proc near
mov ax,x
cmp ax,0
jge done
neg ax
done:
ret
absx endp
; f(x)=3x^2+5x-8=(3x+5)*x-8
f proc near
push ax
mov ax,3
mul x
add ax,5
mul x
sub x,8
mov z,ax
pop ax
ret
f endp
strlen proc near
push ax
push bx
lea bx,str
mov ax,0
for:
cmp byte ptr [bx],0
je exit
inc ax
inc bx
jmp for
exit:
mov len,ax
pop bx
pop ax
ret
strlen endp
end start
微机原理与接口技术习题4-31:
一个学生的信息包括姓名、班级、学号(班内序号)、成绩。试编写程序实现以下功能:
(1) 能录入学生成绩(十进制形式);
(2) 能按要求(如班内序号或成绩)进行排序显示;
(3) 能统计平均成绩;
(4) 能按分数段统计人数,不及格、60~70、70~80、80~90、90~100各分数段的人 数。
写得有点长。
origin: 11-12
UPD:2017-11-28 17:20:21 zjl发现了两个bug,统计分数段时没有清空以及90~100段有问题,已修复。
UPD: 2017-11-29 19:79 lzx 发现分数段还是不正确。经过思考,发现我当成排好序的了,然后写过了个算法。另外注意,宏太长会导致一些跳转失败,jmp外的跳转指令能跳转的相对位置有限,所以要用子程序。
;=========================MACRO=======================
saveReg macro
push ax
push bx
push cx
push dx
push si
endm
recoverReg macro
pop si
pop dx
pop cx
pop bx
pop ax
endm
; cx <- x*10
mul10 macro x
push ax
mov ax, x
mov cx, 10
imul cx
mov cx, ax
pop ax
endm
; change ax from string to decimal number
toDigit macro
mov dl, al ; ready to show
sub al, '0'; ax-='0'
mov ah, 0
endm
; output '\n\r'
endl macro
outputChar CR
outputChar LF
endm
; echo input
echoIn macro
mov ah, 01h
int 21h
endm
; ans <- x/10, ans <- x%10
getAns macro x
saveReg
mov ax, x
mov dx, 0
mov cx, 10
div cx
mov ans, ax
mov ans2, dx
recoverReg
endm
; output char
outputChar macro char
push ax
push dx
mov dl, char
mov ah, 2
int 21h
pop dx
pop ax
endm
; output string ends with '$'
outputStr macro string
push dx
push ax
lea dx, string
mov ah, 9
int 21h
pop ax
pop dx
endm
; read until input is digit.
; store in [al]
readNonDigit macro
local for
for:
mov ah, 1; echo input
int 21h
cmp al, '0'
jb for ;<0
cmp al, '9'
ja for ;>9
endm
; input string ends with '\n' or ' '
inputStr macro string
push bx
lea bx, string
call inStr
pop bx
endm
; input number num
inputNum macro num
push cx
call inputNumPro
mov word ptr num, cx
pop cx
endm
inputFloat macro num
push cx
call inputFloatPro
mov word ptr num,cx
pop cx
endm
; output num
outputNum macro num
push ax
mov ax, word ptr num
call outputNumPro
pop ax
endm
; stumov dest,souce
;function: mov student from souce to dest
stumov macro dest,souce
saveReg
mov ax, ds
mov es, ax; (es)<-(ds)
lea si, souce
lea di, dest
mov cx, stuSize
shr cx, 1
cld;df<-0
rep movsw
recoverReg
endm
; stage
stage macro
local begin,end,clearNumFor,for,for2,next,show
saveReg
;clear num
mov bx,0
clearNumFor:
cmp bx,10
jae begin
mov num[bx],0
add bx,2
jmp clearNumFor
begin:
mov ax, 0
mov bx, 0
for:
cmp ax, n
je show
mov cx, 600
mov dx, 0
for2:
cmp word ptr stus[bx].score, cx
jb next; <600
cmp cx, 1000
je next; == 1000
add cx,100
add dx,2
jmp for2
next:
inc ax
push bx
mov bx,dx
inc num[bx]
pop bx
add bx, stuSize
jmp for
show:
outputNum num[0]
mov bx, 2
nextShow:
cmp bx, 10
je end
outputChar ','
outputNum num[bx]
add bx, 2
jmp nextShow
end:
endl
recoverReg
endm
; swap stua,stub
;function: swap student stua and student stub
swap macro stua,stub
stumov tmp,stua
stumov stua,stub
stumov stub,tmp
endm
clr macro
mov ah, 0
mov al, 03h
int 10h
endm
PressAny macro
mov ah, 08h
int 21h
endm
;=========================BEGIN=======================
.model small
.data
student struc
nm db 10 dup('$')
clss db 10 dup('$')
id dw ?
score dw ?
student ends
stus student 10 dup(<>)
tmp student <>
stuSize EQU $-tmp
n dw 0
ans dw 0
ans2 dw 0
sum dw 0
num dw 6 dup(0)
op dw 0
hasNum db 0
cmpById db 0
buf db 6 dup(0), '$'
bufptr EQU offset buf+6
.const
CR = 0dh
LF = 0ah
BLK = ' '
DOT = '.'
EN_NUM db "Enter the number of students:", '$'
EN_DETAIL db "Enter name, class, id and score of each student:",CR,LF, '$'
EN_MENU db "MENU:",CR,LF
db "0: exit",CR,LF
db "1: sort by score", CR,LF
db "2: sort by id", CR,LF
db "3: get average score", CR,LF
db "4: get the number of students in each stage",CR,LF,'$'
EN_AV db "The average score is:",'$'
EN_TH db "Name Class Id Score",CR,LF,'$'
EN_PRS db "Press any key to return...",'$'
EN_ST db "[0,60),[60,70),[70,80),[80,90),[90,100]",CR,LF,'$'
.stack 300h
.code
start:
mov ax, @data
mov ds, ax
clr
outputStr EN_NUM
inputNum n
outputStr EN_DETAIL
mov cx, n
mov bx,0
or cx,cx
jz MENU
;===================readStu==============
readStu:
inputStr stus[bx].nm
inputStr stus[bx].clss
inputNum stus[bx].id
inputFloat stus[bx].score
mov ax, word ptr stus[bx].score
add sum, ax
add bx,stuSize
loop readStu
;==================Menu==============
MENU:
outputStr EN_MENU
inputNum op
cmp op, 0
jne nxOp
jmp exit
nxOp:
cmp op, 2
je sortById
cmp op, 3
je averageScore
cmp op, 4
je everyStage
;=====[ sortByScore ]============
sortByScore:
outputStr EN_TH
mov cmpById, 0
call sort
jmp PRESS
;=====[ sortById ]============
sortById:
outputStr EN_TH
mov cmpById, 1
call sort
jmp PRESS
;====[ averageScore ]============
averageScore:
outputStr EN_AV
mov ax, sum
mov dx, 0
or n, 0
jz sishewuru
div n
shl dx, 1
cmp dx, n
jb sishewuru
inc ax
sishewuru:
getAns ax
call outputAns
jmp PRESS
;====[ everyStage ]==============
everyStage:
outputStr EN_ST
stage
PRESS:
outputStr EN_PRS
PressAny
clr
jmp MENU
exit:
mov ax, 4c00h
int 21h
;=============outputNumPro==============
; output a decimal number from ax
outputNumPro proc near
saveReg
mov bx, bufptr
or ax, ax
jnz outLoop
dec bx
mov byte ptr [bx], '0'
jz show
outLoop:
or ax, ax
jz show
mov dx, 0
mov cx, 10
div cx
add dx, '0'
dec bx
mov byte ptr [bx], dl
jmp outLoop
show:
mov dx, bx
mov ah, 9
int 21h
recoverReg
ret
outputNumPro endp
;===================outputAns==============
outputAns proc near
outputNum ans
or ans2, 0
je ansEnd
outputChar DOT
outputNum ans2
ansEnd:
endl
ret
outputAns endp
;==================outputFun====================
; output
output proc near
push ax
push bx
push cx
mov bx, 0
mov cx, n
for:
outputStr stus[bx].nm
outputChar BLK
outputStr stus[bx].clss
outputChar BLK
outputNum stus[bx].id
outputChar BLK
mov ax, word ptr stus[bx].score
getAns ax
call outputAns
add bx, stuSize
loop for
return:
pop cx
pop bx
pop ax
ret
output endp
;===========Sort===============
;sort
sort proc near
saveReg
mov dx, 1
for1:
cmp dx, n
jne ctn
jmp done ;jmp can jump far
ctn:
mov cx, 1
mov ax, n
sub ax, dx; n-1..1
mov bx, 0
push dx
mov dx, 0
for2:
cmp dx, ax
jne ctn2
jmp next
ctn2:
push ax
or cmpById, 0
jz sSco
jmp sId
sSco:
mov ax, word ptr stus[bx].score
cmp ax, word ptr stus[bx+stuSize].score
jmp by
sId:
mov ax, word ptr stus[bx].id
cmp ax, word ptr stus[bx+stuSize].id
by:
pop ax
jbe nex2
swap stus[bx], stus[bx+stuSize]
mov cx, 0
nex2:
inc dx
add bx, stuSize
jmp for2
next:
pop dx
inc dx
cmp cx, 1
je done
jmp for1
done:
call output
recoverReg
ret
sort endp
;=============inputFloatPro==============
; input xx.x or xx
; cx <- xx.x * 10
inputFloatPro proc near
push dx
push bx
push ax
readNonDigit
mov bx, 0
mov cx, 0
whileDigit:
cmp al, '0'
jb middle ;<0
cmp al, '9'
ja middle ;>9
mov bx, 1
mul10 cx; cx=cx*10
jo inFEnd
toDigit
add cx, ax; cx+=ax
jo inFEnd
diNext:
echoIn
jmp whileDigit
middle:
mul10 cx; cx=cx*10
jo inFEnd
cmp bx, 1
jne inFEnd
cmp al, '.'
jne inFEnd
lastdigit:
echoIn
cmp al, '0'
jb inFEnd ;<0
cmp al, '9'
ja inFEnd ;>9
toDigit
add cx, ax; cx+=ax
over:
echoIn
cmp al, CR
je inFEnd
cmp al, BLK
je inFEnd
jmp over
inFEnd:
pop ax
pop bx
pop dx
ret
inputFloatPro endp
;=============inputNumPro==============
; input a decimal num to [cx]
inputNumPro proc near
push ax
push bx
readNonDigit
mov cx, 0
inDecLoop:
cmp al, '0'
jb inEnd ;<0
cmp al, '9'
ja inEnd ;>9
mul10 cx; cx=cx*10
jo inEnd
toDigit
add cx, ax; cx+=ax
jo inEnd
inNext:
echoIn
jmp inDecLoop
inEnd:
pop bx
pop ax
ret
inputNumPro endp
;=================inStr==================
; input string ends with '\n' or ' ' to [bx]
inStr proc near
push ax
inStrLoop:
echoIn
cmp al, CR
je inStrEnd
cmp al, BLK
je inStrEnd
mov byte ptr [bx],al
inc bx
jmp inStrLoop
inStrEnd:
mov byte ptr [bx],'$'
pop ax
ret
inStr endp
end start
(实验)可编程并行接口8255 方式0
code segment
assume cs:code
start:
mov dx, 28bh
mov al, 10001001b
out dx, al
inout:
mov dx, 28ah ;从C口输入数据
in al, dx
mov dx, 288h ;从A口输出
out dx, al
mov ah,01h
int 16h
jz inout ;循环
mov ax, 4c00h
int 21h
code ends
end start
串口通讯8251
.model small
.data
msg db 'You can play a key on the keyboard~',0ah,0dh,'$'
control_port8254 EQU 283h
data0_port8254 EQU 280h
control_port8251 EQU 2b9h
data_port8251 EQU 2b8h
.code
assume cs:@code,ds:@data
start:
mov ax,@data
mov ds,ax
mov dx,control_port8254 ;8254初始化
mov al,00010110b ;8254 计数器0工作在方式3
out dx,al
mov dx,data0_port8254 ;将初值写入计数器0
mov al,52
out dx,al
mov dx,control_port8251 ;8251初始化
mov al,01000000b ;复位命令字
out dx,al
nop ;延时
mov al,01001110b ;方式控制字(异步方式,字长8,无校验,波特率因子16)
out dx,al
mov al,00100111b ;工作命令字(RTS,ER,RXE,DTR,TXEN置1)
out dx,al
lea dx,msg ;提示信息
mov ah,09h
int 21h
for1: mov dx,control_port8251 ;TxRDY为1?
in al,dx
test al,01h
jz for1
for2: mov ah,01 ;读键盘
int 21h
cmp al,27 ;是否是ESC
jz exit
inc al
mov dx,data_port8251
out dx,al
for3: mov dx,control_port8251 ;DxRDY为1?
in al,dx
test al,02h
jz for3
mov dx,data_port8251 ;从8251数据口接收数据
in al,dx
mov dl,al
mov ah,02 ;显示数据
int 21h
jmp for1
exit: mov ax,4c00h ;返回操作系统
int 21h
end start