mov sreg, r/m16 在16位和32位编程中的区别

  总结于《X86汇编语言 从实模式到保护模式》

  仅适用于X86系列处理器

1. 两者的区别:

  例:mov ds, ax
  A.在指定16位编译模式下,产生的二进制码是 8E D8
  B.在指定32位编译模式下(在某些老式的编译器中才会出现的),产生的二进制码是 66 8E D8

2. 影响:
  A.加上0x66的前缀是为了反转默认的操作数大小。因为32位模式下,默认的操作数大小是4字节的,而指令中的源操作数是16位的AX。
  B.有前缀和没前缀相比,CPU在执行时会多花一个额外的时钟周期。

3. 解决
  A. 使用32位的源操作数,但是高地址部分会被截断。也让人难以理解。如:
    mov ds, eax
    编译出来的二进制指令是:8E D8
  B. 使用NASM编译器,NASM编译器无论在什么样的处理器模式下,编译出来的指令都是一样的。

[BITS 16]
MOV DS, AX    ;8E D8
MOV DS, EAX ;8E D8
[BITS 32]
MOV DS, AX    ;8E D8
MOV DS, EAX    ;8E D8

 

转载于:https://www.cnblogs.com/Jer-/p/3176551.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是对代码的注释: ``` .cseg ; 指定代码段 .org $0 ; 代码从地址0开始 jmp Reset ; 跳转到Reset函数 duan:.db $c0,$f9,$a4,$b0,$99,$92,$82,$f8,$80,$90 ; 数码管段码表 wei: .db $ef,$df,$bf,7f ; 数码管码表 .org $009A ; 程序从地址0x009A开始 Reset: ldi r16,0xFF ; 初始化r16为0xFF out DDRB,r16 ; 配置DDRB为输出模式 out PORTB,r16 ; 初始化PORTB为高电平 out DDRD,r16 ; 配置DDRD为输出模式 out PORTD,r16 ; 初始化PORTD为高电平 out DDRE,r16 ; 配置DDRE为输出模式 out PORTE,r16 ; 初始化PORTE为高电平 ldi r16,7 ; 初始化r16为7 ldi XL,0x20 ; 初始化XL为0x20 ldi XH,0x03 ; 初始化XH为0x03 i0: ; 循环开始标签 st X+,r16 ; 将r16写入指针指向的地址,同时指针+1 dec r16 ; 将r16减1 cpi r16,0x00 ; r16和0x00比较 brne i0 ; 如果不相等,跳转到i0 mov r1,r16 ; 将r16的值赋给r1 main: ; 主函数 ldi r17,0x77 ; 初始化r17为0x77 sbiw X,4 ; 将指针X减4 L1: ld r18,X+ ; 从指针X指向的地址读取数据,同时指针+1,将读取的数据存入r18 ldi ZL,low(duan<<1) ; 将duan的地址左移1,然后取低8,存入ZL寄存器 ldi ZH,high(duan<<1) ; 将duan的地址左移1,然后取高8,存入ZH寄存器 add ZL,r18 ; 将r18的值加到ZL adc ZH,r1 ; 将r1的值加到ZH,同时加上进标志 lpm r18,Z ; 从指向的地址读取程序存储器的数据,存入r18 call LED ; 调用LED函数 lsl r17 ; 左移r17一,相当于乘以2 mov r19,r17 ; 将r17的值赋给r19 ori r19,0x0f ; 将r19的低4设为1 out PORTD,r19 ; 输出r19到PORTD call Delayms ; 调用Delayms函数 ldi r16,0xff ; 初始化r16为0xff out PORTD,r16 ; 将r16输出到PORTD cpi XL,0x24 ; 将XL和0x24比较 brne L1 ; 如果不相等,跳转到L1 jmp main ; 跳转到主函数 LED: ; LED函数 in r0,sreg ; 将sreg的值读入r0 push r0 ; 将r0压入堆栈 push r18 ; 将r18压入堆栈 push r17 ; 将r17压入堆栈 mov r17,r18 ; 将r18的值赋给r17 lsr r17 ; 右移r17一,相当于除以2 andi r17,0x40 ; 将r17和0x40进行按与运算 in r16,PORTB ; 从PORTB读取数据,存入r16 andi r16,0xbf ; 将r16和0xbf进行按与运算 eor r17,r16 ; 将r16和r17进行按异或运算 out PORTB,r17 ; 将r17输出到PORTB mov r17,r18 ; 将r18的值赋给r17 lsl r17 ; 左移r17一,相当于乘以2 andi r17,0xe0 ; 将r17和0xe0进行按与运算 in r16,PORTE ; 从PORTE读取数据,存入r16 andi r16,0x10 ; 将r16和0x10进行按与运算 eor r17,r16 ; 将r16和r17进行按异或运算 andi r18,0x0f ; 将r18和0x0f进行按与运算 or r17,r18 ; 将r18和r17进行按或运算 out PORTE,r17 ; 将r17输出到PORTE pop r17 ; 从堆栈取出r17 pop r18 ; 从堆栈取出r18 pop r0 ; 从堆栈取出r0 out sreg,r0 ; 将r0输出到sreg ret ; 返回 Delay: ; Delay函数 ldi r22,1 ; 初始化r22为1 delay1: ldi r23,255 ; 初始化r23为255 delay2: ldi r24,255 ; 初始化r24为255 delay3: dec r24 ; 将r24减1 brne delay3 ; 如果r24不为0,跳转到delay3 dec r23 ; 将r23减1 brne delay2 ; 如果r23不为0,跳转到delay2 dec r22 ; 将r22减1 brne delay1 ; 如果r22不为0,跳转到delay1 ret ; 返回 .exit ; 代码结束标志 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值