欢迎来到冰点文库! | 帮助中心 分享价值,成长自我!
冰点文库
全部分类
  • 临时分类>
  • IT计算机>
  • 经管营销>
  • 医药卫生>
  • 自然科学>
  • 农林牧渔>
  • 人文社科>
  • 工程科技>
  • PPT模板>
  • 求职职场>
  • 解决方案>
  • 总结汇报>
  • ImageVerifierCode 换一换
    首页 冰点文库 > 资源分类 > DOCX文档下载
    分享到微信 分享到微博 分享到QQ空间

    计算机组成原理汇编语言程序设计.docx

    • 资源ID:14146496       资源大小:164.43KB        全文页数:23页
    • 资源格式: DOCX        下载积分:5金币
    快捷下载 游客一键下载
    账号登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录
    二维码
    微信扫一扫登录
    下载资源需要5金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP,免费下载
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    计算机组成原理汇编语言程序设计.docx

    1、计算机组成原理汇编语言程序设计 计算机组成原理实验实验报告(实验二)学院名称:数据科学与计算机学院专业(班级):学生姓名:学号时间:2019年10月19日成绩:实验二: MIPS汇编语言程序设计实验 一. 实验目的1. 初步认识和掌握 MIPS 汇编语言程序设计的基本方法;2. 熟悉 QEMU 模拟器和 GNU/Linux 下 x86-MIPS 交叉编译环境的使用。二. 实验内容我的题目为31%4+1,第四题。【密码】编写一个程序, 先从键盘输入一个字符串(有英文字母,可能也有数字),然后显示其中数字符的个数、英文字母的个数和字符串的长度;字符串中不能有空格,若有将其删除,并将改变后的字符串按

    2、相反的顺序显示出来;输入第二个字符串,然后将输入的字符串与前面处理后的字符串比较是否相同,若相同,输出“Password Right!”,否则输出 “Password Error!”。三. 实验器材PC机一台,装有Linux操作系统的虚拟机一套,QEMU模拟器软件一套,GNU跨平台交叉编译环境一套。四. 实验过程与结果说明:根据需要书写相关内容,如:程序流程图、设计的思想与方法、分析、实验步骤和实验结果及分析等。1、程序流程图首先,遍历输入字符串并记录字符串长度,字母个数,数字个数,并把非空格字符存到分配好的空间。然后,逆转字符串并再存入另一个空间。随后再读入一个字符串,判断两者是否相等。如果

    3、相等就输出Password Right!,否则输出Password Error!2、可能用到的指令lb/lh/lw: 从存储器中读取一个byte/half word/word的数据到寄存器中.如lb $1, 0($2)sb/sh/sw: 把一个byte/half word/word的数据从寄存器存储到存储器中.如 sb $1, 0($2)add/addu:把两个定点寄存器的内容相加add $1,$2,$3($1=$2+$3);u为不带符号加。 addi/addiu:把一个寄存器的内容加上一个立即数add $1,$2,#3($1=$2+3);u为不带符号加。sub/subu:把两个定点寄存器的内

    4、容相减。and/andi:与运算,两个寄存器中的内容相与and $1,$2,$3($1=$2 & $3);i为立即数。or/ori:或运算。xor/xori:异或运算。beq/beqz/benz/bne:条件转移eq相等,z零,ne不等。j/jr/jal/jalr:j直接跳转;jr使用寄存器跳转;slt/slti/sltui:如果$2的值小于$3,那么设置$1的值为1,否则设置$1的值为0。slt $1,$2,$3。mov/movz/movn:复制,n为负,z为零。mov $1,$2; movz $1,$2,$3($3为零则复制$2到$1)。本实验主要涉及字符串和字符的操作,此外还涉及到计数。

    5、所以一般使用lb/sb和lw/sw来解决寄存器存储数据空间不足的情况。本实验涉及判断单个字符的类型,需要用到大小比较。我使用slt/slti和beq/beqz/benz/bne来跳转。另外,必须用到的还有加减法、寄存器赋值、逻辑运算等指令。3、设计流程首先我们为输入字符串和操作后的字符串分配内存空间,分配: origin_str:.space 1000 #原始输入字符串 nospace_str:.space 1000 #去除空格后的字符串 reversed_str:.space 1000 #翻转后的字符串然后分配存储计数的整形变量的内存空间: str_len: .word 0 #字符串长度 n

    6、um_let: .word 0 #字母字符数量 num_dig: .word 0 #数字字符数量打印特定的字符串使用syscall 4,预设一些可能用到的asciiz字符串。输入字符串使用syscall 8,需要把目的地址放入寄存器,如下: la $a0, str li $a1, 100 li $v0, 8 syscall遍历字符串取字符的操作可以使用不断自增当前地址+寻址的方式进行: loop: lb $t2, ($t0) add $t0, $t0, 1 #$t0地址加一 j loop题目涉及连续判断的条件。判断大于和小于都可以通过slti和slt来进行,只需要颠倒寄存器的位置即可。对连续判

    7、断条件,可以分别计算并作逻辑运算,例如,判断字符是不是数字: slti $t6, $t2, 58 # $t29+1时置位 slti $t7, $t2, 48 # $t20时置位 nor $t7, $zero, $t7 # $t7取反 and $t6, $t6, $t7 # $t6 = 0=$t2=9 beq $t6, 1, adddigit需要一个取反操作,或者把48放入寄存器中。类似的,判断是不是字母,是不是空格也使用类似的方法。循环过程中进行存数操作,每次存一个字节然后地址增加一个字节。save1: sb $t2, ($t5)addi $t5, $t5, 1 j judge遍历结束后,使用

    8、另一块空间把字符串作逆转,使用C代码的指针实现如下。 char* p1 = str; char* p2 = reversed_str + length - 1; while (*p1 != 0) *p2 = *p1; p2-; p1+; 指针可以直接用地址代替,使用MIPS汇编实现如下:reverse:la $t0, nospace_strla $t1, reversed_stradd $t2, $t3, $t4 # $t2 = nospace_str字符串的有效长度#做一个t2次的循环,不断存字节使 (reversed_str+$t2-i-1) = i(nospace_str)add $t1

    9、, $t1, $t2addi $t1, $t1, -1li $t3, 0loop:beq $t3, $t2, Retypeadd $t4, $t3, $t0lb $t5, ($t4)sub $t6, $t1, $t3sb $t5, ($t6)addi $t3, 1j loop然后再次输入一个字符串,比较两个字符串是否相等。如流程图所示,先判断长度相等与否,再判断每个字符的相等与否。length_equal:la $t0, num_letlb $t2, ($t0)la $t0, num_diglb $t3, ($t0)add $t2, $t2, $t3bne $t1, $t2, not_equa

    10、l la $t0, origin_strla $t1, reversed_strli $t3, 0if_equal:beq $t2, $t3, equallb $t4, ($t0)lb $t5, ($t1)bne $t4, $t5, not_equaladd $t0, $t0, 1 add $t1, $t1, 1add $t3, $t3, 1j if_equalnot_equal:li $v0, 4la $a0, errorsyscallj exitequal:li $v0, 4la $a0, rightsyscallexit:li $v0, 10 # 退出syscall # 系统调用如果都相

    11、等就打印right,否则打印error。先使用PCSPIM进行调试,在修改了部分bug后模拟结果如下。图1 输入正确时的程序输出图2 输入错误时的程序输出可以看到基础的功能都得到实现,尝试在 x86 环境下汇编链接代码并生成 MIPS 可执行文件,随后使用 QEMU 来运行。QEMU和PCSPIM的不同点在于使用的是linux内核调用,所以与syscall相关的代码必须得到修改。此外,由于写整数的接口无法使用,我们需要自己实现一个把整数转换为字符串的函数,用于打印该整数。基本思路还是把整数不断除10,把余数放入对应的地址,如下: #打印一个整数的代码,整数保存在t1中,返回地址保存在ra中 P

    12、rintint: #先确定该整数长度 la $t0, int_str li $t2, 10 li $t4, 0 move $t3, $t1 get_int_len: div $t3, $t2 #除10 mflo $t3 add $t4, $t4, 1 bnez $t3, get_int_len add $t5, $t0, $t4 sb $zero, ($t5) #置末尾为0 addi $t4, $t4, -1 assign: blt $t1, $t2, saveint #如果t1小于10 div $t1, $t2 #除10 mflo $t1 #商 mfhi $t3 #余数 addi $t3,

    13、$t3, 48 #acsii码 add $t5, $t0, $t4 #t5为存字节的地址 sb $t3, ($t5) #存数 addi $t4, $t4, -1 #调整地址 j assign #循环 saveint: addi $t1, $t1, 48 #acsii码 add $t5, $t0, $t4 #t5为存字节的地址 sb $t1, ($t5) #存数 printStr: li $a0, 1 la $a1, int_str li $a2, 100 li $v0, 4004 syscall jr $ra这样我们用jal调用它时,就可以直接打印出$t1中的整数了。自此程序设计环节完成。4、

    14、实验测试结果与分析尝试在linux虚拟机上运行这段程序的MIPS可执行文件,并使用不同的输入例来寻找程序的不足。基础输入例使用例子中的输入,查看到输出如下:图3 QEMU的执行结果1符合我们的预期,再尝试一下其他的测试例。长度不同的输入例查看到输出如下:图4 QEMU的执行结果2长度相同字符不同的输入例查看到输出如下:图5 QEMU的执行结果3全都是空格的输入例输出如下:图6 QEMU的执行结果4可见程序已经能够实现我们题目中给定的逻辑,并能应对一些特殊情况。五. 实验心得实验的主题是使用MIPS汇编进行程序设计,应该说MIPS汇编的难度比起X86要小了很多。比起X86它拥有更灵活的跳转语句,

    15、由此可以带来更精简的循环和递归调用;算术和逻辑运算的数据传输也变得更清晰;此外还有比较容易的变量空间分配和声明。用MIPS来做程序设计是一个很好的提升自己的过程。实验中要实现的功能很简单,如果使用C+等高级语言很快就能实现,但当我们只能使用纯粹的汇编码时,难度就上升了一个等级。原本方便的数据类型、循环等操作都要用汇编码和编译器实现,体验上和高级语言的设计过程有很大的不同。实验的另一个特点就是要在linux环境下用QEMU进行模拟。QEMU的环境和普通的MIPS环境有所不同,这要求我们灵活地进行代码修改和系统功能的调用。对我的题目,需要设计itoa的汇编代码,对别的题目可能还需要atoi的函数。

    16、这种扩展性的问题有助于我们提升资源有限情况下的解决问题能力。总之,本实验通过汇编程序设计,不仅能够提升我们的编程能力,更能加深我们对机器码的运行原理,内存空间和数据的关系,以及编译器、计算机硬件和操作系统之间的交互和协同工作关系的理解。【程序代码】 .data origin_str:.space 1000 #原始输入字符串 nospace_str:.space 1000 #去除空格后的字符串 reversed_str:.space 1000 #翻转后的字符串 int_str:.space 100 #用于储存整形的字符串 input:.asciiz Input string: stringlen

    17、gth:.asciiz String Length: letternum:.asciiz Number of letters: digitnum:.asciiz Number of digits: reversedstr:.asciiz Reversed String: retype:.asciiz Retype: right:.asciiz Password Right!n error:.asciiz Password Error!n endl:.asciiz n str_len: .word 0 #字符串长度 num_let: .word 0 #字母字符数量 num_dig: .word

    18、0 #数字字符数量.text .global mainmain: li $v0, 4004 li $a0, 1 la $a1, input #提示输入字符串 li $a2, 14 syscall li $a0, 0 la $a1, origin_str # a0 = 原始字符串地址 li $a2, 900 li $v0, 4003 syscall la $t0, origin_str #使用寄存器保存三个计数 li $t1, 0 li $t3, 0 li $t4, 0 la $t5, nospace_str #循环,计数字符串长度,字母和数字个数 #并把除空格以外的字符录入nospace_st

    19、r count: lb $t2, ($t0) beq $t2, 0, endcount #结束count循环 li $t6, 32 bne $t6, $t2, save1 # $t2!= 时存字符到nospace_str judge: add $t0, $t0, 1 #$t0地址加一 add $t1, $t1, 1 #字符串长度加一 slti $t6, $t2, 58 # $t29+1时置位 slti $t7, $t2, 48 # $t20时置位 nor $t7, $zero, $t7 # $t7取反 and $t6, $t6, $t7 # $t6 = 0=$t2=9 beq $t6, 1,

    20、adddigit slti $t6, $t2, 91 # $t2Z+1时置位 slti $t7, $t2, 65 # $t2A时置位 nor $t7, $zero, $t7 # $t7取反 and $t6, $t6, $t7 # $t6 = A=$t2=Z beq $t6, 1, addletter slti $t6, $t2, 123 # $t2z+1时置位 slti $t7, $t2, 97 # $t2a时置位 nor $t7, $zero, $t7 # $t7取反 and $t6, $t6, $t7 # $t6 = A=$t2=Z beq $t6, 1, addletter j coun

    21、t save1:#存数 sb $t2, ($t5) addi $t5, $t5, 1 j judge adddigit:#数字字符计数加一 add $t3, $t3, 1 j count addletter:#字母字符计数加一 add $t4, $t4, 1 j count #打印一个整数的代码,整数保存在t1中,返回地址保存在ra中 Printint: #先确定该整数长度 la $t0, int_str li $t2, 10 li $t4, 0 move $t3, $t1 get_int_len: div $t3, $t2 #除10 mflo $t3 add $t4, $t4, 1 bnez

    22、 $t3, get_int_len add $t5, $t0, $t4 sb $zero, ($t5) #置末尾为0 addi $t4, $t4, -1 assign: blt $t1, $t2, saveint #如果t1小于10 div $t1, $t2 #除10 mflo $t1 #商 mfhi $t3 #余数 addi $t3, $t3, 48 #acsii码 add $t5, $t0, $t4 #t5为存字节的地址 sb $t3, ($t5) #存数 addi $t4, $t4, -1 #调整地址 j assign #循环 saveint: addi $t1, $t1, 48 #ac

    23、sii码 add $t5, $t0, $t4 #t5为存字节的地址 sb $t1, ($t5) #存数 printStr: li $a0, 1 la $a1, int_str li $a2, 100 li $v0, 4004 syscall jr $ra endcount: la $t0, str_len addi $t1, $t1, -1# 输入的origin_str最后一个字符为n,所以长度要减一 sw $t1, ($t0) la $t0, num_let sw $t3, ($t0) la $t0, num_dig sw $t4, ($t0) li $v0, 4004 #打印stringl

    24、ength的一行 li $a0, 1 la $a1, stringlength li $a2, 15 syscall la $t0, str_len lw $t1, ($t0) jal Printint li $v0, 4004 li $a0, 1 la $a1, endl li $a2, 1 syscall li $v0, 4004 #打印letternum的一行 li $a0, 1 la $a1, letternum li $a2, 19 syscall #打印整形 la $t0, num_let lw $t1, ($t0) jal Printint li $v0, 4004 li $a0

    25、, 1 la $a1, endl li $a2, 1 syscall li $v0, 4004 #打印digitnum的一行 li $a0, 1 la $a1, digitnum li $a2, 18 syscall #打印整形 la $t0, num_dig lw $t1, ($t0) jal Printint li $v0, 4004 li $a0, 1 la $a1, endl li $a2, 1 syscall reverse:#逆向字符串 la $t0, num_let lw $t3, ($t0) la $t0, num_dig lw $t4, ($t0) la $t0, nospa

    26、ce_str la $t1, reversed_str add $t2, $t3, $t4 # $t2 = nospace_str字符串的有效长度 #做一个t2次的循环,不断存字节使 (reversed_str+$t2-i-1) = i(nospace_str) add $t1, $t1, $t2 addi $t1, $t1, -1 li $t3, 0 loop:#循环,直到到达有效长度 beq $t3, $t2, Retype add $t4, $t3, $t0 lb $t5, ($t4) sub $t6, $t1, $t3 sb $t5, ($t6) addi $t3, 1 j loop

    27、Retype: #打印reversed_str的一行,并请求重新输入 li $v0, 4004 li $a0, 1 la $a1, reversedstr li $a2, 17 syscall li $v0, 4004 li $a0, 1 la $a1, reversed_str li $a2, 100 syscall li $v0, 4004 li $a0, 1 la $a1, endl li $a2, 1 syscall li $v0, 4004 li $a0, 1 la $a1, retype li $a2, 8 syscall #再次获取输入 li $a0, 0 la $a1, ori

    28、gin_str li $a2, 900 li $v0, 4003 syscall la $t0, origin_str li $t1, 0 li $t2, 10 #代表字符n getlen:#获取新字符串长度 lb $t3, ($t0) beq $t2, $t3, length_equal #到达换行符时停止 add $t1, $t1, 1 add $t0, $t0, 1 j getlen length_equal: #判断长度是否相等 la $t0, num_let lw $t2, ($t0) la $t0, num_dig lw $t3, ($t0) add $t2, $t2, $t3 bne $t1, $t2, not_equal #不相等则跳转到not_equal la $t0, origin_str la $t1, reversed_str li $t3, 0 if_equal: #长度相等则判断字符是否相等 beq $t2, $t3, equal #都相等就跳转到equal lb $t4, ($t0) lb $t5, ($t1) bne $t4, $t5, not_equal add $t0, $t0, 1 add $t1, $t1, 1 add $t3, $t3, 1 j if_equal not_equal: #输


    注意事项

    本文(计算机组成原理汇编语言程序设计.docx)为本站会员主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    copyright@ 2008-2023 冰点文库 网站版权所有

    经营许可证编号:鄂ICP备19020893号-2


    收起
    展开