当前位置: 首页 > news >正文

那些网站是专门做一些调研的简答题网络营销是什么

那些网站是专门做一些调研的,简答题网络营销是什么,网站页面怎么做地图,学校网站建设介绍范文计算机的语言#xff1a;汇编指令集 也就是指令集。本书主要介绍 MIPS 指令集。 汇编指令 算数运算#xff1a; add a,b,c # abc sub a,b,c # ab-cMIPS 汇编的注释是 # 号。 由于MIPS中寄存器大小32位#xff0c;是基本访问单位#xff0c;因此也被称为一个字 word。M…计算机的语言汇编指令集 也就是指令集。本书主要介绍 MIPS 指令集。 汇编指令 算数运算 add a,b,c # abc sub a,b,c # ab-cMIPS 汇编的注释是 # 号。 由于MIPS中寄存器大小32位是基本访问单位因此也被称为一个字 word。MIPS汇编有32个寄存器。寄存器数量是与指令集可行性相关的不是说摩尔定律越多越好。 接下来把上述抽象字母替换为寄存器表示 # f(gh)-(ij) # f,g,h,i,j in s0,s1,s2,s3,s4add $t0,$s1,$s2 add $t1,$s3,$s4 sub $s0,$t0,$t1MIPS汇编中寄存器用$两个字符表示。 然后是从存储器中取数据的指令。 # ghA[8] # g,h in s1,s2 # A address in s3 lw $t0,8($s3) # 用这种方式拿出来 add $s1,$s2,$t0MIPS采用大端编址也就是高字节存入低地址。 最低有效位最右边的位也就是 MIPS[31:0]的0位。 最高有效位31位。 如果按字节寻址正确的偏移量是 offset*4. 比如计算A[12]hA[8]h在s2A在s3中。 lw $t0,32($s3) add $t0,$s2,$t0 sw $t0,48($s3) # 写回常数操作比如 s1AddrConstant4 里存储了常量4我们可以 lw $t0,AddConstant4($s1) 把常数取出来。 或者直接使用立即数。 addi $s3,$s3,4 #加立即数需要用 addi立即数运算速度快且能耗低。 $zero 寄存器存的是常数0因为比如数据传送指令可以看做是加0指令这样可以简化数据传送指令和加法指令合并。 根据使用频率定义一些常数是加速大概率事件的方法之一。 数字存储分为无符号数和补码表示的有符号数具体算法也不再详细展开~ 指令组成 t0-t7是寄存器8-15s0-s7是寄存器16-23. 比如指令 add $t0,$s1,$s2 机器语言表示十进制为 首先开头的0字段和结尾的32字段代表 add 指令。 17 18是两个源操作数s1 s2。 8是目的操作数t0. 第五个字段没用到置0. 当然底层表示是32位二进制数。MIPS 指令都是32位。 op操作码。 rs rt两个源操作数寄存器。 rd目的操作数寄存器。 shamt位移量。 funct功能码op的变体比如 addi。 但是这种指令格式的缺陷在于长度有时候不够比如我们要处理的地址或者立即数用5位表示不了5位归根结底只能表示32个数。 因此引入了I型指令用于立即数的指令。上述指令是R型指令用于寄存器 最后一个大字段用于表示地址偏移量或者立即数。 两者都是32位指令因此复杂度没提升太多。但是计算机又怎么判断哪个是R指令哪个是I指令呢通过不同的op来判断具体指令格式。 比如lw代表rs rt是寄存器后面所有位都是addr值。 上例展示了两种不同指令的机器码。如果没有rd用第二个源操作数寄存器rt代替。 左移 sll $t2,$s0,4 # t2s04 and $t0,$t1,$t2 #t0t1 t2 or $t0,$t1,$t2 #t0t1 | t2 nor $t0,$t1,$t2 #t0~(t1 | t2), 其中一个是0的话相当于 not条件跳转 beq $s1,$s2,L1 #两者相等则跳转到L1处 bne $s1,$s2,L1比如 if(ij)fgh;else fg-h; bne $s3,$s4,Else add $s0,$s1,$s2 j Exit Else:sub $s0,$s1,$s2 Exit:循环跳转类似的跳转比较方法。 Loop: #循环体 bne $s0,$s1,Exit #如果两者不等跳出循环 j Loop Exit:小于指令 slt $t0,$s3,$s4 #t01 if s3s4 sltu $t0,$s3,$s4 #无符号数 slti $t0,$s3,10 #带立即数的比较因为遵循简单性原则没有“小于则跳转”的指令。当然我们可以先用slt再用beq判断t0的值这样两条简单的指令效率也会更高。 过程函数 一个抽象的概念程序执行中的一部分过程类似函数。过程不需要知道调用者的全部信息只需要知道自己完成过程所需要的部分。 涉及到传入参数移交控制权给过程过程返回后获取指定的存储区域来获取过程的返回值。 a0~a3是传入参数v0 v1是函数返回值ra是返回起始点的返回地址寄存器。 jaljump and link跳转并且把返回值存入ra。然后使用 jr 指令跳回。jr 是无条件跳转到后面寄存器中存储的地址。 jr ra调用函数的部分是调用者 caller。被调用的函数是 callee。 jal 其实就是把 pc4 的值存入 ra。 栈 比如函数里我们需要用到更多的寄存器不止这5个。 我们可以先把原来寄存器的值压入栈然后把那些寄存器给栈。 栈 sp 还是高地址向低地址增长。 比如函数计算 f(gh)-(ij) 求和。传入四个参数是 a0-a3f存到 s0 里以及过程中两个加法运算需要用到两个临时变量 t0 t1。因此这三个寄存器的值需要入栈保存。 入栈代码 addi $sp,$sp,-12 sw t0,8($sp) sw t1,4($sp) sw s0,0($sp)运算结束后 s0 寄存器中的值应该交给 一个返回值寄存器 add $v0,$s0,$zero出栈代码 lw t0,8($sp) lw t1,4($sp) lw s0,0($sp) addi $sp,$sp,12不过实际上MIPS 规定是 s0-s7 系列寄存器要存callee 存和恢复。t0-t9 系列不用。 嵌套过程 不调用其他过程的过程叫叶过程。不过我们知道只由叶过程组成的程序很少。 非叶过程必须压栈所有必须保留的寄存器caller 保存 a0-a3 参数寄存器和 t0-t9 临时寄存器callee 保存 s0-s7 保存寄存器和 ra 返回地址。callee 保存的寄存器能保证调用时和返回时的值是一样的而临时寄存器和参数寄存器返回时值可变。 因此如果 caller 自己留着 t 系列有用你就自己保存一下别指望 callee 保存没用就不用存。 比如一个递归代码c 语言表示如下 int fact(int n) {if(n1)return 1;else return n*fact(n-1); }MIPS 汇编代码 首先先盘点一下非叶过程要用的寄存器。 计算步骤比较简单不用保存临时寄存器。 n 是 a0 参数需要保存。 ra 需要保存。 s0-s7 没用到。 也就是只有 a0 ra 需要保存。然后再判断一下在什么位置保存caller 还是 callee 每次调用 fact 函数时fact 函数是 callee自己保存 ra。如果 fact 又递归调用了下一个自己那么他自己又变成了 caller需要保存 a0. 或者另一种逻辑每次都保存 ra 和 a0如果递归调用了自己则恢复 ra a0否则不用恢复 ra a0 因为值没变 fact:addi $sp,$sp,-8sw $ra,4($sp)sw $a0,0($sp)slti $t0,$a0,1 # 判断是否 1beq $t0,$zero,L1 # 1 则准备进入下一层循环addi $v0,$zero,1addi $sp,$sp,8jr $ra # ra a0 值没变这里把栈指针恢复一下返回值赋值一下就结束函数了L1:addi $a0,$a0,-1jal fact # 递归调用非叶过程lw $ra,4($sp)lw $a0,0($sp)addi $sp,$sp,8 # 恢复寄存器原值mul $v0,$a0,$v0 # 乘上本轮递归的 njal $ra补充全局和 static 变量是静态的静态变量存放在静态数据区中在过程进入和退出过程中也存在而动态变量只在过程中存在在过程进入和退出过程中不存在。MIPS 有一个 global pointer $gp 指向静态数据区。 递归过程开销还是比较大的尽量用迭代代替会好一些 过程帧 有些过程内部一部分寄存器也要压栈这部分寄存器和局部变量片段叫做过程帧或活动记录。 部分 MIPS 软件会使用 $fp 帧指针和 $sp 共同标识哪一部分是过程帧也有的软件会使用寄存器来保存过程帧的指针。 帧指针还可以保存超过4个的参数超出部分可以根据帧指针在内存中找到其位置。 当然一个很重要的原则还是过程返回前必须把这一部分恢复为空。 代码段 在堆中要为静态变量和动态数据提供空间。 正文代码段。 静态数据全局和 static 变量。 动态动态变量。 c语言中分配释放堆空间通过显式的 malloc 和 free 函数。缺点在于忘记手动释放容易导致内存泄露释放早了又会产生 dangling pointer 悬摆指针程序指向不想指向的位置。而 java 就会自动内存分配和回收无用单元 XD 这是 MIPS 保存的寄存器约定。这算作是一种加速大概率事件因为统计证明保存8个寄存器和10个暂存器在大多数时候已经足够。 人机交互 如今计算机大多使用8位字节来表示字符又名 ASCII 码。 lb sb只读取写入一个字节到目标寄存器的最右边八位。 字符通常被组合成字符串的形式。标志字符串长度有三种方案1. 字符串首位是其长度2. 使用单独的变量存储字符串长度3. 使用特殊的结束符标识字符串的结束c语言采用的是方案3使用 \0 标识。 比如对于一个字符串复制的实现c语言的逻辑为循环遍历一位位复制字符直到碰到 \0 为止。 假设目标数组和源数组基址在 $a0 $a1 中i 存储在 $s0 中。 strcpy:addi $sp,$sp,-4sw $s0,0($sp)add $s0,$zero,$zero # i置0L1:add $t1,$a1,$s0 # t1存放源数组的当前指针lbu $t2,0($t1) # 无符号字节读取add $t3,$a0,$s0 # t1存放目标数组的当前指针sbu $t2,0($t3)beq $t2,$zero,L2 # 跳出结束复制addi $s0,$s0,1 # 这里和之前以字为单位做处理不同我们是以字节为单位做处理因此i而不是i4L2:lw $s0,0($sp)addi $sp,$sp,4jr $rajava 采用的是更通用的 Unicode 现如今大多数 Web 页面采用的方案保存字符单位是16位。MIPS 可以直接通过 lh sh lhu shu 来读取写入半字长正好一个字符长。因此 java 字符串占用内存是 c 的两倍但是字符串操作更快。 java 使用一个字来存储字符串总长。 因为 MIPS 的栈地址必须按字对齐因此 c 中一个 char 8位哪怕有5个 char也会分配8个 char 的长度来对齐2字。java 的半字也是类似的需要对齐机制。 32位立即数 正常立即数都是16位的嘛但是我们有时候需要他更长到 32位。 lui load upper immediate 指令可以把16位立即数复制到寄存器的高16位中。 这样比如一个32位数我们可以先 lui 前16位到一个寄存器中再插入低16位 ori。 MIPS 中有一个专门的 $at 寄存器来临时存储32位立即数。 不过需要注意使用32位立即数和16位立即数比如 addi 和逻辑操作时高16位都是参与运算的16位立即数的高16位逻辑运算视作全0。 寻址 J 系列跳转指令是6位操作码26位跳转地址跳转范围是2^26. 条件分支 b 系列指令因为还需要位存放待比较的寄存器构造为6位操作码5位寄存器15位寄存器216位地址。 如果这个16位地址就代表目标地址那就局限了能跳转的地址范围是 2^16 个字那程序总长不能超过这个范围了那也太没意思了。 为此采取的方案是这16位地址是偏移地址跳转方式是当前基址16位偏移地址一位符号位也就是±2^15。因为大部分循环指令 条件指令都小于 2^15这也是一种加速大概率事件所以这种做法很够用。这种方法叫做 PC 相对寻址。 而且 MIPS 地址都是按字对齐的所以相较字节地址能寻址范围扩大了4倍比如 j 系列寻址范围是 2^28 的字节地址。 但是 PC 地址不是32位的吗实际上其中只有低28位可以被跳转指令修改。如果程序大小超过了 2^28需要通过寄存器跳转方式跳转。 b 系列是相对寻址且相对下一条指令也就是 80016 处的 addi $s3,$s3,1 跳转到 80032 处的 Exit即 880016. j 系列是直接寻址20000*480000 跳转。 这也是一种有趣的思想我说总是感觉条件取反汇编和正常 if 思维不太一样呢。 MIPS 的寻址模式总的来说有以下几种 基址寻址给定寄存器中地址偏移地址。 伪直接寻址PC 高位和26位形式地址拼接而成。 虽然本书中 MIPS 是32位寻址但几乎所有微处理器都可以扩展到64位寻址向上兼容。 并行与同步指令 并行执行任务时同步机制就比较重要防止数据竞争。 这里和学操作系统的时候感觉很像。通过互斥锁对一组数据进行原子读写操作。 我们采用指令对链接取数条件存数 llsc 来实现。 again: addi $t0,$zero,1 ; 尝试上锁1ll $t1,0($s1) ; 获取 s1 初始值sc $t0,0($s1) ; 保存 s1 值。如果发现 ll 获取值和 sc 保存值不同t0 置零beq $t0,$zero,again ; 如果 t0 又变成0了执行失败重新执行add $s4,$zero,$t1 ; 做操作后面章节还会再深入展开滴。 翻译执行程序 早期硬件存储容量小且编译器效率不高都是写汇编的。 汇编器支持一些机器语言的变种比如 move 指令实际是 add $t0,$zero,$t0 汇编器也能翻译但是其实没有 move 指令这类指令叫伪指令。 汇编器将叫符号表。 汇编文件生成的目标文件包含 目标文件头描述目标文件组成大小位置等信息。代码段静态数据段重定位信息一些依赖于绝对地址的指令和数据。符号表未定义的剩余标记如分支和数据传输指令中的标号都放到一个表中待查阅表中数据由标号和地址成对组成如外部引用。调试信息。 链接器将各个机器语言目标文件组合起来变为可执行文件。这其中主要经历的步骤如下 根据文件中的重定位信息和符号表把各个文件中的旧地址组合起来做成新地址。为什么不一开始就生成可执行文件并设定好新地址而非要各个文件编译成单独目标文件后再重新修改因为这样修改效率更快。解析完外部链接后链接器再决定所有模块在内存中的位置并用重定位的绝对地址表示。先处理绝对的地址再布局剩下的相对地址。 总的来说可执行文件和目标文件是相同格式的但是其中不包含未解决的引用除非是一些外部链接比如链接到库函数。 例题如下是 A B 两个目标文件链接并给出更新后的地址。 处理外部引用。A 引用了 XBB引用了 YA。代码段从 0x400000 处开始数据段从 0x10000000 处开始所以 A 代码段是 0x400000-0x400100过程 A 文件头标识了他的正文大小没有用到 0x400100数据段是 0x10000000-0x10000020B 紧随其后代码段是 0x400100-0x400300数据段是 0x10000020-0x10000050。两者第一条跳转指令是跳转到对方的第一条指令位置。jal伪直接寻址则 jal 跳转地址就是对方第一条指令的地址a 是跳到 400100b 是跳到 400000. 再加上 jal 跳转规则是丢弃最左边两位实际跳转是基址4* jal两者实际跳转地址是 100040 和 100000. 指令是递增增长的gp 初始地址是 0x10008000存取数据是依靠基址寄存器存取实际取指地址想取到 0x10000000 的话偏移量应为 0x8000. 大端数据是递减增长的 创建好了可执行文件后加载器来把数据指令放入内存。 读取文件头知晓代码段和数据大小创建足够大的正文和数据空间复制数据指令主函数参数复制入栈顶栈指针指向空跳转到启动例程复制参数并调用程序的 main 函数main 函数返回时调用 exit 终止程序。 前面提到的这种链接方式是静态链接缺点在于如果库函数更新了之前连接过的库函数也没变。而且也会导致尽管不是用到了库中的所有内容库还是会被全部加载进来程序会很大。 而动态链接 DLL 是运行的时候才链接库。一开始的动态链接也是会添加所有库中的内容的晚过程连接的 DLL 是只会链接调用的例程。 第二次就避免了一些间接跳转。 java 程序的执行经过两个步骤。 javac 编译 java 语言变为 class 二进制字节文件。jvm 逐条解释翻译字节码文件。 jvm 效率太低了后来又出现了 JIT 即时编译器辅助会将运行频繁的代码块认定为“热点代码”编译为与本地平台相关的机器码并进行优化来提高效率。 项目示例sort sll $t0,$a1,2 add $t1,$a0,$t0 lw $t2,0($t1) lw $t0,4($t1) sw $t0,4($t1) sw $t2,0($t1) jr ra循环1 move $s0,$zero for1tst:slt $t0,$s0,$a1beq $t0,$zero,$exit1...for loop 2...addi $s0,$s0,1j for1tst exit1:循环2不要动循环1里的 s 寄存器可以随便重新改 t 寄存器。 addi $s1,$s0,-1 for2snd:slti $t0,$s1,0bne $t0,$zero,$exit2sll $t1,$s1,2add $t2,$t1,$a0lw $t3,0($t2)lw $t4,4($t2)slt $t0,$t4,$t3beq $t0,$zero,$exit2...swap...addi $s1,$s1,-1j for2snd exit2:swap 调用先存原来的参数寄存器再修改参数寄存器。 # 传参 move $s2,$a0 move $s3,$a1 move $a0,$s2 move $a1,$s1jal swap最后在合并之前开头和结尾我们还要加上对保存换源寄存器的操作。我们用到了 s0-s3所以要保存 s0-s3 和 ra。 sort:addi $sp,$sp,-20sw $ra,16($sp)sw $s3,12($sp)sw $s2,8($sp)sw $s1,4($sp)sw $s0,0($sp)move $s2,$a0move $s3,$a1 # 不管是否要调用先存一下参数move $s0,$zerofor1tst:slt $t0,$s0,$a1beq $t0,$zero,$exit1addi $s1,$s0,-1for2snd:slti $t0,$s1,0bne $t0,$zero,$exit2sll $t1,$s1,2add $t2,$t1,$a0lw $t3,0($t2)lw $t4,4($t2)slt $t0,$t4,$t3beq $t0,$zero,$exit2move $a0,$s2move $a1,$s1jal swapaddi $s1,$s1,-1j for2sndexit2:addi $s0,$s0,1j for1tstexit1:lw $ra,16($sp)lw $s3,12($sp)lw $s2,8($sp)lw $s1,4($sp)lw $s0,0($sp)addi $sp,$sp,20jr $ra调用 swap 函数的部分也许可以通过内联的方式优化即把交换操作直接展开而不是调用函数减少跳转开销。但是因此代码量增加如果 cache 缺失率增加反而得不偿失了。 另外实际上 $sp 总是保存4个参数寄存器 -16. 因为 c 会有一个可变参数 vararg 选项允许一个指针参数。 数组与指针 数组是下标*4 加到数组基址上指针是数组基址4. 如下程序示例是数组清零的两种实现 对比其他指令集 ARM 架构 ARMAdvanced RISC Machines是一种精简指令集计算机RISC架构广泛用于移动设备、嵌入式系统、嵌入式芯片和微控制器等领域。ARM 设计注重能效和低功耗因此在移动设备领域表现出色。ARM 架构具有多个版本和变体包括 ARMv7、ARMv8 等其中 ARMv8 引入了 64 位执行模式AArch64。 x86 架构 x86 架构是一种复杂指令集计算机CISC架构主要用于个人计算机、服务器和桌面系统。x86 架构的代表性处理器包括 Intel 的 Pentium、Core i 系列和 AMD 的 Ryzen 系列。x86 架构在性能和功能上具有很高的灵活性适用于广泛的计算任务。 MIPS 架构 MIPSMicroprocessor without Interlocked Pipeline Stages是一种精简指令集计算机RISC架构早期在工作站和嵌入式系统中广泛使用。MIPS 设计注重简化指令集以提高执行效率。尽管在一些领域使用逐渐减少但MIPS架构仍然在某些嵌入式、网络设备和嵌入式控制器中有所应用。 by gpt 比如arm 的比较和条件分支MIPS 是把比较结果存在一个寄存器中ARM 是比较结果设置为条件码包括负数零进位溢出。比如 CMP 比较将两个寄存器值相减结果设置条件码。 这样 arm 拥有的寄存器数量少一倍16个但是仍然能完成任务而且某些情况下根据条件码会直接跳过不需要执行的指令节省代码空间的同时也节省了运行时间。 arm 的立即数48 的扩展形式。 也支持对第二个寄存器参数做移位操作同样位数能表示更多数据。 arm 也支持对寄存器组操作通过16位掩码决定加载 / 复制16位寄存器中的哪些寄存器。 x86 的缺点主要在于寻址范围有限而且 cisc 拖慢效率。 总的来说MIPS 指令规整长度统一只采用32个寄存器来保证对速度的要求通过加速大概率事件等思想来优化指令组成。
http://www.zqtcl.cn/news/910236/

相关文章:

  • 房山区网站建设wordpress自动采集翻译插件怎么用
  • 郴州做网站 郴网互联网站制作公司起名
  • 织梦做的的网站首页显示空白查企业营业执照的网站
  • 葫芦岛公司做网站外贸西班牙语网站建设
  • 广西住房和城乡建设厅培训中心网站首页wordpress建导航
  • 企业建立网站需要提供什么建立网站需要多长钱
  • 科技企业网站源码下载网页设计公司哪家效果好
  • 成都龙泉工程建设有限公司网站网络科技有限公司网站建设策划书
  • 温州网站建设对比赣州招聘网最新招聘
  • 网站建设什么时候好商丘创小资网络有限公司
  • 做网站不切片可以吗wordpress导入表单
  • 广告公司的网站建设价格wordpress简洁淘宝客免费主题
  • 内蒙古建设安全监督站的网站做网站排名多少钱
  • 自学网站平面设计友链大全
  • go语言做的网站哪个公司搭建网站
  • 网站地图抓取正邦设计创始人
  • 济南建网站公司佛山做营销型网站建设
  • 网站总体策划的内容有哪些做网站排名seo
  • 网站备案上传照片几寸上海网站排名提升
  • 重庆cms建站系统丰都网站建设联系电话
  • 网络教学平台昆明理工大学优化大师的功能有哪些
  • 个人主题网站做的步骤一流的网站建设
  • 公司网站建设规划国外搜索关键词的网站
  • 石家庄网站快速优化排名国内做性视频网站有哪些
  • 易居做网站网页设计的发展
  • 开一个网站建设公司好产品销售型的网站
  • 苍梧县网站建设南京网站建设 雷仁网络
  • 四川网站制作成都wordpress 移动支付
  • 山西网站开发二次开发做自媒体可以参考的外国网站
  • 合肥 网站设计大学生创新创业大赛项目计划书