Self-Complementing Codes (Excess 3, 84-2-1, 2*421) - bcd

I'm having a topic here which is from "Number Systems" in the subject of "Introduction to Computer Organisation & Architecture"
Then i came across this topic,"Self complementing Codes"
There are 3 parts of it which are as follows:
i)Excess-3 (I understand this part as it requires us to add 3 to BCD)
ii)84-2-1 (I don't understand)
iii)2*421 (I don't understand)
I hope someone could explain how the part ii & iii works.
Thanks alot.

I think this part of "Digital Design" book from Morris Mano will answer your question:
BCD and the 2421 code are examples of weighted codes. In a weighted code, each bit
position is assigned a weighting factor in such a way that each digit can be evaluated by
adding the weights of all the 1’s in the coded combination.
Four Different Binary Codes for the Decimal Digits
_____________________________________________________________
Decimal BCD 2421 Excess‐3 8, 4, -2, -1
Digit 8421
_____________________________________________________________
0 0000 0000 0011 0000
1 0001 0001 0100 0111
2 0010 0010 0101 0110
3 0011 0011 0110 0101
4 0100 0100 0111 0100
5 0101 1011 1000 1011
6 0110 1100 1001 1010
7 0111 1101 1010 1001
8 1000 1110 1011 1000
9 1001 1111 1100 1111
_____________________________________________________________
1010 0101 0000 0001
Unused 1011 0110 0001 0010
bit 1100 0111 0010 0011
combi- 1101 1000 1101 1100
nations 1110 1001 1110 1101
1111 1010 1111 1110
The 2421, the excess‐3 and the 84-2-1 codes are examples of self‐complementing codes. Such
codes have the property that the 9’s complement of a decimal number is obtained
directly by changing 1’s to 0’s and 0’s to 1’s (i.e., by complementing each bit in the pattern). For example, decimal 395 is represented in the excess‐3 code as 0110 1100 1000.
The 9’s complement of 604 is represented as 1001 0011 0111, which is obtained simply
by complementing each bit of the code (as with the 1’s complement of binary numbers).
Digital Design-Fifth edition-By Morris Mano

First of all 84-2-1 & 2421 code are "weighted code" and as well as "self-complementing code" both (because the necessary condition for a code to be self-complementing is that the sum of all of its weight must be equal to 9) i.e. 84-2-1(8+4-2-1=9) and, 2421(2+4+2+1=9).
So, constructing binary equivalent of decimal of number you to need to make sure one thing:
The number's code and its 9's complement's code should have complementary relationship (i.e. the number & its 9's complement code are complements of each other)
For example let's take a 84-2-1 System.
Decimal 0=0000(in 84-2-1 system) & (9's complement of 0=9) than 9(in 84-2-1) should have 1111. Hence 0 & its 9's complement i.e. 9 maintain their self-complement relationship.
Let's take another example:
Decimal 1=0111(in 84-2-1 system) & (9's complement of 1=8 ) that implies (84-2-1) equivalent of 8 should be 1000,hence again the number & its complement preserve their self-complementary relationship.
Similarly, as in 2421 system, all you need to construct the code by making sure that the number and its 9's complement should have maintained their self-complementing relationship.

Related

elf aarch64 golfed with sys_write

To better understand the ELF format and the ARM aarch64, I'm trying to create my elf binary without compilers, just echoing bytes with bash.
Will can see my effort here: http://www.github.com/glaudiston/elf
I have succeeded in achieving a fully working elf with sys_write and sys_exit syscalls for x64.
But for aarch64, it's not working as I expect it to:
# cat make-elf.sh
#!/bin/bash
#
# depends on:
# - elf_fn.sh (github.com/glaudiston/elf)
# - base64 (gnu-coreutils)
#
. elf_fn.sh
instructions="";
instructions="${instructions}\nwrite $(echo -en "hello world\n" | base64 -w0)";
instructions="${instructions}\nexit 3";
write_elf elf "${instructions}";
It generates:
$ xxd elf
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0200 b700 0100 0000 7800 0100 0000 0000 ........x.......
00000020: 4000 0000 0000 0000 0000 0000 0000 0000 #...............
00000030: 0000 0000 4000 3800 0100 0000 0000 0000 ....#.8.........
00000040: 0100 0000 0500 0000 0000 0000 0000 0000 ................
00000050: 0000 0100 0000 0000 0000 0000 0000 0000 ................
00000060: 7800 0000 0000 0000 7800 0000 0000 0000 x.......x.......
00000070: 0000 0000 0000 0000 2000 80d2 010c 0058 ........ ......X
00000080: 8201 80d2 0808 80d2 0100 00d4 6000 80d2 ............`...
00000090: a80b 80d2 0100 00d4 6865 6c6c 6f20 776f ........hello wo
000000a0: 726c 640a
$ ./make-elf.sh 0 && ./elf; echo $?
3
$ cat elf | base64 -w0; echo
f0VMRgIBAQAAAAAAAAAAAAIAtwABAAAAeAABAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAeAAAAAAAAAB4AAAAAAAAAAAAAAAAAAAAIACA0gEMAFiCAYDSCAiA0gEAANRgAIDSqAuA0gEAANRoZWxsbyB3b3JsZAo=
It returns the expected exit code, with no illegal exceptions, but the sys_write call is not printing anything.
Hiding all ELF overhead, we have this:
00000078: 2000 80d2 010c 0058 ......X
00000080: 8201 80d2 0808 80d2 0100 00d4 6000 80d2 ............`...
00000090: a80b 80d2 0100 00d4 6865 6c6c 6f20 776f ........hello wo
000000a0: 726c 640a rld.
The exit call is working as expected, so I can hide it too:
00000078: 2000 80d2 010c 0058 ......X
00000080: 8201 80d2 0808 80d2 0100 00d4 ............
00000090: 6865 6c6c 6f20 776f hello wo
000000a0: 726c 640a rld.
So we have the data hello world.\n starting at position 98. I am very confused about how to do the sys_write call here. In x64 I can set to the next data address that in this case should be 65688(composed of PH_VADDR_V(65536) + ELF_HEADER_SIZE(64) + ELF_BODY_SIZE(32) (without DATA_SECTION)")
To the output fd I do set in r0 the value 1 with 2000 80d2
To the data address I am using 010c that is little endian representation of 0c01 this bits: 00001100000 00001 The last 5 bits are the r1 register, used to data address.
Given I only have 11 bits
Here I've used the LDR (0058) but I've tried MOV (here 80d2) too. With no success
I've tried any value from 0 to 2048 where it starts to reports Illegal instruction and exit code 132.
I think maybe aarch64 does not allow the same trick I've used in x64 to print data without a labeled data section. I'll work on creating it, but this is just a guess and I really want to understand why this is not printing nothing.
So, your string is at absolute address 0x10098 and you need to get this address into the x1 register.
First of all, LDR is not what you want. It is, as the name suggests, a load (read) from memory. You don't want your instruction to access memory at all, it just wants to put the value 0x10098 into the register.
MOV is closer, which writes an immediate value into the register, but the problem is that the immediate is limited to 16 bits, and you need 17. Because instructions are 32 bits, there are only so many bits available for an immediate. My guess is that you overflowed this and ended up changing opcode bits instead, so you encoded a totally different instruction. (Don't guess at encodings! Look them up. This would have shown you the 16-bit limit.)
For getting arbitrary immediate values into a register, the intended approach is a sequence of MOV/MOVK instructions to write 16 bits at a time. Here you would just need two of them:
0: d2801301 mov x1, #0x98 // #152
4: f2a00021 movk x1, #0x1, lsl #16
Though since we are using a extra word, the address of the string will also shift, so you'd have to adjust accordingly.
However, for addresses in particular, AArch64 provides pc-relative address generation instructions, ADR/ADRP. These let you add an immediate value to the current value of the program counter (i.e. the address of the currently executing instruction) and write the result to a register. As a bonus, they allot more bits for the immediate (though you will no longer need them).
Here we can use ADR. Its opcode is 0 at bit 31, and 10000 at bits 24-28. The destination register is bits 0-4, we want 00001. The immediate gets its low two bits at bits 29-30, and the higher bits at 5-23. The ADR instruction will be at absolute address 0x1007c and we want 0x10098, so the displacement is 0x1c = 0b11100. Thus the encoding we want is
0 00 10000 0000000000000000111 00001 = 0x100000e1
Some general tips:
Try writing code with an assembler first, so that you can learn the instruction set and be able to focus on experimenting with what the instructions do, instead of also getting bogged down in how they are encoded. If you want to come back and do the encoding by hand later, fine, but with an assembler you'll also have a way to check your work.
Use a debugger to single-step your program. That would have showed you that your LDR was giving you a totally bogus value and might have been a hint that it didn't do what you think it did.
Use strace to see what system calls your program makes. That would show you (I think, I didn't test) that write does get invoked but with the wrong address.

bit representation in python

Hi I have a question about the bit representation in python
when I use bit operation 1<<31, then we can see the bits are
1000 0000 0000 0000 0000 0000 0000 0000
python will print this value as 2147483648
but when I give a variable value like a = -2**31
the bits are also
1000 0000 0000 0000 0000 0000 0000 0000
but python will print -2147483648
so if the bits are the same , how python decide to use 2147483648 or -2147483648 ?
In python integers do not have a limited precision. Which means among other things, that the numbers are not stored in twos compliment binary. The sign is NOT stored in the bit representation of the number.
So all of -2**31, 2**31 and 1<<31 will have the same bit representation for the number. The sign part of the -2**31 is not part of the bitwise representation of the number. The sign is separate.
You can see this if you try this:
>>> bin(5)
'0b101'
>>> bin(-5)
'-0b101'
The representation isn't really the same. You can use int.to_bytes to check it:
(1 << 31).to_bytes(32, 'big', signed=True)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00'
(-2 ** 31).to_bytes(32, 'big', signed=True)
b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00'
Also, be careful about the - operator, which have the lower priority here:
-2 ** 31 == -(2 ** 31)

n-th bit of the binary representation

I have a problem that asks
"find the K-th bit of the binary representation of an integer N"
where 0 <= K <= 31.
The answer states that when N=1 K=0 , the k-th bit is 1
and also
when N=2 K=1 , the k-th bit is 1 as well. How is this so?
The little endian binary representation of 1 is 0000 0000 0000 0001 and the little endian binary representation of 2 is 0000 0000 0000 0010.

Retrieve greatest value of a field, for a range of cells specified dynamically by another cell

The following is a rough analogy of the data I have to work with:
|SKU| |Master SKU| |Weight|
0000
0001 0000 5.6
0002 0000 2
0003 0000 4
0004
0005 0004 1
0006 0004 3
0007 0004 0.5
In a new column called Master's Greatest Weight; I need a formula that, for each row that has no Master SKU, returns the greatest weight of each row that has a match for it's own SKU in the Master SKU field.
To put it simply, this is the desired result:
|SKU| |Master SKU| |Weight| |Master's Greatest Weight|
0000 5.6
0001 0000 5.6
0002 0000 2
0003 0000 4
0004 3
0005 0004 1
0006 0004 3
0007 0004 0.5
I have a feeling that this Filter an array using a formula (without VBA) question is relevant, but if it is I'm not sure how to adapt it to what I want to achieve.
Please try in SKU 0000 row (assumed to be Row2) and copied down:
=IF(B2<>"","",MAX(IF(B:B=A2,C:C)))
with Ctrl+Shift+Enter.

Why is BCD = Decimal in PLC?

This question is derived from my previous SO question's commends.
I am confused with PLC's interpretation of BCD and decimal.
In a PLC documentation, it somehow implies BCD = decimal:
The instruction reads the content of D300, 0100, as BCD. Referring to Cyber Slueth Omega's answer and online BCD-Hex converter, 0100 (BCD) = 4 (Decimal) = 4 (Hex), but the documentation indicates 0100 (BCD) = 100 (Decimal).
Why?
BCD is HEX
BCD is not binary
HEX is not binary
BCD and HEX are representations of binary information.
The only difference is in how you decide to interpret the numbers. Some PLC instructions will take a piece of word memory and will tell you that "I, the TIM instruction, promise to treat the raw data in D300 as BCD data". It is still HEX data, but it interprets it differently.
If D300 = [x2486] --> the timer (as example) will wait 248.6 seconds. This even though HEX 2486 = 9350 decimal. You can treat hex data as anything. If you treat hex data as encoded BCD you get one answer. If you treat it as a plain unsigned binary number you get another, etc.
If D300 = [x1A3D] --> TIM will throw an error flag because D300 contains non-BCD hex digits
Further, the above example is showing HEX digits - not BINARY digits. It is confusing because they chose [x0100] as their example - only zeroes and ones. When you are plugging this into your online converter you are doing it wrong - you are converting binary 0100 to decimal 4. Hexadecimal is not binary - hex is a base16 representation of binary.
Anatomy of a D-memory location is this
16 Bits | xxxx | xxxx | xxxx | xxxx | /BINARY/
---> | | | |
4 bits/digit D4 D3 D2 D1 /HEX/
example
D300 = 1234 | 0001 | 0010 | 0011 | 0100 |
----> 1 2 3 4
example
D300 = 2F6B | 0010 | 1111 | 0110 | 1011 |
----> 2 F 6 B
example (OP!)
D300 = 0100 | 0000 | 0001 | 0000 | 0000 |
----> 0 1 0 0
A D-memory location can store values from x0000 -> xFFFF (decimal 0-65535). A D-memory location which is used to store BCD values, however, can only use decimal digits. A->F are not allowed. This reduces the range of a 16-bit memory location to 0000->9999.
Counting up you would go :
Decimal BCD HEX
1 0001 0001
2 0002 0002
3 0003 0003
4 0004 0004
5 0005 0005
6 0006 0006
7 0007 0007
8 0008 0008
9 0009 0009
10 0010 000A
11 0011 000B
12 0012 000C
13 0013 000D
14 0014 000E
15 0015 000F
16 0016 0010
17 0017 0011
18 0018 0012
19 0019 0013
20 0020 0014
...etc
Going the other way, if you wish to pass a decimal value to a memory location and have it stored as pure hex (not BCD hex!) you use the '&' symbol.
For example -> [MOV #123 D300]
This moves HEX value x0123 to memory location D300. If you use D300 in a future operation which interprets this as a hexadecimal number then it will have a decimal value of 291. If you use it in an instruction which interprets it as a BCD value then it will have a decimal value of 123.
If instead you do [MOV &123 D300]
This moves the decimal value 123 to D300 and stores it as a hexadecimal number -> [x007B]! If you use D300 now in a future operation which interprets this as a hexadecimal number it will have a decimal value of 123. If you try to use it in an instruction which interprets it as a BCD value you will get an ERROR because [x007B] contains the hex digit 'B' which is not a valid BCD digit.
Binary-coded decimal is encoded as hex digits that have a limited range of 0-9. This means that 0x0100 should be read as 100 when BCD is meant. Numbers with hexadecimal digits from A to F are not valid BCD numbers.

Resources