微机原理实验三、将AX寄存器中的16位数分成4组,每组4位,让后把这四组数分别放在AL,BL,CL,DL
功能: 将AX寄存器中的16位数分成4组,每组4位,让后把这四组数分别放在AL,BL,CL,DL
; 调试结果:
input:AX <-- 1234H
output: AL <-- 1H BL <–2H CL <–3H DL <–4H
一、 SHR 逻辑右移指令
SHR
是 x86 汇编中的逻辑右移指令,用于将一个寄存器或内存位置的二进制数向右移动指定的位数,并将移出的位保存到进位标志位(CF)中。
语法为:
SHR destination, count
destination
:要进行右移的操作数,可以是寄存器或内存位置。count
:要右移的位数,可以是立即数或者存放着位数的寄存器。
执行 SHR AH, CL
指令后,AH 寄存器中的内容向右移动 CL 寄存器中的值,移出的位被保存到进位标志位(CF)中。
1.1 误区:MOV BL, CF
注意!!有一个坑
虽然前面有说过将移出的位保存到进位标志位(CF)中但是…
CF(Carry Flag,进位标志位)是一个单独的标志位寄存器,用于标记算术操作中的进位。SHR 指令将 AH 寄存器中的内容右移指定的位数,并将被移出的位(即最右边的位)存储在 CF 中。但是,MOV 指令无法直接将 CF 寄存器中的值移动到另一个寄存器中。
因此,无法通过MOV BL, CF
来实现将 CF 中的值直接移动到 BL 寄存器中。要使用 CF 中的值,您需要先将其与其他寄存器或数据进行操作,然后将结果存储到 BL 寄存器中。
例如,您可以通过以下方式使用 CF 寄存器中的值:
; 假设您已经执行了 SHR AH, CL 指令,CF 中存储了移出的位
; 判断 CF 是否为 1(表示有进位)
CMP CF, 1
JE has_carry ; 如果 CF 为 1,则跳转到有进位的处理过程
; CF 为 0,没有进位的处理过程
...
has_carry:
; CF 为 1,有进位的处理过程
...
或者,您可以将 CF 寄存器中的值与其他数据进行逻辑或算术运算,然后将结果存储到 BL 寄存器中。
二、 实现将16位数分为四组的逻辑
MOV AX, num ; 将 num 的值加载到 AX 寄存器中,待分组的数
MOV CL,4 ; 将要右移的位数加载到 CL 寄存器中,右移 4 位,即分组为高 4 位和低 4 位
MOV BX,AX ; 将 AX 寄存器的值复制到 BX 寄存器中
MOV DX,AX ; 将 AX 寄存器的值复制到 DX 寄存器中,ax 值先保存至寄存器中
; AL 存放 AH 中的高 4 位,右移
SHR AH,CL
MOV AL,AH
; BL 存放 AH 中的低 4 位,与操作
AND BH,0FH
MOV BL,BH
MOV DH,DL ; 准备给 CL
; DL 存放 AL 中低 4 位,与操作
AND DL,0FH
; CL 存放 AL 中高 4 位,右移
SHR DH,CL
MOV CL,DH
-
MOV AX, num
:将双字寄存器num
中的值加载到 AX 寄存器中,以备后续的操作。 -
MOV CL,4
:将要进行的位移数(4)加载到 CL 寄存器中,因为我们想要将双字寄存器的值分为高低两部分,每部分各占 4 位。 -
MOV BX,AX
和MOV DX,AX
:这两行将 AX 寄存器的值分别复制到 BX 寄存器和 DX 寄存器中,以便稍后的操作。这是为了保存 AX 寄存器的值,因为我们要对它进行修改。 -
SHR AH,CL
:将 AH 寄存器中的值向右移动 CL 次,即将 AX 中的高 4 位移到 AH 中。这样就完成了高低位的分组。 -
MOV AL,AH
:将 AH 寄存器中的值移动到 AL 寄存器中,这样 AL 中就存储了原始值的高 4 位。 -
AND BH,0FH
:将 BH 寄存器中的值与 0FH(00001111B)进行按位与操作,这样就只保留了低 4 位的值,将其他位清零。 -
MOV BL,BH
:将 BH 寄存器中的值移动到 BL 寄存器中,这样 BL 中就存储了原始值的低 4 位。 -
MOV DH,DL
:将 DL 寄存器中的值移动到 DH 寄存器中,这是为了备份 DL 寄存器中的值,因为接下来要对 DL 进行操作。 -
AND DL,0FH
:将 DL 寄存器中的值与 0FH 进行按位与操作,这样就只保留了 AL 中的低 4 位的值,将其他位清零。 -
SHR DH,CL
:将 DH 寄存器中的值向右移动 CL 次,即将 AL 中的高 4 位移到 DH 中。这样就完成了对原始值的高 4 位的处理。 -
MOV CL,DH
:将 DH 寄存器中的值移动到 CL 寄存器中,这样 CL 中就存储了原始值的高 4 位。
三、实现程序完整代码(结果未打印)
下面程序的结果没有打印出来,但是可以通过调试的手段看到各寄存器的值
DATAS SEGMENT
; 此处输入数据段代码
num DW 0H ; 用于存放待分组的数
DATAS ENDS
STACKS SEGMENT
; 此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS ; 将数据段的段地址加载到 AX 寄存器中
MOV DS,AX ; 将 AX 寄存器中的数据段地址设置到 DS 寄存器,以便程序能够访问数据段中的数据
MOV AX, num ; 将 num 的值加载到 AX 寄存器中,待分组的数
MOV CL,4 ; 将要右移的位数加载到 CL 寄存器中,右移 4 位,即分组为高 4 位和低 4 位
MOV BX,AX ; 将 AX 寄存器的值复制到 BX 寄存器中
MOV DX,AX ; 将 AX 寄存器的值复制到 DX 寄存器中,ax 值先保存至寄存器中
; AL 存放 AH 中的高 4 位,右移
SHR AH,CL
MOV AL,AH
; BL 存放 AH 中的低 4 位,与操作
AND BH,0FH
MOV BL,BH
MOV DH,DL ; 准备给 CL
; DL 存放 AL 中低 4 位,与操作
AND DL,0FH
; CL 存放 AL 中高 4 位,右移
SHR DH,CL
MOV CL,DH
MOV AH,4CH ; DOS 功能号,表示"程序终止"
INT 21H ; 终止程序的执行
CODES ENDS
END START
四、使用串口打印出各寄存器的值
实现效果:
;#########################################################################
; @Description: 将AX寄存器中的16位数分成4组,
; 每组4位,让后把这四组数分别放在AL,BL,CL,DL
;* @Version: 1.0
;* @Autor: Huining Li777
;* @input: num DW 4444H
;* @output:
; AL: 4
; BL: 4
; CL: 4
; DL: 4
;#########################################################################
DATAS SEGMENT
; 此处输入数据段代码
num DW 4444H ; 用于存放待分组的数
outputAL DB 'AL: $' ; 输入提示文字
outputBL DB 'BL: $' ; 输入提示文字
outputCL DB 'CL: $' ; 输入提示文字
outputDL DB 'DL: $' ; 输入提示文字
newline DB 13, 10, '$' ; 换行符
DATAS ENDS
STACKS SEGMENT
; 此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS ; 将数据段的段地址加载到 AX 寄存器中
MOV DS,AX ; 将 AX 寄存器中的数据段地址设置到 DS 寄存器,以便程序能够访问数据段中的数据
MOV AX, num ; 将 num 的值加载到 AX 寄存器中,待分组的数
MOV CL,4 ; 将要右移的位数加载到 CL 寄存器中,右移 4 位,即分组为高 4 位和低 4 位
MOV BX,AX ; 将 AX 寄存器的值复制到 BX 寄存器中
MOV DX,AX ; 将 AX 寄存器的值复制到 DX 寄存器中,ax 值先保存至寄存器中
; AL 存放 AH 中的高 4 位,右移
SHR AH,CL
MOV AL,AH
; BL 存放 AH 中的低 4 位,与操作
AND BH,0FH
MOV BL,BH
MOV DH,DL ; 准备给 CL
; DL 存放 AL 中低 4 位,与操作
AND DL,0FH
; CL 存放 AL 中高 4 位,右移
SHR DH,CL
MOV CL,DH
MOV BH,DL ; 保存 DL 中低 4 位,用于输出
; 输出 AL、BL、CL、DH 的值
;MOV AH, 09H ; DOS 功能号,表示"输出字符串"
MOV DX, OFFSET outputAL ; 设置DX为输出字符串的地址
MOV AH, 09H ; DOS功能号,表示"打印字符串"
INT 21H ; 输出字符串到控制台
MOV DL, AL ; 将 AL 寄存器的值传递给 DL 以便输出
ADD DL, '0' ; 将数字转换为对应的 ASCII 码
MOV AH, 02H ; 设置 DOS 功能号为 "输出字符"
INT 21H ; 输出字符到控制台
MOV DX, OFFSET newline ; 设置DX为换行符的地址
MOV AH, 09H ; DOS功能号,表示"打印字符串"
INT 21H ; 输出换行符到控制台
MOV DX, OFFSET outputBL ; 设置DX为输出字符串的地址
MOV AH, 09H ; DOS功能号,表示"打印字符串"
INT 21H ; 输出字符串到控制台
MOV DL, BL ; 将 BL 寄存器的值传递给 DL 以便输出
ADD DL, '0' ; 将数字转换为对应的 ASCII 码
MOV AH, 02H ; 设置 DOS 功能号为 "输出字符"
INT 21H ; 输出字符到控制台
MOV DX, OFFSET newline ; 设置DX为换行符的地址
MOV AH, 09H ; DOS功能号,表示"打印字符串"
INT 21H ; 输出换行符到控制台
MOV DX, OFFSET outputCL ; 设置DX为输出字符串的地址
INT 21H ; 输出字符串到控制台
MOV DL, CL ; 将 CL 寄存器的值传递给 DL 以便输出
ADD DL, '0' ; 将数字转换为对应的 ASCII 码
MOV AH, 02H ; 设置 DOS 功能号为 "输出字符"
INT 21H ; 输出字符到控制台
MOV DX, OFFSET newline ; 设置DX为换行符的地址
MOV AH, 09H ; DOS功能号,表示"打印字符串"
INT 21H ; 输出换行符到控制台
MOV DX, OFFSET outputDL ; 设置DX为输出字符串的地址
INT 21H ; 输出字符串到控制台
MOV DL, BH ; 将 BH 寄存器的值传递给 DL 以便输出
ADD DL, '0' ; 将数字转换为对应的 ASCII 码
MOV AH, 02H ; 设置 DOS 功能号为 "输出字符"
INT 21H ; 输出字符到控制台
MOV AH,4CH ; DOS 功能号,表示"程序终止"
INT 21H ; 终止程序的执行
CODES ENDS
END START