全面的介绍——基于ARM的微机和基于8086的微机的代码层面的区别

这篇具有很好参考价值的文章主要介绍了全面的介绍——基于ARM的微机和基于8086的微机的代码层面的区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

初析

ARM 和 8086这两种架构有很多方面的区别,包括指令集、寻址模式、性能、功耗、市场等。
全面的介绍——基于ARM的微机和基于8086的微机的代码层面的区别,arm开发,汇编,单片机,考研,嵌入式硬件,面试,蓝桥杯

全面的介绍——基于ARM的微机和基于8086的微机的代码层面的区别,arm开发,汇编,单片机,考研,嵌入式硬件,面试,蓝桥杯

指令集类型

ARM 和 8086 属于不同的指令集类型。ARM 是一种精简指令集(RISC),它的指令数量较少,长度相同,执行速度较快,适合流水线操作。8086 是一种复杂指令集(CISC),它的指令数量较多,长度不同,执行速度较慢,适合高级语言编译。

例如,下面是一个实现两个 32 位无符号整数相加的 ARM 汇编代码:

 MOV R0, #0x12345678 ; R0 = 0x12345678
 MOV R1, #0x87654321 ; R1 = 0x87654321
 ADD R2, R0, R1      ; R2 = R0 + R1

下面是一个实现同样功能的 8086 汇编代码:

  MOV AX, 0x5678 ; AX = 0x5678
  MOV BX, 0x4321 ; BX = 0x4321
  ADD AX, BX     ; AX = AX + BX
  MOV CX, 0x1234 ; CX = 0x1234
  MOV DX, 0x8765 ; DX = 0x8765
  ADC CX, DX     ; CX = CX + DX + CF

可以看出,ARM 代码只需要三条指令,而 8086 代码需要六条指令。ARM 代码中的每条指令都可以在一个时钟周期内完成,而 8086 代码中的每条指令都需要多个时钟周期。ARM 代码中的每条指令都可以直接操作 32 位的寄存器,而 8086 代码中的每条指令都只能操作 16 位的寄存器,所以需要用两个寄存器来表示一个 32 位的数,并且需要用进位标志(CF)来处理高位的进位。

寻址方式

ARM 和 8086 有不同的寻址模式。寻址模式是指定操作数在存储器中的位置的方式。ARM 支持的寻址模式较少,主要有立即数寻址、寄存器寻址、寄存器间接寻址、基址变址寻址等。8086 支持的寻址模式较多,主要有立即数寻址、寄存器寻址、直接寻址、寄存器间接寻址、基址变址寻址、相对寻址、段寄存器寻址等。
例如,下面是一个使用基址变址寻址的 ARM 汇编代码:

    LDR R0, [R1, R2] ; R0 = Memory[R1 + R2]

下面是一个使用基址变址寻址的 8086 汇编代码:

    MOV AX, [BX+SI] ; AX = Memory[BX + SI]

可以看出,ARM 代码中的基址变址寻址可以使用任意两个寄存器作为基址和变址,而 8086 代码中的基址变址寻址只能使用 BX 或 BP 作为基址,SI 或 DI 作为变址。ARM 代码中的基址变址寻址可以直接访问 32 位的存储器地址,而 8086 代码中的基址变址寻址需要加上段寄存器的值来形成 20 位的存储器地址。

性能和功耗

ARM 和 8086 有不同的性能和功耗特点。ARM 的性能优势在于它的指令执行速度快,流水线效率高,寄存器数量多,可以减少存储器访问次数。8086 的性能劣势在于它的指令执行速度慢,流水线效率低,寄存器数量少,需要频繁访问存储器。

例如,下面是一个实现斐波那契数列的 ARM 汇编代码:

   MOV R0, #10 ; R0 = 10, 要计算的项数
   MOV R1, #0  ; R1 = 0, 第一项
   MOV R2, #1  ; R2 = 1, 第二项
   MOV R3, #0  ; R3 = 0, 循环
loop:
   CMP R3, R0  ; 比较 R3 和 R0
   BGE end     ; if R3 >= R0, 分支结束
   ADD R4, R1, R2 ; R4 = R1 + R2, 下一项
   MOV R1, R2  ; R1 = R2, 更新第一项
   MOV R2, R4  ; R2 = R4, 更新第二项
   ADD R3, R3, #1 ; R3 = R3 + 1, 使循环数加1
   B loop      ; 分支循环
end:
   ; R1包含斐波拉契数列的最后一项

下面是一个实现斐波那契数列的 8086 汇编代码:

    MOV CX, 10 ; CX = 10, 要计算的项数
    MOV AX, 0  ; AX = 0, 第一项
    MOV BX, 1  ; BX = 1, 第二项
loop:
    CMP CX, 0  ; 比较 CX 和 0
    JE end     ; if CX == 0, 跳转到尾
    ADD DX, AX, BX ; DX = AX + BX, 第二项
    MOV AX, BX ; AX = BX, 更新第一项
    MOV BX, DX ; BX = DX, 更新第二项
    DEC CX     ; CX = CX - 1, 减去循环数
    JMP loop   ; 跳转循环
end:
    ; AX 包含斐波那契数列的最后一项

可以看出,ARM 代码只需要八条指令,而 8086 代码需要九条指令。ARM 代码中的每条指令都可以在一个时钟周期内完成,而 8086 代码中的每条指令都需要多个时钟周期。ARM 代码中的每条指令都可以直接操作 32 位的寄存器,而 8086 代码中的每条指令都只能操作 16 位的寄存器,所以需要用 DX 来存放下一项的高位。

ARM 代码中使用了条件分支指令,可以减少无用的跳转,而 8086 代码中使用了无条件跳转指令,会增加流水线的开销。

ARM 的功耗优势在于它的指令集简单,电路结构简洁,运行频率低,可以节省电能。8086 的功耗劣势在于它的指令集复杂,电路结构复杂,运行频率高,会消耗更多的电能。

例如,下面是一个比较 ARM 和 8086 的功耗的表格:

CPU Frequency Power Energy per Instruction
ARM 25 MHz 0.5 W 0.02 nJ
8086 5 MHz 1.5 W 0.3 nJ

可以看出, ARM 的功耗是 8086 的三分之一,而每条指令的能耗是 8086 的十五分之一。这意味着 ARM 可以在相同的电池容量下运行更长的时间,也可以在相同的时间内执行更多的指令。这就是为什么 ARM 适合用于移动设备和嵌入式系统,而 8086 适合用于个人电脑和服务器。

具体分析

下面,我将结合具体实例,从10个方面解析8086和 ARM 之间的区别。

跳转指令 (Jump)

跳转指令用于改变程序的执行流程,根据条件或地址进行转移。

ARM 和 8086 的跳转指令有以下区别:

  • ARM 的跳转指令有 B 和 BL 两种,B 用于无条件跳转,BL 用于子程序调用。8086 的跳转指令有 JMP、CALL、RET 等,JMP 用于无条件跳转,CALL 用于子程序调用,RET 用于子程序返回。
  • ARM 的跳转指令可以在指令后加上条件码,表示只有在满足条件时才执行跳转,例如 BEQ 表示等于时跳转,BNE 表示不等于时跳转。8086 的跳转指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。
  • ARM 的跳转指令可以使用寄存器或标号作为跳转目标,例如 B R0 表示跳转到 R0 寄存器中的地址,B loop 表示跳转到 loop 标号处。8086 的跳转指令只能使用标号或内存地址作为跳转目标,例如 JMP loop 表示跳转到 loop 标号处,JMP [BX] 表示跳转到 BX 寄存器中的地址。

例如,下面是一个使用跳转指令实现循环打印 10 个字符的 ARM 汇编代码:

    MOV R0, #10 ; R0 = 10, 循环数
    MOV R1, #65 ; R1 = 65, ASCII 码 中的'A'
loop:
    CMP R0, #0  ; 比较 R0 和 0
    BEQ end     ; if R0 == 0, 分支结束
    BL print    ; 调用打印子列
    ADD R1, R1, #1 ; R1 = R1 + 1, 增加 ASCII 码值
    SUB R0, R0, #1 ; R0 = R0 - 1,减少循环数
    B loop      ; 分支循环
end:
    ;结束

下面是一个使用跳转指令实现同样功能的 8086 汇编代码:

    MOV CX, 10 ; CX = 10, 循环数
    MOV AL, 65 ; AL = 65, ASCII 值中的'A'
loop:
    CMP CX, 0  ;比较 CX 和 0
    JE end     ; if CX == 0, 跳转到尾
    CALL print ; 调用打印子列
    INC AL     ; AL = AL + 1, 增加 ASCII 值
    DEC CX     ; CX = CX - 1, 减少循环数
    JMP loop   ; 跳转循环
end:
    ; 结束

数据传送指令 (Data Transfer)

数据传送指令用于在寄存器、存储器和端口之间传送数据。ARM 和 8086 的数据传送指令有以下区别:

  • ARM 的数据传送指令有 LDR 和 STR 两种,LDR 用于从存储器加载数据到寄存器,STR 用于从寄存器存储数据到存储器。8086 的数据传送指令有 MOV、IN、OUT 等,MOV 用于在寄存器、存储器和立即数之间传送数据,IN 用于从端口输入数据到寄存器,OUT 用于从寄存器输出数据到端口。
  • ARM 的数据传送指令可以使用不同的寻址模式,例如立即数寻址、寄存器寻址、寄存器间接寻址、基址变址寻址等。8086 的数据传送指令也可以使用不同的寻址模式,例如立即数寻址、寄存器寻址、直接寻址、寄存器间接寻址、基址变址寻址、相对寻址、段寄存器寻址等。
  • ARM 的数据传送指令可以在指令后加上条件码,表示只有在满足条件时才执行数据传送,例如 LDREQ 表示等于时加载,STRNE 表示不等于时存储。8086 的数据传送指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用数据传送指令实现从存储器读取一个字节并输出到端口的 ARM 汇编代码:

    LDR R0, =data ; R0 = 数据地址
    LDRB R1, [R0] ; R1 = 数据的字节值
    STR R1, =port ; 将 R1 输出到端口

下面是一个使用数据传送指令实现同样功能的 8086 汇编代码:

    MOV SI, data ; SI = 数据地址
    MOV AL, [SI] ; AL = 数据的字节值
    OUT port, AL ; 将 AL 输出到端口

算术运算指令 (Arithmetic Operations)

算术运算指令用于在寄存器或存储器中进行加、减、乘、除等运算。ARM 和 8086 的算术运算指令有以下区别:

  • ARM 的算术运算指令有 ADD、SUB、MUL、DIV 等,ADD 用于加法运算,SUB 用于减法运算,MUL 用于乘法运算,DIV 用于除法运算。8086 的算术运算指令有 ADD、SUB、MUL、DIV、INC、DEC、NEG、CMP 等,ADD 用于加法运算,SUB 用于减法运算,MUL 用于无符号数乘法运算,DIV 用于无符号数除法运算,INC 用于增量运算,DEC 用于减量运算,NEG 用于取负运算,CMP 用于比较运算。
  • ARM 的算术运算指令可以使用不同的操作数,例如立即数、寄存器、存储器等。8086 的算术运算指令也可以使用不同的操作数,例如立即数、寄存器、存储器等。
  • ARM 的算术运算指令可以在指令后加上条件码,表示只有在满足条件时才执行算术运算,例如 ADDEQ 表示等于时加,SUBNE 表示不等于时减。8086 的算术运算指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用算术运算指令实现计算两个数的最大公约数的 ARM 汇编代码:

    ; 假设 R0 和 R1 存放两个要求最大公约数的数,R2 存放余数,R3 存放最大公约数
    ; 先比较 R0 和 R1 的大小,确保 R0 大于等于 R1
    CMP R0, R1 ; 比较 R0 和 R1
    BGE loop ; 如果 R0 大于等于 R1,跳转到 loop
    MOV R2, R0 ; 否则,交换 R0 和 R1
    MOV R0, R1
    MOV R1, R2
loop:
    UDIV R2, R0, R1 ; R2 = R0 / R1,无符号除法,得到余数
    CMP R2, #0 ; 比较 R2 和 0
    BEQ done ; 如果 R2 等于 0,跳转到 done
    MOV R0, R1 ; 否则,将 R1 赋值给 R0
    MOV R1, R2 ; 将 R2 赋值给 R1
    B loop ; 跳转到 loop
done:
    MOV R3, R1 ; 将 R1 赋值给 R3,此时 R3 就是最大公约数

下面是一个使用算术运算指令实现同样功能的 8086 汇编代码:

    ; 假设 AX 和 BX 存放两个要求最大公约数的数,DX 存放余数,CX 存放最大公约数
    ; 先比较 AX 和 BX 的大小,确保 AX 大于等于 BX
    CMP AX, BX ; 比较 AX 和 BX
    JAE loop ; 如果 AX 大于等于 BX,跳转到 loop
    MOV DX, AX ; 否则,交换 AX 和 BX
    MOV AX, BX
    MOV BX, DX
loop:
    XOR DX, DX ; 清空 DX
    DIV BX ; DX:AX / BX,无符号除法,商在 AX,余数在 DX
    CMP DX, 0 ; 比较 DX 和 0
    JE done ; 如果 DX 等于 0,跳转到 done
    MOV AX, BX ; 否则,将 BX 赋值给 AX
    MOV BX, DX ; 将 DX 赋值给 BX
    JMP loop ; 跳转到 loop
done:
    MOV CX, BX ; 将 BX 赋值给 CX,此时 CX 就是最大公约数```

注:计算两个数的最大公约数的一种常用方法是辗转相除法,即用较大的数除以较小的数,然后用较小的数除以余数,重复这个过程,直到余数为零,此时的除数就是最大公约数。

逻辑运算指令 (Logical Operations)

逻辑运算指令用于在寄存器或存储器中进行与、或、非、异或等运算。ARM 和 8086 的逻辑运算指令有以下区别:

  • ARM 的逻辑运算指令有 AND、ORR、EOR、MVN 等,AND 用于按位与运算,ORR 用于按位或运算,EOR 用于按位异或运算,MVN 用于按位取反运算。8086 的逻辑运算指令有 AND、OR、XOR、NOT 等,AND 用于按位与运算,OR 用于按位或运算,XOR 用于按位异或运算,NOT 用于按位取反运算。
  • ARM 的逻辑运算指令可以使用不同的操作数,例如立即数、寄存器、存储器等。8086 的逻辑运算指令也可以使用不同的操作数,例如立即数、寄存器、存储器等。
  • ARM 的逻辑运算指令可以在指令后加上条件码,表示只有在满足条件时才执行逻辑运算,例如 ANDEQ 表示等于时与,ORRNE 表示不等于时或。8086 的逻辑运算指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用逻辑运算指令实现计算两个数的奇偶性的 ARM 汇编代码:

    MOV R0, #12 ; R0 = 12, 第一个数字
    MOV R1, #18 ; R1 = 18, 第二个数字
    AND R2, R0, #1 ; R2 = R0 & 1, R0 的最低有效位
    AND R3, R1, #1 ; R3 = R1 & 1, R1 的最低有效位
    CMP R2, #0  ; 比较 R2 和 0
    BEQ even1   ; if R2 == 0, 分支到 even1
    BL odd1     ; else, 调用 odd1 子例
even1:
    BL even2    ; 调用 even2 子例程
    CMP R3, #0  ; 比较 R3 和 0
    BEQ even2   ; if R3 == 0, 分支到 even2
    BL odd2     ; else, 调用 odd2 子例程
even2:
    BL even3    ; 调用 even3 子例程

下面是一个使用逻辑运算指令实现同样功能的 8086 汇编代码:

    MOV AX, 12 ; AX = 12, 第一个数字
    MOV BX, 18 ; BX = 18, 第二个数字
    AND AL, 1  ; AL = AX & 1, AX 的最低有效位
    AND BL, 1  ; BL = BX & 1, BX 的最低有效位
    CMP AL, 0  ; 比较 AL 和 0
    JE even1   ; if AL == 0, 跳转到 even1
    CALL odd1  ; else, 调用 odd1 子例程
even1:
    CALL even2 ; 调用 even2 子例
    CMP BL, 0  ; 比较 BL 和 0
    JE even2   ; if BL == 0, 跳转到even2
    CALL odd2  ; else, 调用 odd2 子例
even2:
    CALL even3 ; 调用 even3 子例

移位运算指令 (Shift Operations)

移位运算指令用于在寄存器或存储器中进行左移、右移、循环移位等运算。ARM 和 8086 的移位运算指令有以下区别:

  • ARM 的移位运算指令有 LSL、LSR、ASR、ROR 等,LSL 用于逻辑左移运算,LSR 用于逻辑右移运算,ASR 用于算术右移运算,ROR 用于循环右移运算。8086 的移位运算指令有 SHL、SHR、SAR、ROR、ROL 等,SHL 用于逻辑左移运算,SHR 用于逻辑右移运算,SAR 用于算术右移运算,ROR 用于循环右移运算,ROL 用于循环左移运算。
  • ARM 的移位运算指令可以使用不同的操作数,例如立即数、寄存器、存储器等。8086 的移位运算指令也可以使用不同的操作数,例如立即数、寄存器、存储器等。
  • ARM 的移位运算指令可以在指令后加上条件码,表示只有在满足条件时才执行移位运算,例如 LSLEQ 表示等于时左移,LSRNE 表示不等于时右移。8086 的移位运算指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用移位运算指令实现计算一个数的二进制表示中有多少个 1 的 ARM 汇编代码:

    MOV R0, #12 ; R0 = 12, 要计数的数字
    MOV R1, #0  ; R1 = 0, 计数器
loop:
    CMP R0, #0  ; 比较 R0 和 0
    BEQ end     ; if R0 == 0, 分支结束
    AND R2, R0, #1 ; R2 = R0 & 1, R0 的最低有效位
    ADD R1, R1, R2 ; R1 = R1 + R2, 如果 R2 为 1,则递增计数
    LSR R0, R0, #1 ; R0 = R0 >> 1, 右移 R0 1 位
    B loop      ; 分支循环
end:
    ; R1 包含 R0 中的 1 个

下面是一个使用移位运算指令实现同样功能的 8086 汇编代码:

    MOV AX, 12 ; AX = 12, 要计数的数字
    MOV CX, 0  ; CX = 0, 计数器
loop:
    CMP AX, 0  ; 比较 AX 和 0
    JE end     ; if AX == 0, 跳转到尾
    AND AL, 1  ; AL = AX & 1, AX 的最低有效位
    ADD CX, AX ; CX = CX + AX, 如果 AL 为 1,则递增计数
    SHR AX, 1  ; AX = AX >> 1, 右移 AX 1 位
    JMP loop   ; 跳转循环
end:
    ; CX 包含 AX 中的 1 个

位操作指令 (Bit Operations)

位操作指令用于在寄存器或存储器中进行位测试、位设置、位清除等运算。ARM 和 8086 的位操作指令有以下区别:

  • ARM 的位操作指令有 TST、TEQ、BIC 等,TST 用于按位与测试运算,TEQ 用于按位异或测试运算,BIC 用于按位清除运算。8086 的位操作指令有 BT、BTS、BTR、BTC 等,BT 用于位测试运算,BTS 用于位设置运算,BTR 用于位清除运算,BTC 用于位反转运算。
  • ARM 的位操作指令可以使用不同的操作数,例如立即数、寄存器、存储器等。8086 的位操作指令也可以使用不同的操作数,例如立即数、寄存器、存储器等。
  • ARM 的位操作指令可以在指令后加上条件码,表示只有在满足条件时才执行位操作,例如 TSTEQ 表示等于时测试,BICNE 表示不等于时清除。8086 的位操作指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用位操作指令实现判断一个数是否为 2 的幂的 ARM 汇编代码:

    MOV R0, #16 ; R0 = 16, 要检查的号码
    SUB R1, R0, #1 ; R1 = R0 - 1, 从 R0 中减去 1
    TST R0, R1  ; test R0 & R1
    BEQ power   ; if R0 & R1 == 0, 分支power
    BL notpower ; else, 调用 NotPower 子例
power:
    BL power2   ; 调用 Power2 子例程

下面是一个使用位操作指令实现同样功能的 8086 汇编代码:

    MOV AX, 16 ; AX = 16, 要检查的号码
    DEC AX     ; AX = AX - 1, 将 AX 减 1
    BT AX, 0   ; 测试 AX 的第 0 位
    JC notpower ; if CF == 1, 跳转到 NotPower
    JZ power   ; if ZF == 1, 跳到power
    CALL notpower ; else, 调用 NotPower 子例
power:
    CALL power2 ; 调用 Power2 子例

栈操作指令 (Stack Operations)

栈操作指令用于在栈中进行数据的压入和弹出。ARM 和 8086 的栈操作指令有以下区别:

  • ARM 的栈操作指令有 PUSH 和 POP 两种,PUSH 用于将一个或多个寄存器的值压入栈中,POP 用于将一个或多个寄存器的值从栈中弹出。8086 的栈操作指令有 PUSH 和 POP 两种,PUSH 用于将一个寄存器或存储器的值压入栈中,POP 用于将一个寄存器或存储器的值从栈中弹出。
  • ARM 的栈操作指令可以使用不同的寄存器,例如 R0-R15 等。8086 的栈操作指令只能使用 SP 和 BP 两个寄存器作为栈指针和基指针。
  • ARM 的栈操作指令可以在指令后加上条件码,表示只有在满足条件时才执行栈操作,例如 PUSHEQ 表示等于时压栈,POPNE 表示不等于时弹栈。8086 的栈操作指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用栈操作指令实现将两个数的和和差保存到栈中的 ARM 汇编代码:

    MOV R0, #12 ; R0 = 12, 第一个数字
    MOV R1, #18 ; R1 = 18, 第二个数字
    ADD R2, R0, R1 ; R2 = R0 + R1, 和
    SUB R3, R0, R1 ; R3 = R0 - R1, 差
    PUSH {R2, R3} ; 将 R2 和 R3 推送到堆栈

下面是一个使用栈操作指令实现同样功能的 8086 汇编代码:

    MOV AX, 12 ; AX = 12, 第一个数字
    MOV BX, 18 ; BX = 18, 第二个数字
    ADD CX, AX, BX ; CX = AX + BX, 和
    SUB DX, AX, BX ; DX = AX - BX, 差
    PUSH CX ; 将 CX 推送到堆栈
    PUSH DX ; 将 DX 推送到堆栈

输入输出指令 (Input/Output)

输入输出指令用于在 CPU 和外部设备之间进行数据的交换。ARM 和 8086 的输入输出指令有以下区别:

  • ARM 的输入输出指令没有专门的指令,而是使用数据传送指令和存储器映射的方式来实现,即将外部设备的地址映射到存储器空间中,然后使用 LDR 和 STR 指令来进行数据的读写。8086 的输入输出指令有 IN 和 OUT 两种,IN 用于从端口输入数据到寄存器,OUT 用于从寄存器输出数据到端口。
  • ARM 的输入输出指令可以使用不同的寄存器,例如 R0-R15 等。8086 的输入输出指令只能使用 AL 或 AX 作为数据寄存器,DX 或立即数作为端口号。
  • ARM 的输入输出指令可以在指令后加上条件码,表示只有在满足条件时才执行输入输出,例如 LDREQ 表示等于时加载,STRNE 表示不等于时存储。8086 的输入输出指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用输入输出指令实现从键盘输入一个字符并显示到屏幕的 ARM 汇编代码:

    LDR R0, =keyboard ; R0 = 键盘的地址
    LDRB R1, [R0] ; R1 = 键盘的字节值
    LDR R0, =screen ; R0 = 屏幕地址
    STRB R1, [R0] ; 将 R1 输出到屏幕

下面是一个使用输入输出指令实现同样功能的 8086 汇编代码:

    MOV DX, keyboard ; DX = 键盘的端口号
    IN AL, DX ; AL = 键盘的字节值
    MOV DX, screen ; DX = 屏幕的端口号
    OUT DX, AL ; 将 AL 输出到屏幕

中断指令 (Interrupt)

中断指令用于触发或响应中断,中断是一种特殊的事件,可以打断程序的正常执行流程,转而执行一段中断服务程序。ARM 和 8086 的中断指令有以下区别:

  • ARM 的中断指令有 SVC、BKPT、WFI、WFE 等,SVC 用于产生软件中断,BKPT 用于产生断点中断,WFI 用于等待中断发生,WFE 用于等待事件发生。8086 的中断指令有 INT、IRET、CLI、STI 等,INT 用于产生软件中断,IRET 用于从中断服务程序返回,CLI 用于禁止中断,STI 用于允许中断。
  • ARM 的中断指令可以使用不同的参数,例如 SVC #n 表示产生编号为 n 的软件中断,BKPT #n 表示产生编号为 n 的断点中断。8086 的中断指令只能使用立即数作为参数,例如 INT 21h 表示产生编号为 21h 的软件中断。
  • ARM 的中断指令可以在指令后加上条件码,表示只有在满足条件时才执行中断,例如 SVCNE #n 表示不等于时产生软件中断,WFEQ 表示等于时等待事件。8086 的中断指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用中断指令实现从键盘输入一个字符并显示到屏幕的 ARM 汇编代码:

    SVC #0 ; 生成软件中断以从键盘读取字符
    ; 该字符在 R0 中返回
    SVC #1 ; 生成软件中断以将字符写入屏幕
    ; 该字符取自 R0

下面是一个使用中断指令实现同样功能的 8086 汇编代码:

    MOV AH, 1 ; 将功能代码设置为1,从键盘读取一个字符
    INT 21h ; 生成软件中断以调用 DOS 服务
    ; 字符在 AL 中返回
    MOV AH, 2 ; 将功能代码设置为2,在屏幕上写入一个字符
    INT 21h ; 生成软件中断以调用 DOS 服务
    ; 状态取自DL

协处理器指令 (Coprocessor)

协处理器指令用于在 CPU 和协处理器之间进行数据的交换和运算,协处理器是一种辅助的处理器,可以增强 CPU 的功能,例如浮点运算、图形处理、加密解密等。ARM 和 8086 的协处理器指令有以下区别:

  • ARM 的协处理器指令有 MRC、MCR、CDP 等,MRC 用于从协处理器寄存器读取数据到 CPU 寄存器,MCR 用于从 CPU 寄存器写入数据到协处理器寄存器,CDP 用于在协处理器上执行运算。8086 的协处理器指令有 FLD、FST、FADD、FSUB 等,FLD 用于从存储器或寄存器加载数据到协处理器栈,FST 用于从协处理器栈存储数据到存储器或寄存器,FADD 用于在协处理器栈上执行浮点加法运算,FSUB 用于在协处理器栈上执行浮点减法运算。
  • ARM 的协处理器指令可以使用不同的协处理器编号,例如 MRC p15, 0, R0, c1, c0, 0 表示从编号为 15 的协处理器的 c1 寄存器的第 0 位读取数据到 R0 寄存器。8086 的协处理器指令只能使用 8087 协处理器,它有八个 80 位的浮点寄存器,组成一个栈结构,称为 ST0-ST7。
  • ARM 的协处理器指令可以在指令后加上条件码,表示只有在满足条件时才执行协处理器指令,例如 MRCEQ 表示等于时读取,MCRNE 表示不等于时写入。8086 的协处理器指令没有条件码,而是使用单独的条件转移指令,例如 JE 表示等于时跳转,JNE 表示不等于时跳转。

例如,下面是一个使用协处理器指令实现计算两个浮点数的和和差的 ARM 汇编代码:

    LDR R0, =num1 ; R0 = num1 的地址
    LDR R1, =num2 ; R1 = num2 的地址
    VLDR S0, [R0] ; S0 = num1 的浮点值
    VLDR S1, [R1] ; S1 = num2 的浮点值
    VADD F32 S2, S0, S1 ; S2 = S0 + S1, 和
    VSUB F32 S3, S0, S1 ; S3 = S0 - S1, 差

下面是一个使用协处理器指令实现同样功能的 8086 汇编代码:

    FLD num1 ; 将 num1 的浮点值加载到 ST0
    FLD num2 ; 将 num2 的浮点值加载到 ST0,ST1 = num1
    FADD ; 将 ST0 和 ST1 相加,ST0 = num1 + num2,即总和
    FST sum ; 将 ST0 存储到总和
    FSUB ; 减去 ST0 和 ST1,ST0 = num1 - num2,差值
    FST diff ; 将 ST0 存储到 diff

总结

在进行以上的基于实例的分析以后,来做个小总结。

基于arm的微机原理与接口技术和基于8086的微机原理与接口技术的代码和指令方面有很多区别,主要体现在以下几个方面:

  • 架构类型:arm是一种精简指令集(RISC)的架构,而8086是一种复杂指令集(CISC)的架构。RISC架构的指令数量较少,格式统一,执行速度快,但需要更多的寄存器和存储器访问。CISC架构的指令数量较多,格式不一,执行速度慢,但可以减少编程的难度和存储器的占用。
  • 指令长度:arm的指令长度为32位,而8086的指令长度为8位到16位不等。这意味着arm的指令可以携带更多的信息,而8086的指令需要更多的前缀和后缀来扩展功能。
  • 寻址模式:arm的寻址模式较少,主要有立即数寻址、寄存器寻址、寄存器间接寻址、基址变址寻址等。而8086的寻址模式较多,除了上述寻址模式外,还有直接寻址、相对寻址、段寻址、堆栈寻址等。寻址模式的多少影响了指令的灵活性和复杂性。
  • 寄存器数量和功能:arm的寄存器数量较多,有16个通用寄存器,其中一个作为程序计数器,另一个作为当前程序状态寄存器。而8086的寄存器数量较少,只有14个寄存器,其中有8个通用寄存器,4个段寄存器,一个程序计数器,一个标志寄存器。arm的寄存器功能较为统一,可以用于数据操作、地址计算、条件判断等。而8086的寄存器功能较为分散,有些寄存器只能用于特定的用途,如段寄存器只能用于段寻址,标志寄存器只能用于条件判断等。
  • 数据类型和操作:arm支持的数据类型有字节(8位)、半字(16位)、字(32位)和双字(64位),可以进行逻辑、算术、移位、乘法、除法等操作。而8086支持的数据类型有字节(8位)、字(16位)和双字(32位),可以进行逻辑、算术、移位、乘法、除法、字符串处理等操作。arm的数据操作一般都是寄存器到寄存器的,而8086的数据操作可以是寄存器到寄存器、寄存器到存储器、存储器到寄存器或存储器到存储器的。

除了代码和指令方面的区别外,基于ARM和基于8086的微机原理与接口技术还有其他方面的区别,如:文章来源地址https://www.toymoban.com/news/detail-838181.html

  • 系统结构:arm的系统结构一般是基于片上系统(SOC)的,将CPU、存储器、外设等集成在一个芯片上,实现高度的集成和低功耗。而8086的系统结构一般是基于总线的,将CPU、存储器、外设等通过总线连接起来,实现高度的扩展和兼容。
  • 中断处理:arm的中断处理一般是基于向量的,将不同的中断源分配不同的中断向量,通过中断向量表来定位中断服务程序。而8086的中断处理一般是基于优先级的,将不同的中断源分配不同的优先级,通过中断控制器来选择优先级最高的中断服务程序。
  • 存储器管理:arm的存储器管理一般是基于分页的,将存储器划分为固定大小的页,通过页表来实现逻辑地址到物理地址的映射。而8086的存储器管理一般是基于分段的,将存储器划分为不同大小的段,通过段基址和段偏移量来实现逻辑地址到物理地址的转换。

参考

  1. 阎波. 微处理器系统结构与嵌入式系统设计-3版 [M]. 北京:电子工业出版社,2020.8 ISBN
    978-7-121-35822-7
  2. Intel 公司. IA-32 Intel Architecture Software Developer’s Manual. Volume 1. Basic Architecture.
  3. 周明德,张淑玲. 80X86、80X87结构与汇编语言程序设计. 北京:清华大学出版社,1993.

到了这里,关于全面的介绍——基于ARM的微机和基于8086的微机的代码层面的区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从Vue层面 - 解析发布订阅模式和观察者模式区别

    观察者模式和发布订阅模式作为日常开发中经常使用到的模式,我一直不能做到很好的区分。最近在看Vue的源码,里面设计到了观察者模式,比较感兴趣,就去学习了下,这里做个总结吧。 基于一个 事件中心 ,接收通知的对象是订阅者,需要先订阅某个事件,触发事件的对

    2024年02月15日
    浏览(27)
  • Nginx详细介绍(并从技术层面深度剖析)

    Nginx (engine x) 是一个轻量级,高性能的 HTTP 和 反向代理 服务,也是一个IMAP/POP3/SMTP服务。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。 Nginx 是一个

    2024年01月20日
    浏览(39)
  • 基于8086家具门安全控制系统设计

    ** 单片机设计介绍,基于8086家具门安全控制系统设计   # 8086家具门安全控制系统设计介绍 8086家具门安全控制系统是一种用于保护家具和保证室内安全的系统。该系统基于8086微处理器,通过电磁锁和传感器来控制家具门的开关和监测室内环境。本文将介绍该系统的设计思

    2024年02月04日
    浏览(28)
  • 基于8086的中断方式4*4矩阵键盘

    1.设计要求 使,8086, 8255 和 8259 等芯片,设计中断方式 4X4 矩阵键盘(16 进制 0—F),且单个数 码管显示按键信息。 2.设计思路 分析要求,使用 8255 和 8259 等芯片,设计中断方式 4X4 矩阵键盘(16 进制 0—F),且单个数码管显示按键信息。那么得到主要信息为,本系统主要由以

    2024年02月09日
    浏览(24)
  • 全面地介绍 将二维数据矩阵插值拟合为二维曲面方程——基于matlab

    要利用matlab将二维数据矩阵拟合成一个二维曲面方程,首先,我们得明白什么是插值和拟合。下面,从对洋流数据的处理入手,先以一个基本的流程为例,进行问题的概述,然后介绍两种具体的方法。 根据已知的数据点,生成一个连续的函数,可以在任意位置求值。matlab 提

    2024年04月11日
    浏览(30)
  • 代码层面探索前端性能

    最近在做性能优化,具体优化手段,网上铺天盖地,这里就不重复了。 性能优化可分为以下几个维度:代码层面、构建层面、网络层面。 本文主要是从代码层面探索前端性能,主要分为以下 4 个小节。 使用 CSS 替代 JS 深度剖析 JS 前端算法 计算机底层 这里主要从动画和 CS

    2024年02月08日
    浏览(26)
  • java分布式项目需要进行注意的事项(代码层面)

    在分布式系统中,使用主键自增会引发一系列问题。以下是几个主要原因: 高并发冲突:在分布式系统中,多个节点同时生成主键时会产生冲突。因为每个节点都有自己的自增序列,同时生成的主键可能会有重复。 单点故障:使用主键自增通常依赖于一个中心节点或数据库

    2024年04月22日
    浏览(33)
  • 【AI大模型应用开发】【LangFuse: LangSmith平替,生产级AI应用维护平台】0. 快速上手 - 基本功能全面介绍与实践(附代码)

    大家好,我是同学小张,日常分享AI知识和实战案例 欢迎 点赞 + 关注 👏, 持续学习 , 持续干货输出 。 +v: jasper_8017 一起交流💬,一起进步💪。 微信公众号也可搜【同学小张】 🙏 本站文章一览: 前面我们介绍了LangChain无缝衔接的LangSmith平台,可以跟踪程序运行步骤,提

    2024年03月21日
    浏览(52)
  • 微机课设 | 基于STC15单片机的简易数字密码锁设计

    在日常的生活和工作中,住宅与部门的安全防范、单位的文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决。若使用传统的机械式钥匙开锁,人们常需携带多把钥匙, 使用极不方便, 且钥匙丢失后安全性即大打折扣。在安全技术防范领域,具有防盗报警功能的

    2024年02月04日
    浏览(38)
  • Java LongAdder类介绍、代码示例、底层实现原理及与分段锁的区别

    LongAdder是Java并发包(java.util.concurrent)中的一个类,用于高效地实现多线程环境下的加法操作。 在多线程环境中,如果多个线程同时对同一个变量进行加法操作,会存在竞争条件(race condition)。传统的加法操作使用synchronized或者锁来保证线程安全,但是在高并发情况下

    2024年02月12日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包