I have to write a program which is reading chars from a file, moving bits in every char and writing those changed chars to a new file in TASM.
I've written a program which is reading chars from a file and writing them to a new file, but I don't know how to move bits in a char.
For example, here would be our file with chars:
▼ ▼
! // 00100001
" // 00100010
# // 00100011
$ // 00100100
And this would be our new file with changed chars (2nd bit goes to 7th position):
▼ ▼
! // 00100001
b // 01100010
c // 01100011
$ // 00100100
How to move that bit in a char in TASM?
Edit:
This is not a duplicate question to How to change bits in a char in TASM? because I need to detect if the desired bit is 0 or 1, necessary to know what to use, OR or AND, then set the proper bit in 1 and the rest in 0, or the proper bit in 0 and the rest in 1, then execute the OR or AND. That's a bit different question.
The most straightforward literal rewrite of English sentence "copy 2nd bit into 7th bit" into 8086 Assembly I can think of:
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
About bitmask constant calculation:
When you have some binary value like 1010 1001
= mask of 8 bits, when used by AND
, it will keep original values everywhere where "1" are set in mask, and it will clear the bits where "0" is.
That should be easy to imagine, if you know which bit you want to manipulate by AND/OR/XOR/TEST
instruction, like "obvious".
But you don't want to type such long binary number into assembler (plus if you use some obsolete one, it will not even compile it for you)... So write it instead in hexa 0A9h
. It's just as "obvious" as binary one, just every 4 bits form single hexadecimal digit, so 1010
is 8+2 = 10 = Ah
(write "0A" into editor, leading 0 to tell assembler that the "A" belongs to number, not to label) and 1001
is 8+1 = 9
, write "9" into editor, then add "h" to mark it hexa value, done.
How Matt managed to get decimal 191
(= 0xBF = 0b10111111
) - I don't know, probably he used calculator or he did 255-64 in head (full mask minus single bit). While I can write the BF
hexadecimal form on fly just by imagining the bit pattern in head.
Also read this, the wiki article is IMO quite good: https://en.wikipedia.org/wiki/Bitwise_operation