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
