如何在 TASM 中将一个字符的位从一个位置移动到另一个位置?
How to move a char's bit from one position into another in TASM?
我必须编写一个程序,从文件中读取字符,移动每个字符中的位,并将这些更改的字符写入 TASM 中的新文件。
我编写了一个从文件中读取字符并将其写入新文件的程序,但我不知道如何移动字符中的位。
例如,这里是我们的字符文件:
▼ ▼
! // 00100001
" // 00100010
# // 00100011
$ // 00100100
这将是我们更改了字符的新文件(第 2 位到第 7 位):
▼ ▼
! // 00100001
b // 01100010
c // 01100011
$ // 00100100
如何在 TASM 中移动字符中的那个位?
编辑:
这不是 的重复问题,因为我需要检测所需的位是 0 还是 1,必须知道要使用什么,OR 或 AND,然后在 1 和中设置正确的位其余位在0,或适当的位在0,其余位在1,然后执行OR或AND。这是一个有点不同的问题。
为此,通过屏蔽除要测试的位以外的所有内容来测试 "source" 位,然后根据结果值是否为零有条件地分支。然后您可以设置或清除 "destination" 位。
因此,例如,假设您的 char 在 AL 寄存器中,
TEST AL,2 ; TEST sets zero flag if the result of ANDing is zero,
JZ BIT_IS_ZERO ; so there is no need to do a separate CMP
; not zero, so fall through to BIT_IS_ONE, no need for a JMP
BIT_IS_ONE:
OR AL,64 ; set bit 7; define constant make easier to understand
JMP DONE
BIT_IS_ZERO:
AND AL,191 ; mask off bit 7; ditto on defining constant for this
; fall through to DONE, no need for a JMP here
DONE:
根据您的目标芯片,您可能需要使用 AND 而不是 TEST。 AND 修改要测试的寄存器,所以你必须保留另一个副本并在 setting/clearing 位之前加载它,但其他都是一样的。
您也可以使用 SHL,通过使用 AND 清除除您关心的位以外的所有位,然后使用 SHL 将剩余位(无论是 0 还是 1)从第 2 位移到第 7 位,然后清除 "destination" 字符(一个单独的副本)中的那个位,最后将两者组合在一起。我上面提供的方法可能更容易理解和实现,但它确实引入了使用SHL时不需要的分支指令,因此效率低于SHL。
我能想到的最直截了当的英文句子"copy 2nd bit into 7th bit"直译成8086汇编:
mov al,char ; input value
mov ah,al ; copy of value for 2nd bit extraction
and ah,0b00000010 ; keep only 2nd bit in copy
; ^ and ah,2 if your assembler doesn't support "0b"
shl ah,5 ; move 2nd bit to position of 7th bit
and al,0b10111111 ; clear 7th bit in char
; ^ and al,0BFh if your assembler doesn't support "0b"
or al,ah ; merge "second bit" into cleared one at 7th
关于位掩码常量计算:
当你有一些二进制值,如 1010 1001
= 8 位掩码,当被 AND
使用时,它将在掩码中设置“1”的任何地方保留原始值,并且它将清除“0”所在的位。
这应该很容易想象,如果你知道你想通过AND/OR/XOR/TEST
指令操作哪一位,比如"obvious"。
但是你不想将这么长的二进制数输入汇编器(另外,如果你使用一些过时的,它甚至不会为你编译)...所以用十六进制写它 0A9h
.就像 "obvious" 作为二进制一样,每 4 位组成一个十六进制数字,所以 1010
是 8+2 = 10 = Ah
(将“0A”写入编辑器,前导 0 告诉汇编器 "A"属于数字,不属于标签)而1001
是8+1 = 9
,将“9”写入编辑器,然后添加"h"标记为十六进制值,完成。
Matt 是如何算出小数的 191
(= 0xBF = 0b10111111
) - 我不知道,可能他使用了计算器或者他在脑子里做了 255-64(全掩码减去一位)。虽然我可以通过想象 head.
中的位模式来即时编写 BF
十六进制形式
还读了这个,维基文章是IMO相当不错:
https://en.wikipedia.org/wiki/Bitwise_operation
我必须编写一个程序,从文件中读取字符,移动每个字符中的位,并将这些更改的字符写入 TASM 中的新文件。
我编写了一个从文件中读取字符并将其写入新文件的程序,但我不知道如何移动字符中的位。
例如,这里是我们的字符文件:
▼ ▼
! // 00100001
" // 00100010
# // 00100011
$ // 00100100
这将是我们更改了字符的新文件(第 2 位到第 7 位):
▼ ▼
! // 00100001
b // 01100010
c // 01100011
$ // 00100100
如何在 TASM 中移动字符中的那个位?
编辑:
这不是
为此,通过屏蔽除要测试的位以外的所有内容来测试 "source" 位,然后根据结果值是否为零有条件地分支。然后您可以设置或清除 "destination" 位。
因此,例如,假设您的 char 在 AL 寄存器中,
TEST AL,2 ; TEST sets zero flag if the result of ANDing is zero,
JZ BIT_IS_ZERO ; so there is no need to do a separate CMP
; not zero, so fall through to BIT_IS_ONE, no need for a JMP
BIT_IS_ONE:
OR AL,64 ; set bit 7; define constant make easier to understand
JMP DONE
BIT_IS_ZERO:
AND AL,191 ; mask off bit 7; ditto on defining constant for this
; fall through to DONE, no need for a JMP here
DONE:
根据您的目标芯片,您可能需要使用 AND 而不是 TEST。 AND 修改要测试的寄存器,所以你必须保留另一个副本并在 setting/clearing 位之前加载它,但其他都是一样的。
您也可以使用 SHL,通过使用 AND 清除除您关心的位以外的所有位,然后使用 SHL 将剩余位(无论是 0 还是 1)从第 2 位移到第 7 位,然后清除 "destination" 字符(一个单独的副本)中的那个位,最后将两者组合在一起。我上面提供的方法可能更容易理解和实现,但它确实引入了使用SHL时不需要的分支指令,因此效率低于SHL。
我能想到的最直截了当的英文句子"copy 2nd bit into 7th bit"直译成8086汇编:
mov al,char ; input value
mov ah,al ; copy of value for 2nd bit extraction
and ah,0b00000010 ; keep only 2nd bit in copy
; ^ and ah,2 if your assembler doesn't support "0b"
shl ah,5 ; move 2nd bit to position of 7th bit
and al,0b10111111 ; clear 7th bit in char
; ^ and al,0BFh if your assembler doesn't support "0b"
or al,ah ; merge "second bit" into cleared one at 7th
关于位掩码常量计算:
当你有一些二进制值,如 1010 1001
= 8 位掩码,当被 AND
使用时,它将在掩码中设置“1”的任何地方保留原始值,并且它将清除“0”所在的位。
这应该很容易想象,如果你知道你想通过AND/OR/XOR/TEST
指令操作哪一位,比如"obvious"。
但是你不想将这么长的二进制数输入汇编器(另外,如果你使用一些过时的,它甚至不会为你编译)...所以用十六进制写它 0A9h
.就像 "obvious" 作为二进制一样,每 4 位组成一个十六进制数字,所以 1010
是 8+2 = 10 = Ah
(将“0A”写入编辑器,前导 0 告诉汇编器 "A"属于数字,不属于标签)而1001
是8+1 = 9
,将“9”写入编辑器,然后添加"h"标记为十六进制值,完成。
Matt 是如何算出小数的 191
(= 0xBF = 0b10111111
) - 我不知道,可能他使用了计算器或者他在脑子里做了 255-64(全掩码减去一位)。虽然我可以通过想象 head.
BF
十六进制形式
还读了这个,维基文章是IMO相当不错: https://en.wikipedia.org/wiki/Bitwise_operation