微机原理上机实验相关
Latest
;eg0706.asm
;eg0706.asm in DOS
include io16.inc
.data
intmsg byte 'A 8259A Interrupt !',0dh,0ah,0
counter byte 0 ;中断次数记录单元
.code
start:
mov ax,@data
mov ds,ax
mov ax,3508h ;获取原中断向量
int 21h
push es ;保存原中断向量(利用堆栈)
push bx
cli ;关中断
push ds ;设置新中断向量
mov ax,seg new08h
mov ds,ax
mov dx,offset new08h
mov ax,2508h
int 21h
pop ds
in al,21h ;读出IMR
push ax ;保存原IMR内容
and al,0feh ;允许IRQ0,其他不变
out 21h,al ;设置新IMR内容
mov counter,0 ;设置中断次数初值
sti ;开中断
;主程序完成中断服务程序设置,可以处理其他事务
start1: cmp counter,10 ;本例的主程序仅循环等待中断
jb start1 ;中断10次退出
;
cli ;关中断
pop ax ;恢复IMR
out 21h,al
pop dx ;恢复原中断向量
pop ds
mov ax,2508h
int 21h
sti ;开中断
exit 0
; 中断服务程序
new08h proc
sti ;开中断
push ax ;保护寄存器
push si
push ds
mov ax,@data ;外部随机产生中断,DS也不确定,所以必须设置DS
mov ds,ax
inc counter ;中断次数加1
mov si,offset intmsg ;显示信息
call dpstri
mov al,20h ;发送EOI命令
out 20h,al
pop ds ;恢复寄存器
pop si
pop ax
iret ;中断返回
new08h endp
dpstri proc ;显示字符串子程序
push ax ;入口参数:DS:SI=字符串首址
push bx
dps1: mov al,[si]
cmp al,0
jz dps2
mov bx,0 ;调用ROM-BIOS功能显示al中的字符
mov ah,0eh
int 10h
inc si
jmp dps1
dps2: pop bx
pop ax
ret
dpstri endp
end start
在例题7-6基础上,现要求每隔一次中断才显示信息,并显示出当前中断的次数
;eg0706-1.asm
;eg0706.asm in DOS
include io16.inc
.data
intmsg byte 'A 8259A Interrupt !',0dh,0ah,0
counter byte 0 ;中断次数记录单元
outmsg byte 'The value of counter is: ',0
.code
start:
mov ax,@data
mov ds,ax
mov ax,3508h ;获取原中断向量
int 21h
push es ;保存原中断向量(利用堆栈)
push bx
cli ;关中断
push ds ;设置新中断向量
mov ax,seg new08h
mov ds,ax
mov dx,offset new08h
mov ax,2508h
int 21h
pop ds
in al,21h ;读出IMR
push ax ;保存原IMR内容
and al,0feh ;允许IRQ0,其他不变
out 21h,al ;设置新IMR内容
mov counter,0 ;设置中断次数初值
sti ;开中断
;主程序完成中断服务程序设置,可以处理其他事务
start1: cmp counter,10 ;本例的主程序仅循环等待中断
jb start1 ;中断10次退出
;
cli ;关中断
pop ax ;恢复IMR
out 21h,al
pop dx ;恢复原中断向量
pop ds
mov ax,2508h
int 21h
sti ;开中断
exit 0
; 中断服务程序
new08h proc
sti ;开中断
push ax ;保护寄存器
push si
push ds
mov ax,@data ;外部随机产生中断,DS也不确定,所以必须设置DS
mov ds,ax
inc counter ;中断次数加1
inc counter ;+1
mov si,offset intmsg ;显示信息
call dpstri
mov si,offset outmsg
call dpstri
; 此处进行修改
mov al,counter
call dispuib
call dispcrlf
mov al,20h ;发送EOI命令
out 20h,al
pop ds ;恢复寄存器
pop si
pop ax
iret ;中断返回
new08h endp
dpstri proc ;显示字符串子程序
push ax ;入口参数:DS:SI=字符串首址
push bx
dps1: mov al,[si]
cmp al,0
jz dps2
mov bx,0 ;调用ROM-BIOS功能显示al中的字符
mov ah,0eh
int 10h
inc si
jmp dps1
dps2: pop bx
pop ax
ret
dpstri endp
end start
本文内容基于微机原理老师发的 2024年微机原理上机实验要求
重要的资源:
实验任务1:熟悉DOS环境、熟悉汇编语言的开发过程和数据表达、变量定义及属性
1. 熟悉进入和退出32位控制台和16位DOS环境的方法。
2. 熟悉汇编语言的开发过程,实现教材例题2-1程序。
eg0201.asm
;eg0201.asm
include io32.inc
.data
msg byte 'Hello,Assembly!',13,10,0
.code
start:
mov eax,offset msg
call dispmsg
exit 0
end start
3. 掌握数据寻址方式,上机实现教材中的例题2-2程序。
eg0202.asm
;eg0202.asm
include io32.inc
.data
count dword 12345678h,9abcdef0h,0,0,3721h
.code
start:
mov eax,33221100h
mov ebx,eax
mov ecx,count
mov ebx,offset count
mov edx,[ebx]
mov esi,[ebx+4]
mov esi,4
mov edi,count[esi]
mov edi,[ebx+esi]
mov ecx,[ebx+esi*4]
mov edx,[ebx+esi*4-4]
mov ebp,esp
call disprd
exit 0
end start
4. 验证教材例题3-3,实现习题3.14程序。
eg0303
;eg0303.asm
include io32.inc
.data
minint = 10
wvar1 word 0,32768,65535,-32768,0,+32767
wvar2 word 1,-1,38,-38,38h,-38h
wvar3 word ?
wvar4 word 2010h,1020h
word 5 dup(minint,?)
wvar6 word 3139h,3832h
bvar6 byte 39h,31h,32h,38h
byte 0
.code
start:
mov eax,offset wvar6
call dispmsg
exit 0
end start
ex0314
include io32.inc
.data;代码段
table byte ' | 0 1 2 3 4 5 6 7 8 9 A B C D E F',13,10
byte '---+-------------------------------',13,10
byte '20 |',20h,20h,21h,20h,22h,20h,23h,20h,24h,20h,25h,20h,26h,20h,27h,20h,28h,20h,29h,20h
byte 2ah,20h,2bh,20h,2ch,20h,2dh,20h,2eh,20h,2fh,20h,13,10
byte '30 |',30h,20h,31h,20h,32h,20h,33h,20h,34h,20h,35h,20h,36h,20h,37h,20h,38h,20h,39h,20h
byte 3ah,20h,3bh,20h,3ch,20h,3dh,20h,3eh,20h,3fh,20h,13,10
byte '40 |',40h,20h,41h,20h,42h,20h,43h,20h,44h,20h,45h,20h,46h,20h,47h,20h,48h,20h,49h,20h
byte 4ah,20h,4bh,20h,4ch,20h,4dh,20h,4eh,20h,4fh,20h,13,10
byte '50 |',50h,20h,51h,20h,52h,20h,53h,20h,54h,20h,55h,20h,56h,20h,57h,20h,58h,20h,59h,20h
byte 5ah,20h,5bh,20h,5ch,20h,5dh,20h,5eh,20h,5fh,20h,13,10
byte '60 |',60h,20h,61h,20h,62h,20h,63h,20h,64h,20h,65h,20h,66h,20h,67h,20h,68h,20h,69h,20h
byte 6ah,20h,6bh,20h,6ch,20h,6dh,20h,6eh,20h,6fh,20h,13,10
byte '70 |',70h,20h,71h,20h,72h,20h,73h,20h,74h,20h,75h,20h,76h,20h,77h,20h,78h,20h,79h,20h
byte 7ah,20h,7bh,20h,7ch,20h,7dh,20h,7eh,20h,7fh,20h,13,10
byte 0
.code
start:
mov eax,offset table
call dispmsg
exit 0
end start
eg0423.asm
.686
.model flat,stdcall
option casemap:none
includelib bin\kernel32.lib
includelib bin\user32.lib
ExitProcess proto,:DWORD
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD
MessageBox equ <MessageBoxA>
NULL equ 0
MB_OK equ 0
.data
szCaption byte '消息窗口',0
outbuffer byte '本机的处理器是', 12 dup(0),0
outbufsize = sizeof outbuffer-1
.code
start: mov eax,0
cpuid ; 获得显示器信息
mov dword ptr outbuffer+outbufsize-12,ebx
mov dword ptr outbuffer+outbufsize-8,edx
mov dword ptr outbuffer+outbufsize-4,ecx
invoke MessageBox,\
NULL,addr outbuffer,addr szCaption,MB_OK
invoke ExitProcess,NULL
end start
实验任务2:熟悉汇编语言中的常用传送和运算指令的应用
ex0320.asm
include io32.inc
.code
start:
mov eax,80h
call disprf
call disphd
call dispcrlf
add eax,3
call disprf
call disphd
call dispcrlf
add eax,80h
call disprf
call disphd
call dispcrlf
add eax,3
call disprf
call disphd
call dispcrlf
call dispcrlf
mov eax,100
call disprf
call disphd
call dispcrlf
add ax,200
call disprf
call disphd
call dispcrlf
call dispcrlf
mov eax,100
call disprf
call disphd
call dispcrlf
add al,200
call disprf
call disphd
call dispcrlf
call dispcrlf
mov al,7fh
call disprf
call disphd
call dispcrlf
sub al,8
call disprf
call disphd
call dispcrlf
sub al,80h
call disprf
call disphd
call dispcrlf
sbb al,3
call disprf
call disphd
call dispcrlf
exit 0
end start
实验任务3:掌握、理解位操作、串操作类指令
ex0328.asm
include io32.inc
.data
bcd byte 92h
.code
start:
mov al,bcd
shr al,4
add al,30h
call dispc
mov al,bcd
and al,0fh
add al,30h
call dispc
exit 0
end start
实验任务4:掌握转移指令和分支程序结构
ex0405.asm
;ex0405.asm
include io32.inc
.data
no_msg byte 'Not Ready!',0
yes_msg byte 'Ready to Go!',0
.code
start:
;mov eax,58h ; 假设一个数据
mov eax,56h
;test eax,02h ; 测试D1位(使用D1=1,其他位为0的数据)
shr eax,2
;jnz yesm ; D1=1条件成立,转移
jnc yesm
mov eax,offset no_msg ; D1=0,显示没有准备好
jmp done ; 跳转过另一个分支体!
yesm: mov eax,offset yes_msg ; 显示准备好
done: call dispmsg
exit 0
end start
ex0411.asm
include io32.inc
.data
inmsg byte 'Input number(0~9):',0
ermsg byte 0dh,0ah,'ERROR! Input again:',0
.code
start:
mov eax,offset inmsg
call dispmsg
again: call readc
cmp al,'0'
jb erdisp
cmp al,'9'
ja erdisp
call dispcrlf
call dispc
jmp done
erdisp: mov eax,offset ermsg
call dispmsg
jmp again
done:
exit 0
end start
实验任务5:掌握循环指令和循环程序结构
① 掌握循环指令和循环程序结构。验证例题4-12程序,实现习题4.13程序。
eg0412
;eg0412.asm
include io32.inc
.data
string byte 'Do you have fun with Assembly?',0 ; 以0结尾的字符串
.code
start:
xor ebx,ebx ; EBX用于记录字符个数,同时也用于指向字符的指针
again: mov al,string[ebx]
cmp al,0
jz done
inc ebx ; 个数加1
jmp again ; 继续循环
done: mov eax,ebx ; 显示个数
call dispuid
exit 0
end start
ex0413
include io32.inc
.data
string byte 'Do you have fun with Assembly ?',0 ;以О结尾的字符串
space dword ?
.code
start:
mov esi,offset string
xor ebx, ebx; EBX用于记录空格数
again:
mov al,[esi]
cmp al,0
jz donecmp al, 20h ;空格的ASCII 码是20H
jne next ;不相等、不是空格,转移
inc bx ;相等、是空格,空格个数加1
next:
inc esi
jmp again ;继续循环
done:
mov space, ebx ;保存结果
mov eax,space
call dispuid
exit 0
end start
② 验证例题4-10程序。实现如下程序:进行自然数相加(1+2+3+……+N);如果(无符号整数的)累加和用一个32位寄存器存储,求出有效累加和的最大值及N的界限。
eg0410.asm
include io32.inc
.data
.code
start:
mov edx, 1
mov esi, 2
done1:
add edx, esi ; 自然数相加,求和
jc done ; 最高位进位,跳转
inc esi ; 加数加一
jmp done1 ; 重复进行自然数相加
done:
sub esi, 1 ; 加数减一,使累加和不进位而有效
mov ebx, 1
mov ecx, 2
nom:
add ebx, ecx ; 求得有效累加和
cmp ecx, esi ; 使加数到N的界限停止
jz again
inc ecx ; 加数加一
jmp nom ; 重复进行自然数相加
again:
mov eax, ebx ; 显示有效累加和的最大值
call dispuid
call dispcrlf ; 换行
mov eax, ecx ; 显示N的界限
call dispuid
exit 0
end start
来源:
Q:
现在你的环境为64位windows11系统,但是可以使用32位cmd运行make32指令。请基于使用io32.inc的32位汇编语言写一段代码,实现如下程序:进行自然数相加(1+2+3+……+N);如果(无符号整数的)累加和用一个32位寄存器存储,求出有效累加和的最大值及N的界限,并且输出这两个变量。特别注意,请将可以输出结果的完整程序代码写出。
A:
当然,我可以帮你写一段32位汇编语言的代码来实现这个功能。首先,让我们来分析一下问题。你需要计算自然数相加的累加和(1 + 2 + 3 + … + N),并且将结果存储在一个32位寄存器中。然后,你要找到有效累加和的最大值以及N的界限。
以下是一个满足你需求的汇编代码示例,使用了
io32.inc
文件:
include io32.inc
.data
.code
start:
mov edx, 1
mov esi, 2
done1:
add edx, esi ; 自然数相加,求和
jc done ; 最高位进位,跳转
inc esi ; 加数加一
jmp done1 ; 重复进行自然数相加
done:
sub esi, 1 ; 加数减一,使累加和不进位而有效
mov ebx, 1
mov ecx, 2
nom:
add ebx, ecx ; 求得有效累加和
cmp ecx, esi ; 使加数到N的界限停止
jz again
inc ecx ; 加数加一
jmp nom ; 重复进行自然数相加
again:
mov eax, ebx ; 显示有效累加和的最大值
call dispuid
call dispcrlf ; 换行
mov eax, ecx ; 显示N的界限
call dispuid
exit 0
end start
这段代码首先使用
edx
和esi
寄存器进行自然数相加,直到累加和不再进位。然后,它计算有效累加和的最大值并找到N的界限。请注意,这只是一个示例代码,你可以根据你的需求进行修改。如果你有其他问题或需要进一步的解释,请随时告知![1][2][3]
希望这对你有所帮助!